60 KiB
🎨 طرح نوسازی رابط کاربری فرانتآفیس + سیستم بلاگ
تاریخ شروع: تیر ۱۴۰۴
آخرین بروزرسانی: بهمن ۱۴۰۴
وضعیت: فازهای ۱ تا ۶ تکمیل ✅ — فاز ۷ در حال اجرا
اولویت: بالا
فهرست مطالب
- خلاصه اجرایی
- وضعیت فعلی
- اهداف پروژه
- معماری فنی
- فاز ۱ — موجودیتهای بکند (CMS)
- فاز ۲ — پنل مدیریت بلاگ (BackOffice)
- فاز ۳ — صفحات محتوای دینامیک (درباره ما / تماس با ما)
- فاز ۴ — نوسازی لندینگ پیج
- فاز ۵ — صفحات بلاگ فرانتآفیس
- فاز ۶ — بهبود داشبورد کاربر
- فاز ۷ — بهینهسازی موبایل
- فایلهای تغییریافته (نقشه فایلها)
- جدول زمانی
- ریسکها و وابستگیها
1. خلاصه اجرایی
این سند طرح جامع نوسازی رابط کاربری فرانتآفیس (سمت مشتری) و ایجاد سیستم بلاگ/مدیریت محتوا را شامل میشود. اهداف اصلی:
- ✅ ایجاد سیستم بلاگ با قابلیت انتشار مقالات، مجوزها، گواهینامهها با تصاویر
- ✅ صفحات دینامیک درباره ما و تماس با ما (قابل مدیریت از پنل ادمین)
- ✅ نوسازی لندینگ پیج با طراحی حرفهای و حس زنده بودن سامانه
- ✅ صفحات بلاگ فرانتآفیس — لیست مقالات با جستجو/فیلتر + صفحه جزئیات مقاله
- ✅ بهبود داشبورد کاربر با طراحی مدرن و اطلاعات پویا
- 🔄 طراحی Mobile-First (اولویت موبایل) — فاز ۷
- ⛔ بدون تغییر UI سمت ادمین (فقط افزودن صفحات مدیریت بلاگ/محتوا)
2. وضعیت فعلی
2.1 پشته فنی
| لایه | تکنولوژی |
|---|---|
| FrontOffice | Blazor Server (.NET 9) + MudBlazor 8.14.0 |
| BackOffice | Blazor WebAssembly (.NET 9) + MudBlazor 8.14.0 |
| CMS (Backend) | .NET 9 gRPC + MediatR CQRS + EF Core |
| دیتابیس | SQL Server |
| فایلها | FMS (File Management Service) via gRPC |
| زبان UI | فارسی (RTL) + فونت Vazir |
| تم | Light/Dark toggle |
2.2 صفحات فعلی فرانتآفیس
| صفحه | مسیر | وضعیت |
|---|---|---|
| لندینگ | / |
✅ Hero گرادیان + Features + Timeline + Stats + بلاگ + Testimonials + FAQ + CTA |
| درباره ما | /about |
✅ محتوای دینامیک از CMS (با fallback) |
| تماس با ما | /contact |
✅ محتوای دینامیک از CMS + فرم تماس |
| بلاگ | /blog |
✅ لیست مقالات + جستجو + فیلتر دستهبندی + صفحهبندی |
| مقاله | /blog/{slug} |
✅ صفحه جزئیات مقاله + breadcrumb + تگها + شمارنده بازدید |
| سوالات متداول | /faq |
✅ فعال |
| پروفایل | /profile/* |
✅ ۱۰ صفحه (هدر گرادیانی + والتکارتها + تایلهای مدرن) |
| فروشگاه | /products/* |
✅ ۸ صفحه (محصولات، سبد، سفارشات، ...) |
| باشگاه | /club/* |
✅ ۲ صفحه |
| کمیسیون | /commission/* |
✅ ۳ صفحه |
| شبکه | /network/* |
✅ ۲ صفحه |
| پکیج | /packages/* |
✅ ۴ صفحه |
2.3 مشکلات فعلی (رفع شده ✅)
احساس ایستا بودن — لندینگ پیج بدون انیمیشن و محتوای پویا→ ✅ فاز ۴ حل شدبدون بلاگ — امکان انتشار مقاله/خبر/مجوز وجود ندارد→ ✅ فازهای ۱، ۲، ۵ حل شدصفحات استاتیک — درباره ما و تماس با ما هاردکد هستند→ ✅ فاز ۳ حل شدطراحی ساده — فاقد عناصر بصری جذاب→ ✅ فازهای ۴ و ۶ حل شد- موبایلمحور نبودن — ریسپانسیو هست اما اولویت با دسکتاپ → 🔄 فاز ۷
3. اهداف پروژه
3.1 اهداف عملیاتی
| هدف | شاخص موفقیت |
|---|---|
| سیستم بلاگ | ادمین بتواند مقاله بنویسد، دستهبندی کند، تصویر آپلود کند، منتشر/آرشیو کند |
| محتوای دینامیک | ادمین بتواند درباره ما و تماس با ما را از پنل ویرایش کند |
| لندینگ حرفهای | اولین بازدید حس «پلتفرم زنده و فعال» بدهد |
| Mobile-First | تمام صفحات در موبایل عالی نمایش داده شوند |
| عملکرد | زمان بارگذاری صفحه اول < ۳ ثانیه |
3.2 محدوده (Scope)
✅ در محدوده:
- سیستم بلاگ کامل (CMS → BackOffice → FrontOffice)
- صفحات محتوای دینامیک (About, Contact)
- نوسازی لندینگ پیج
- بهبود داشبورد/پروفایل
- بهینهسازی موبایل
- افزودن صفحات مدیریت بلاگ به BackOffice
⛔ خارج از محدوده:
- تغییرات UI سایر بخشهای BackOffice
- سیستم کامنتگذاری (فاز بعدی)
- سیستم جستجوی پیشرفته (فاز بعدی)
- اپلیکیشن موبایل (PWA یا Native)
4. معماری فنی
4.1 جریان داده بلاگ
┌──────────────┐ gRPC ┌───────────┐ EF Core ┌──────────┐
│ BackOffice │ ──────────► │ CMS │ ────────────► │ SQL Server│
│ (Admin CRUD) │ ◄────────── │ (gRPC) │ ◄──────────── │ │
└──────────────┘ └───────────┘ └──────────┘
│ ▲
gRPC │ │
▼ │
┌──────────────┐
│ FrontOffice │
│ (مشاهده بلاگ)│
└──────────────┘
│
FMS │ (آپلود تصاویر)
▼
┌──────────┐
│ FMS │
│ (فایلها) │
└──────────┘
4.2 موجودیتهای جدید (Entity Relationship)
BlogPost (1) ──────── (N) BlogPostCategory ──────── (1) BlogCategory
│
│ (1:N)
▼
BlogPostImage
BlogPost.Tags → از Tag موجود استفاده میشود (BlogPostTag join table)
SitePage → صفحات دینامیک (About, Contact, Custom)
│
│ (1:N)
▼
SitePageSection → بخشهای هر صفحه
4.3 الگوی CQRS موجود (برای مرجع)
Proto (gRPC Definition)
↓
WebApi/Services/{Feature}Service.cs (extends generated gRPC base)
↓ Mapster (Proto → Command/Query)
Application/{Feature}CQ/Commands/ or Queries/
↓ MediatR
Handler → Repository (DbContext)
↓
Domain/Entities/{Entity}.cs
5. فاز ۱ — موجودیتهای بکند (CMS) ✅ تکمیل شد
وضعیت: ✅ تکمیل | اولویت: بالا | پیشنیاز: ندارد
5.1 موجودیتهای جدید Domain
BlogPost.cs
Location: CMS/src/CMSMicroservice.Domain/Entities/Blog/BlogPost.cs
Base: BaseAuditableEntity
Properties:
- string Title (required, max 200)
- string Slug (required, unique, max 200)
- string Summary (max 500) — خلاصه برای کارتها
- string HtmlContent (required) — محتوای HTML کامل
- string? FeaturedImagePath — تصویر شاخص
- string? FeaturedImageThumbnailPath — تامبنیل تصویر شاخص
- BlogPostStatus Status (enum: Draft, Published, Scheduled, Archived)
- DateTime? PublishedAt — زمان انتشار
- DateTime? ScheduledPublishAt — زمانبندی انتشار
- int ViewCount — تعداد بازدید
- long AuthorUserId — نویسنده
- bool IsFeatured — نمایش در صفحه اول
- int SortOrder — ترتیب نمایش
Relations:
- ICollection<BlogPostCategory> BlogPostCategories
- ICollection<BlogPostTag> BlogPostTags
- ICollection<BlogPostImage> BlogPostImages
BlogCategory.cs
Location: CMS/src/CMSMicroservice.Domain/Entities/Blog/BlogCategory.cs
Base: BaseAuditableEntity
Properties:
- string Title (required, max 100)
- string Slug (required, unique, max 100)
- string? Description (max 500)
- string? IconName — آیکون Material
- int SortOrder
- bool IsActive
Relations:
- ICollection<BlogPostCategory> BlogPostCategories
BlogPostCategory.cs (Join Table)
Location: CMS/src/CMSMicroservice.Domain/Entities/Blog/BlogPostCategory.cs
Base: BaseEntity
Properties:
- long BlogPostId
- long BlogCategoryId
Relations:
- BlogPost BlogPost
- BlogCategory BlogCategory
BlogPostTag.cs (Join Table)
Location: CMS/src/CMSMicroservice.Domain/Entities/Blog/BlogPostTag.cs
Base: BaseEntity
Properties:
- long BlogPostId
- long TagId
Relations:
- BlogPost BlogPost
- Tag Tag (موجود — استفاده مجدد)
BlogPostImage.cs
Location: CMS/src/CMSMicroservice.Domain/Entities/Blog/BlogPostImage.cs
Base: BaseAuditableEntity
Properties:
- long BlogPostId
- string ImagePath
- string ThumbnailPath
- string? AltText (max 200)
- string? Caption (max 300)
- int SortOrder
Relations:
- BlogPost BlogPost
SitePage.cs (صفحات دینامیک)
Location: CMS/src/CMSMicroservice.Domain/Entities/Content/SitePage.cs
Base: BaseAuditableEntity
Properties:
- string PageKey (unique, e.g. "about", "contact") — کلید شناسایی
- string Title (max 200)
- string? MetaDescription (max 300) — SEO
- string? HeroTitle — عنوان Hero
- string? HeroSubtitle — زیرعنوان Hero
- string? HeroImagePath — تصویر Hero
- bool IsActive
Relations:
- ICollection<SitePageSection> Sections
SitePageSection.cs (بخشهای صفحه)
Location: CMS/src/CMSMicroservice.Domain/Entities/Content/SitePageSection.cs
Base: BaseAuditableEntity
Properties:
- long SitePageId
- string SectionKey (e.g. "mission", "vision", "team-member-1")
- string Title (max 200)
- string? Subtitle (max 300)
- string? HtmlContent — محتوای HTML
- string? IconName — آیکون Material
- string? ImagePath
- string? ImageThumbnailPath
- int SortOrder
- bool IsActive
- string? ExtraData — JSON blob for flexible data
Relations:
- SitePage SitePage
Enum: BlogPostStatus.cs
Location: CMS/src/CMSMicroservice.Domain/Enums/BlogPostStatus.cs
Values:
Draft = 0
Published = 1
Scheduled = 2
Archived = 3
5.2 Entity Configurations (Infrastructure)
فایلهای جدید:
CMS/src/CMSMicroservice.Infrastructure/Configurations/Blog/
├── BlogPostConfiguration.cs
├── BlogCategoryConfiguration.cs
├── BlogPostCategoryConfiguration.cs
├── BlogPostTagConfiguration.cs
└── BlogPostImageConfiguration.cs
CMS/src/CMSMicroservice.Infrastructure/Configurations/Content/
├── SitePageConfiguration.cs
└── SitePageSectionConfiguration.cs
فایلهای ویرایشی:
CMS/src/CMSMicroservice.Infrastructure/ApplicationDbContext.cs
+ DbSet<BlogPost> BlogPosts
+ DbSet<BlogCategory> BlogCategories
+ DbSet<BlogPostCategory> BlogPostCategories
+ DbSet<BlogPostTag> BlogPostTags
+ DbSet<BlogPostImage> BlogPostImages
+ DbSet<SitePage> SitePages
+ DbSet<SitePageSection> SitePageSections
5.3 Proto Definitions
blogpost.proto
Location: CMS/src/CMSMicroservice.Protobuf/Protos/blogpost.proto
service BlogPostContract {
rpc CreateBlogPost (CreateBlogPostRequest) returns (BlogPostResponse);
rpc UpdateBlogPost (UpdateBlogPostRequest) returns (BlogPostResponse);
rpc DeleteBlogPost (DeleteBlogPostRequest) returns (BoolResponse);
rpc GetBlogPost (GetBlogPostRequest) returns (BlogPostResponse);
rpc GetBlogPostBySlug (GetBlogPostBySlugRequest) returns (BlogPostResponse);
rpc GetAllBlogPosts (GetAllBlogPostsRequest) returns (BlogPostListResponse);
rpc GetPublishedBlogPosts (GetPublishedBlogPostsRequest) returns (BlogPostListResponse);
rpc GetFeaturedBlogPosts (GetFeaturedBlogPostsRequest) returns (BlogPostListResponse);
rpc PublishBlogPost (PublishBlogPostRequest) returns (BoolResponse);
rpc ArchiveBlogPost (ArchiveBlogPostRequest) returns (BoolResponse);
rpc IncrementViewCount (IncrementViewCountRequest) returns (BoolResponse);
}
blogcategory.proto
Location: CMS/src/CMSMicroservice.Protobuf/Protos/blogcategory.proto
service BlogCategoryContract {
rpc CreateBlogCategory (CreateBlogCategoryRequest) returns (BlogCategoryResponse);
rpc UpdateBlogCategory (UpdateBlogCategoryRequest) returns (BlogCategoryResponse);
rpc DeleteBlogCategory (DeleteBlogCategoryRequest) returns (BoolResponse);
rpc GetBlogCategory (GetBlogCategoryRequest) returns (BlogCategoryResponse);
rpc GetAllBlogCategories (GetAllBlogCategoriesRequest) returns (BlogCategoryListResponse);
}
blogpostimage.proto
Location: CMS/src/CMSMicroservice.Protobuf/Protos/blogpostimage.proto
service BlogPostImageContract {
rpc AddBlogPostImage (AddBlogPostImageRequest) returns (BlogPostImageResponse);
rpc DeleteBlogPostImage (DeleteBlogPostImageRequest) returns (BoolResponse);
rpc GetBlogPostImages (GetBlogPostImagesRequest) returns (BlogPostImageListResponse);
rpc ReorderBlogPostImages (ReorderBlogPostImagesRequest) returns (BoolResponse);
}
sitepage.proto
Location: CMS/src/CMSMicroservice.Protobuf/Protos/sitepage.proto
service SitePageContract {
rpc GetSitePage (GetSitePageRequest) returns (SitePageResponse);
rpc GetSitePageByKey (GetSitePageByKeyRequest) returns (SitePageResponse);
rpc UpdateSitePage (UpdateSitePageRequest) returns (SitePageResponse);
rpc GetAllSitePages (GetAllSitePagesRequest) returns (SitePageListResponse);
rpc CreateSitePageSection (CreateSitePageSectionRequest) returns (SitePageSectionResponse);
rpc UpdateSitePageSection (UpdateSitePageSectionRequest) returns (SitePageSectionResponse);
rpc DeleteSitePageSection (DeleteSitePageSectionRequest) returns (BoolResponse);
rpc ReorderSitePageSections (ReorderSitePageSectionsRequest) returns (BoolResponse);
}
5.4 Application Layer (CQRS)
CMS/src/CMSMicroservice.Application/
BlogPostCQ/
Commands/
CreateBlogPost/
CreateBlogPostCommand.cs
CreateBlogPostCommandHandler.cs
CreateBlogPostCommandValidator.cs
UpdateBlogPost/
UpdateBlogPostCommand.cs
UpdateBlogPostCommandHandler.cs
UpdateBlogPostCommandValidator.cs
DeleteBlogPost/
DeleteBlogPostCommand.cs
DeleteBlogPostCommandHandler.cs
PublishBlogPost/
PublishBlogPostCommand.cs
PublishBlogPostCommandHandler.cs
ArchiveBlogPost/
ArchiveBlogPostCommand.cs
ArchiveBlogPostCommandHandler.cs
Queries/
GetBlogPost/
GetBlogPostQuery.cs
GetBlogPostQueryHandler.cs
GetBlogPostBySlug/
GetBlogPostBySlugQuery.cs
GetBlogPostBySlugQueryHandler.cs
GetAllBlogPosts/
GetAllBlogPostsQuery.cs
GetAllBlogPostsQueryHandler.cs
GetPublishedBlogPosts/
GetPublishedBlogPostsQuery.cs
GetPublishedBlogPostsQueryHandler.cs
GetFeaturedBlogPosts/
GetFeaturedBlogPostsQuery.cs
GetFeaturedBlogPostsQueryHandler.cs
BlogCategoryCQ/
Commands/
CreateBlogCategory/ (3 files)
UpdateBlogCategory/ (3 files)
DeleteBlogCategory/ (2 files)
Queries/
GetBlogCategory/ (2 files)
GetAllBlogCategories/ (2 files)
BlogPostImageCQ/
Commands/
AddBlogPostImage/ (3 files)
DeleteBlogPostImage/ (2 files)
ReorderBlogPostImages/ (2 files)
Queries/
GetBlogPostImages/ (2 files)
SitePageCQ/
Commands/
UpdateSitePage/ (3 files)
CreateSitePageSection/ (3 files)
UpdateSitePageSection/ (3 files)
DeleteSitePageSection/ (2 files)
ReorderSitePageSections/ (2 files)
Queries/
GetSitePage/ (2 files)
GetSitePageByKey/ (2 files)
GetAllSitePages/ (2 files)
5.5 WebApi Services & Mappings
CMS/src/CMSMicroservice.WebApi/
Services/
BlogPostService.cs — extends BlogPostContractBase
BlogCategoryService.cs — extends BlogCategoryContractBase
BlogPostImageService.cs — extends BlogPostImageContractBase
SitePageService.cs — extends SitePageContractBase
Common/Mappings/
BlogPostProfile.cs
BlogCategoryProfile.cs
BlogPostImageProfile.cs
SitePageProfile.cs
5.6 Migration
# ساخت Migration جدید
cd CMS/src/CMSMicroservice.Infrastructure
dotnet ef migrations add AddBlogAndSitePages \
--startup-project ../CMSMicroservice.WebApi \
--context ApplicationDbContext
6. فاز ۲ — پنل مدیریت بلاگ (BackOffice) ✅ تکمیل شد
تخمین: ۲-۳ روز | اولویت: بالا | پیشنیاز: فاز ۱ | وضعیت: تکمیل ✅
6.1 صفحات ایجاد شده BackOffice
BackOffice/src/BackOffice/Pages/
Blog/
BlogPostManagementPage.razor — لیست پستها + فیلتر وضعیت/دستهبندی + جستجو
BlogPostManagementPage.razor.cs — کدبیهایند: LoadServerData، CRUD، Publish، Archive
BlogCategoryManagementPage.razor — مدیریت دستهبندیها (MudDataGrid)
BlogCategoryManagementPage.razor.cs
Components/
BlogPostEditDialog.razor — ایجاد/ویرایش پست (عنوان، اسلاگ، خلاصه، HTML، دستهبندیها)
BlogPostEditDialog.razor.cs — Multi-select دستهبندی + ویژه/ترتیب
BlogCategoryEditDialog.razor — ایجاد/ویرایش دستهبندی
BlogCategoryEditDialog.razor.cs
Content/
SitePageManagementPage.razor — لیست صفحات سایت
SitePageManagementPage.razor.cs — ویرایش صفحه + مدیریت بخشها
Components/
SitePageEditDialog.razor — ویرایش اطلاعات صفحه (Hero, Meta, وضعیت)
SitePageEditDialog.razor.cs
SitePageSectionsDialog.razor — مدیریت بخشهای صفحه (CRUD + لیست)
SitePageSectionsDialog.razor.cs
SitePageSectionEditDialog.razor — ایجاد/ویرایش بخش (کلید، عنوان، HTML، تصاویر)
SitePageSectionEditDialog.razor.cs
6.2 ناوبری BackOffice (NavMenu) ✅
بخش «مدیریت محتوا» به NavMenu.razor اضافه شد (قبل از بخش سیستم):
<MudText Class="nav-menu__title" Typo="Typo.subtitle2">مدیریت محتوا</MudText>
<AuthorizeView Roles="Administrator">
<Authorized>
@if (CanManageBlog)
{
<MudNavGroup Title="بلاگ" Icon="@Icons.Material.Filled.Article" Expanded="false">
<MudNavLink Href="/blog/posts" Icon="@Icons.Material.Filled.PostAdd">پستها</MudNavLink>
<MudNavLink Href="/blog/categories" Icon="@Icons.Material.Filled.Category">دستهبندیها</MudNavLink>
</MudNavGroup>
}
@if (CanManageSitePages)
{
<MudNavLink Href="/content/pages" Icon="@Icons.Material.Filled.WebAsset">صفحات سایت</MudNavLink>
}
</Authorized>
</AuthorizeView>
مجوزهای جدید: blog.manage، sitepages.manage
6.3 سرویسهای BackOffice ✅
BackOffice/src/BackOffice/Services/
Blog/
IBlogCategoryService.cs — اینترفیس + DTOs (Filter, ListResult, Item, Edit)
BlogCategoryService.cs — پیادهسازی با gRPC client (GetAll, GetActive, GetById, Create, Update, Delete)
IBlogPostService.cs — اینترفیس + DTOs (Filter, ListResult, ListItem, Details, Edit, PublishResult, ArchiveResult)
BlogPostService.cs — پیادهسازی (CRUD + Publish + Archive)
IBlogPostImageService.cs — اینترفیس + DTOs (ImageItem, ImageAdd, ImageSort)
BlogPostImageService.cs — پیادهسازی (GetByPostId, Add, Delete, Reorder)
Content/
ISitePageService.cs — اینترفیس + DTOs (Summary, Details, SectionItem, Edit, SectionEdit, SectionSort)
SitePageService.cs — پیادهسازی (GetAll, GetById, Update, CRUD Section, Reorder)
ثبت DI در ConfigureService.cs:
- ۴ gRPC Client:
BlogPostContractClient،BlogCategoryContractClient،BlogPostImageContractClient،SitePageContractClient - ۴ Application Service:
IBlogPostService،IBlogCategoryService،IBlogPostImageService،ISitePageService
6.4 ویرایشگر محتوا
از پکیج موجود Tizzani.MudBlazor.HtmlEditor (قبلاً نصب شده) استفاده میشود:
<!-- در CreateBlogPostDialog -->
<MudHtmlEditor @bind-Value="_post.HtmlContent"
Placeholder="محتوای مقاله را بنویسید..."
MinHeight="400px" />
6.5 آپلود تصویر شاخص
از سرویس موجود IFileManagerService استفاده:
// الگوی موجود از ProductService
var imagePath = await _fileManagerService.UploadFileAsync(imageBytes, fileName);
6.6 مشخصات صفحه مدیریت مقالات
| ویژگی | شرح |
|---|---|
| جدول مقالات | MudDataGrid با ستونهای: عنوان، دستهبندی، وضعیت، تاریخ انتشار، بازدید |
| فیلتر | وضعیت (همه/پیشنویس/منتشر/آرشیو) + جستجوی عنوان |
| عملیات | ایجاد، ویرایش، حذف، انتشار، آرشیو، پیشنمایش |
| تصویر شاخص | Drag & Drop آپلود + پیشنمایش |
| دستهبندی | Multi-select از دستهبندیهای موجود |
| تگ | Multi-select با autocomplete از تگهای موجود |
| ویرایشگر | WYSIWYG HTML editor (MudBlazor.HtmlEditor) |
7. فاز ۳ — صفحات محتوای دینامیک (درباره ما / تماس با ما) ✅ تکمیل شد
وضعیت: ✅ تکمیل | اولویت: متوسط | پیشنیاز: فاز ۱
7.1 تغییرات About.razor
قبل (فعلی): محتوا هاردکد — عنوانها، تصاویر، متون همه در Razor مستقیم نوشته شده
بعد (جدید):
OnInitializedAsync:
1. صدا زدن SitePageContract.GetSitePageByKey("about")
2. دریافت SitePage + Sections
3. نمایش دینامیک با loop روی Sections
Fallback:
- اگر سرویس خطا داد → نمایش محتوای پیشفرض (هاردکد فعلی به عنوان fallback)
ساختار بخشهای صفحه درباره ما:
| SectionKey | نوع | داده |
|---|---|---|
hero |
Hero | HeroTitle, HeroSubtitle, HeroImagePath |
mission |
Card | Title, HtmlContent, IconName |
vision |
Card | Title, HtmlContent, IconName |
value-1 ... value-N |
Cards Grid | Title, Subtitle, IconName, HtmlContent |
team-1 ... team-N |
Team Cards | Title (نام), Subtitle (سمت), HtmlContent (توضیح), ImagePath |
7.2 تغییرات Contact.razor
| SectionKey | نوع | داده |
|---|---|---|
hero |
Hero | HeroTitle, HeroSubtitle |
contact-info |
Info | ExtraData (JSON: address, phone, email, hours) |
social-media |
Links | ExtraData (JSON: telegram, instagram, linkedin, whatsapp urls) |
map |
Map | ExtraData (JSON: lat, lng, address text) |
7.3 Seed Data
اجرای اولیه Migration با داده پیشفرض (محتوای هاردکد فعلی):
// در SitePageConfiguration یا Seed Migration
var aboutPage = new SitePage {
PageKey = "about",
Title = "درباره ما",
HeroTitle = "پلتفرم هوشمند تیمسازی و مدیریت فروش",
HeroSubtitle = "ما با ارائه ابزارهای نوآورانه...",
IsActive = true
};
// + Sections با محتوای فعلی
8. فاز ۴ — نوسازی لندینگ پیج ✅ تکمیل شد
وضعیت: ✅ تکمیل | اولویت: بالا | پیشنیاز: فاز ۱ (بخش بلاگ برای "آخرین مقالات")
8.1 ساختار جدید لندینگ پیج
┌─────────────────────────────────────────┐
│ 🔝 HERO SECTION │
│ • Gradient animated background │
│ • عنوان بزرگ + زیرعنوان │
│ • Badgeهای انیمیشنی │
│ • CTA buttons با hover effects │
│ • تصویر/ایلاستریشن سمت چپ │
│ • اعداد زنده (تعداد کاربران، ...) │
└─────────────────────────────────────────┘
↓ Scroll indicator ↓
┌─────────────────────────────────────────┐
│ ✨ FEATURES (چرا ما؟) │
│ • 6 کارت با آیکون + عنوان + توضیح │
│ • Hover effect (scale + shadow) │
│ • انیمیشن fade-in on scroll │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ 📊 LIVE STATS (آمار زنده) │
│ • Counter animation (شمارش تعداد) │
│ • تعداد کاربران فعال │
│ • تعداد محصولات │
│ • حجم معاملات │
│ • Intersection Observer trigger │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ 🔄 HOW IT WORKS (چطور کار میکند) │
│ • Timeline بهبودیافته │
│ • آیکونهای مرحلهای بزرگتر │
│ • انیمیشن step-by-step │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ 📝 LATEST BLOG (آخرین مقالات) │ ← جدید!
│ • ۳ کارت آخرین مقالات منتشرشده │
│ • تصویر شاخص + عنوان + خلاصه │
│ • دکمه "مشاهده همه مقالات" │
│ • Loading skeleton │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ 🏆 TESTIMONIALS (اعتماد مشتریان) │
│ • Carousel/Swiper اسلایدر │
│ • Avatar + نام + سمت + نقل قول │
│ • Auto-play + دکمههای ناوبری │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ ❓ FAQ (سوالات متداول) │
│ • بدون تغییر اساسی (فقط پولیش) │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ 📞 CTA BANNER (دعوت نهایی) │ ← جدید!
│ • Gradient background │
│ • عنوان جذاب + دکمه ثبتنام │
│ • طرح ساده و تأثیرگذار │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ 🦶 FOOTER │
│ • بدون تغییر اساسی + لینک بلاگ │
└─────────────────────────────────────────┘
8.2 تغییرات فنی لندینگ
الف) Hero Section بهبودیافته
تغییرات:
1. Animated gradient background (CSS keyframes)
2. اعداد واقعی از API (تعداد کاربران، محصولات، ...)
3. Badgeها با انیمیشن pulse
4. Scroll-down indicator (chevron انیمیشنی)
5. تصویر/SVG illustration سمت چپ
ب) آمار زنده (Live Stats)
سرویس جدید — یک Query ساده در CMS:
GetPlatformStats → { UserCount, ProductCount, OrderCount, ... }
فرانت:
- Counter animation (JS interop یا CSS counter)
- Intersection Observer: فقط وقتی اسکرول به این بخش رسید شمارش شروع شود
ج) بخش آخرین مقالات (جدید)
<!-- Latest Blog Posts Section -->
<section class="py-16">
<MudContainer MaxWidth="MaxWidth.Large">
<MudText Typo="Typo.h4" Align="Align.Center">آخرین مقالات</MudText>
<MudGrid Spacing="4">
@foreach (var post in _latestPosts.Take(3))
{
<MudItem xs="12" md="4">
<BlogPostCard Post="post" />
</MudItem>
}
</MudGrid>
<MudButton Href="/blog" Variant="Variant.Outlined">مشاهده همه</MudButton>
</MudContainer>
</section>
د) CTA Banner نهایی (جدید)
<!-- Final CTA -->
<section class="cta-banner py-16">
<MudContainer MaxWidth="MaxWidth.Medium">
<MudStack AlignItems="AlignItems.Center" Spacing="4">
<MudText Typo="Typo.h3">آماده شروع هستید؟</MudText>
<MudText>همین الان ثبتنام کنید و از مزایای کارا بازار سلامت بهرهمند شوید.</MudText>
<MudButton Variant="Variant.Filled" Color="Color.Primary" Size="Size.Large">
شروع رایگان
</MudButton>
</MudStack>
</MudContainer>
</section>
8.3 CSS جدید / بهبودیافته
/* فایل: wwwroot/css/app.css — بخشهای جدید */
/* Animated gradient hero */
.hero-section {
background: linear-gradient(-45deg, #6366f1, #8b5cf6, #a855f7, #6366f1);
background-size: 400% 400%;
animation: gradientShift 8s ease infinite;
}
@keyframes gradientShift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
/* Scroll-triggered fade-in */
.fade-in-up {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.6s ease, transform 0.6s ease;
}
.fade-in-up.visible {
opacity: 1;
transform: translateY(0);
}
/* Counter animation */
@property --num {
syntax: '<integer>';
initial-value: 0;
inherits: false;
}
.counter {
animation: counter 2s ease-out forwards;
counter-reset: num var(--num);
}
/* Pulse badge */
.pulse-badge {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(99,102,241,0.4); }
70% { box-shadow: 0 0 0 10px rgba(99,102,241,0); }
100% { box-shadow: 0 0 0 0 rgba(99,102,241,0); }
}
/* CTA Banner */
.cta-banner {
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
color: white;
border-radius: 24px;
margin: 2rem;
}
/* Card hover effects */
.feature-card-v2 {
transition: transform 0.3s, box-shadow 0.3s;
}
.feature-card-v2:hover {
transform: translateY(-8px);
box-shadow: 0 12px 40px rgba(0,0,0,0.12);
}
/* Blog post card */
.blog-card {
transition: transform 0.3s ease;
overflow: hidden;
}
.blog-card:hover {
transform: translateY(-4px);
}
.blog-card .blog-card-image {
transition: transform 0.5s ease;
}
.blog-card:hover .blog-card-image {
transform: scale(1.05);
}
8.4 JS Interop (حداقل)
// فایل: wwwroot/js/landing.js
// Intersection Observer for fade-in animations
window.initScrollAnimations = () => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.fade-in-up').forEach(el => observer.observe(el));
};
// Counter animation
window.animateCounter = (elementId, target, duration) => {
const el = document.getElementById(elementId);
if (!el) return;
let start = 0;
const step = target / (duration / 16);
const timer = setInterval(() => {
start += step;
if (start >= target) { start = target; clearInterval(timer); }
el.textContent = Math.floor(start).toLocaleString('fa-IR');
}, 16);
};
9. فاز ۵ — صفحات بلاگ فرانتآفیس ✅ تکمیل شد
وضعیت: ✅ تکمیل | اولویت: بالا | پیشنیاز: فاز ۱
9.1 صفحات ایجاد شده (واقعی)
FrontOffice/src/FrontOffice.Main/Pages/Blog/
Index.razor — لیست مقالات با جستجو + فیلتر دستهبندی + صفحهبندی
Index.razor.cs — LoadPostsAsync، OnCategoryChanged، OnPageChanged، NavigateToPost
Post.razor — صفحه جزئیات مقاله (تصویر شاخص، breadcrumb، HTML، تگها)
Post.razor.cs — OnParametersSetAsync (لود slug)، IncrementViewCount خودکار
9.2 سرویسهای جدید فرانتآفیس
FrontOffice/src/FrontOffice.Main/Utilities/
BlogPostService.cs — (قبلاً فاز ۴ ایجاد شد) GetFeatured, GetPublished, GetBySlug, IncrementView
BlogCategoryService.cs — GetActiveCategoriesAsync (فیلتر سایدبار بلاگ)
DTOs تعریف شده در BlogPostService.cs:
BlogPostCardDto— Id, Title, Slug, Summary, ThumbnailUrl, PublishedAt, ViewCount, IsFeatured, CategoriesBlogPostDetailDto— همه فیلدهای کارت + HtmlContent, FeaturedImagePath, TagsBlogPostListResult— Posts, TotalCount, TotalPages, CurrentPageBlogCategoryInfo— Id, Title, SlugBlogTagInfo— Id, Title, Name
DTO تعریف شده در BlogCategoryService.cs:
BlogCategoryDto— Id, Title, Slug, Description, IconName, PostCount
9.3 مسیرها (Routes) — پیادهسازی شده
// RouteConstants.cs
public static class Blog
{
public const string Index = "/blog";
public const string Post = "/blog/"; // usage: /blog/{slug}
}
9.4 طراحی صفحه لیست بلاگ — پیادهسازی شده
┌─────────────────────────────────────────┐
│ Blog Hero (گرادیان بنفش) │
│ "بلاگ" │
│ "آخرین مطالب، آموزشها و اخبار" │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ [جستجو...] [دستهبندی ▼] [جستجو 🔍] │ ← فیلتر + MudSelect
└─────────────────────────────────────────┘
┌────────┐ ┌────────┐ ┌────────┐
│ Card 1 │ │ Card 2 │ │ Card 3 │ ← blog-card-v2
│ thumb │ │ thumb │ │ thumb │ ← تصویر شاخص
│ cat │ │ cat │ │ cat │ ← chip دستهبندی
│ title │ │ title │ │ title │ ← ۲ خط clamp
│ desc │ │ desc │ │ desc │ ← ۲ خط clamp
│ 📅 👁 │ │ 📅 👁 │ │ 📅 👁 │ ← تاریخ + بازدید
└────────┘ └────────┘ └────────┘
← ← ← [1] [2] [3] → → → ← MudPagination
9.5 طراحی صفحه مقاله — پیادهسازی شده
┌─────────────────────────────────────────┐
│ [تصویر شاخص full-width] + overlay │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ خانه > بلاگ > عنوان مقاله │ ← Breadcrumb
│ │
│ [دستهبندی ۱] [دستهبندی ۲] │ ← Chips (کلیک → فیلتر)
│ │
│ عنوان مقاله (H4, bold) │
│ خلاصه مقاله (subtitle) │
│ │
│ 📅 تاریخ 👁 ۱,۲۳۴ بازدید │
│ ───────────────────────── │
│ │
│ [محتوای HTML مقاله] │ ← blog-content (styled)
│ ... │
│ │
│ ───────────────────────── │
│ 🏷️ [تگ ۱] [تگ ۲] [تگ ۳] │ ← Outlined chips
│ │
│ [← بازگشت به بلاگ] │
└─────────────────────────────────────────┘
9.6 CSS اضافه شده (بخش Blog Pages در site.css)
/* Blog Pages region — اضافه شده به site.css */
.blog-hero — گرادیان بنفش (مشابه CTA)
.blog-title-clamp — -webkit-line-clamp: 2
.blog-summary-clamp — -webkit-line-clamp: 2
.cursor-pointer — cursor: pointer
.blog-detail-hero — تصویر شاخص 340px + overlay
.blog-content — تایپوگرافی مقاله (h1-h3, p, img, blockquote, code, pre, ul/ol, a)
/* + mobile overrides + dark mode */
9.7 ناوبری — لینک بلاگ اضافه شد ✅
تغییرات واقعی:
- MainLayout.razor → لینک "بلاگ" در navbar دسکتاپ (بین FAQ و Contact)
- MainLayout.razor → لینک "بلاگ" در Mobile Drawer
- Index.razor (لندینگ) → کارتهای بلاگ کلیکپذیر شدند (onclick)
- Index.razor (لندینگ) → دکمه "مشاهده همه مقالات" فعال شد (uncomment)
9.8 ثبت DI (ConfigureServices.cs)
// اضافه شده:
using CMSMicroservice.Protobuf.Protos.BlogCategory;
// Common services:
services.AddScoped<BlogCategoryService>();
// gRPC clients:
services.AddScoped(CreateAuthenticatedClient<BlogCategoryContract.BlogCategoryContractClient>);
10. فاز ۶ — بهبود داشبورد کاربر ✅ تکمیل شد
وضعیت: ✅ تکمیل | اولویت: متوسط | پیشنیاز: ندارد
10.1 بازطراحی کامل Profile/Index.razor
صفحه /profile به طور کامل با طراحی مدرن بازنویسی شد:
┌─────────────────────────────────────────┐
│ ████ GRADIENT HEADER CARD ████ │ ← .dash-header-card
│ 🧑 آواتار شیشهای | نام + موبایل │ ← .dash-avatar
│ عضو از ... | [💎 سامانه دایا] │ ← دکمه glass-morphism
└─────────────────────────────────────────┘
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 💳 اعتباری│ │ 🏷 تخفیف │ │ 👥 تیمی │ ← .dash-wallet-card
│ ۲.۵M تومان│ │ ۵۰۰K │ │ ۸۵۰K │ (hover lift)
└──────────┘ └──────────┘ └──────────┘
┌─────────────────────────────────────────┐
│ 📎 کد دعوت شما | [اشتراکگذاری] │ ← فعال اگر پکیج + باشگاه
│ یا │
│ 🔒 لینک دعوت فعال نشده (dashed border)│ ← حالت قفل
│ [شروع فرآیند تامین اعتبار] │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ دسترسی سریع │ ← .dash-tile (10 تایل)
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
│ │شخصی│ │آدرس│ │شجره│ │تنظیم│ │ هر تایل:
│ └────┘ └────┘ └────┘ └────┘ │ - آواتار رنگی
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ - عنوان + زیرعنوان
│ │فروش│ │کیف │ │برداشت│ │باشگا│ │ - hover: lift + primary border
│ └────┘ └────┘ └────┘ └────┘ │
│ ┌────┐ ┌────┐ │
│ │آمار│ │پاداش│ │
│ └────┘ └────┘ │
└─────────────────────────────────────────┘
10.2 تغییرات فایلها
Profile/Index.razor — بازنویسی کامل:
- هدر گرادیانی (
dash-header-card) با آواتار شیشهای - ۳ کارت والت جداگانه (اعتباری/تخفیف/تیمی) با رنگهای مختلف
- بخش رفرال تمیزتر (فعال با TextField + دکمه | قفل با dashed border)
- ۱۰ تایل مدرن با
DashTilerecord + آواتار رنگی
Profile/Index.razor.cs — اضافه شده:
private readonly List<DashTile> _dashTiles = new()
{
new(RouteConstants.Profile.Personal, Icons.Material.Filled.Person, "اطلاعات شخصی", ...),
new(RouteConstants.Profile.Addresses, Icons.Material.Filled.LocationOn, "آدرسها", ...),
// ... 10 تایل با رنگبندی اختصاصی
};
private record DashTile(string Href, string Icon, string Title, string Subtitle, string AvatarStyle);
10.3 CSS اضافه شده (بخش Dashboard v2 در site.css)
/* Dashboard v2 region */
.dash-header-card — گرادیان بنفش + دایره تزئینی
.dash-avatar — شیشهای (rgba + border سفید)
.dash-wallet-card — border + hover lift
.dash-tile — border + hover lift + primary border on hover
/* + dark mode + mobile overrides */
11. فاز ۷ — بهینهسازی موبایل ✅ تکمیل شد
وضعیت: ✅ تکمیل | اولویت: بالا | پیشنیاز: فازهای ۴-۶
11.1 مشکلات شناسایی و رفع شده
| مشکل | وضعیت قبل | راهحل |
|---|---|---|
| Dead Zone ناوبری (600-959px) | همبرگر فقط زیر 600px، لینکها فقط بالای 960px | تغییر Breakpoint از SmAndUp به MdAndUp |
| فوتر پنهان در موبایل | DeviceDetector.IsDesktop() فوتر را حذف میکرد |
حذف شرط — فوتر همیشه نمایش داده شود |
| عدم وجود Bottom Nav | فقط Drawer برای ناوبری موبایل | اضافه شدن bottom-nav ثابت (5 لینک) |
| تایپوگرافی بزرگ | h1=2rem, h2=1.875rem ثابت | responsive: h1→1.5rem, h2→1.35rem در موبایل |
| Touch targets کوچک | Dense AppBar، لینکهای Drawer بدون padding | min-height: 44px برای لینکها، 40px برای آیکونها |
| نقشه تماس بلند | 400px ثابت | 240px در موبایل با کلاس contact-map-placeholder |
| دکمههای About تنگ | Row بدون flex-wrap | اضافه flex-wrap + full-width در موبایل |
| محتوای بلاگ overflow | بدون guard | overflow-x: auto + table/iframe responsive |
| هاور در تاچ | جلوههای هاور در صفحه لمسی | @media (hover: none) — غیرفعال |
| Safe area | بدون padding | env(safe-area-inset-*) برای notched phones |
| theme-color | نداشت | <meta name="theme-color" content="#7c4dff"> |
11.2 Bottom Navigation — پیادهسازی
┌──────────────────────────────────────┐
│ 🏠 🏬 📰 🛒 👤 │ ← .bottom-nav (fixed)
│ خانه فروش بلاگ سبد پروفایل │ backdrop-filter blur
└──────────────────────────────────────┘
- فقط در زیر
Breakpoint.MdAndUpنمایش داده شود (MudHidden) - اگر لاگین نباشد: دکمه "ورود" بجای "سبد خرید" و "پروفایل"
padding-bottom: 68pxروی.main-content-wrapperبرای جلوگیری از overlapenv(safe-area-inset-bottom)برای گوشیهای notched
11.3 CSS اضافه شده (بخش Phase 7 در site.css ~120 خط)
.bottom-nav — fixed, z-1100, rounded top, glass blur
.bottom-nav-item — flex column, min 48px touch, transition color
.main-content-wrapper — padding-bottom 68px (≤960px)
responsive typography — h1-h5 smaller ≤600px
touch targets — drawer links 44px, appbar icons 40px
footer mobile — compact padding, smaller text
landing mobile — smaller chips, timeline text
blog mobile — shorter thumbnails, scaled pagination, overflow guard
dashboard mobile — compact wallets + tiles
about mobile — hero button wrap, reduced padding
contact mobile — shorter map, full-width submit
global mobile — tighter container padding, safe-area
@media (hover: none) — disable hover transforms on touch
11.4 فایلهای تغییریافته
MainLayout.razor — Breakpoint fix + Bottom Nav + Footer gate removed
site.css — +120 خط CSS موبایل (Phase 7 region)
_Host.cshtml — +theme-color + apple-mobile-web-app meta tags
Contact.razor — +class contact-map-placeholder
About.razor — +flex-wrap روی دکمههای hero
12. فایلهای تغییریافته (نقشه فایلها)
فایلهای جدید
| پروژه | مسیر | تعداد فایل |
|---|---|---|
| CMS Domain | Entities/Blog/ (BlogPost, BlogCategory, BlogTag, BlogPostCategory, BlogPostTag, BlogPostImage) + Entities/Content/ (SitePage, SitePageAttachment) + Enums/ (BlogPostStatus) |
9 |
| CMS Infrastructure | Configurations/Blog/ (5) + Configurations/Content/ (2) + EF Migration |
8 |
| CMS Application | BlogPostCQ/ (~25) + BlogCategoryCQ/ (~12) + BlogPostImageCQ/ (~9) + SitePageCQ/ (~18) |
~64 |
| CMS Protobuf | public_messages.proto + blogpost.proto + blogcategory.proto + sitepage.proto |
4 |
| CMS WebApi | Services/ (BlogPostService, BlogCategoryService, SitePageService, BlogPostImageService) + Mappings/ (4 profiles) |
8 |
| BackOffice Pages | Pages/Blog/ (BlogPosts.razor, BlogCategories.razor + ۲ dialog) + Pages/Content/ (SitePages.razor + ۳ dialog) |
10 |
| BackOffice Services | Services/Blog/ (BlogPostService, BlogCategoryService, BlogTagService + ۳ model) + Services/Content/ (SitePageService + model) |
8 |
| FrontOffice Pages | Pages/Blog/Index.razor + Index.razor.cs + Post.razor + Post.razor.cs |
4 |
| FrontOffice Services | Utilities/BlogPostService.cs + Utilities/BlogCategoryService.cs + Utilities/SitePageService.cs |
3 |
| FrontOffice Assets | wwwroot/js/landing.js |
1 |
| ~119 فایل جدید |
فایلهای ویرایشی
| پروژه | فایل | تغییر |
|---|---|---|
| CMS Infrastructure | ApplicationDbContext.cs |
+7 DbSets (BlogPost, BlogCategory, BlogTag, BlogPostCategory, BlogPostTag, BlogPostImage, SitePage) |
| CMS WebApi | Program.cs |
+4 gRPC service registrations |
| BackOffice | Shared/NavMenu.razor |
+بخش مدیریت محتوا (بلاگ + صفحات) + ۲ مجوز جدید |
| BackOffice | Common/Configure/ConfigureService.cs |
+4 gRPC clients + 4 services + using statements |
| FrontOffice | Pages/Index.razor |
بازنویسی کامل (Hero + Features + Timeline + Stats + Blog + Testimonials + FAQ + CTA) |
| FrontOffice | Pages/Index.razor.cs |
+LoadFeaturedPosts + NavigateToPost |
| FrontOffice | Pages/About.razor |
تبدیل به دینامیک (CMS + fallback) |
| FrontOffice | Pages/Contact.razor |
تبدیل به دینامیک (CMS + fallback) |
| FrontOffice | Pages/Profile/Index.razor |
بازنویسی کامل (header card + wallets + tiles) |
| FrontOffice | Pages/Profile/Index.razor.cs |
+DashTile record + _dashTiles لیست |
| FrontOffice | Shared/MainLayout.razor |
+لینک بلاگ (desktop + mobile drawer) |
| FrontOffice | Common/Configure/ConfigureServices.cs |
+BlogCategoryService + BlogCategoryContract gRPC |
| FrontOffice | Utilities/RouteConstants.cs |
+Blog.Index + Blog.Post routes |
| FrontOffice | wwwroot/css/site.css |
+Landing v2 + Blog Pages + Dashboard v2 (~300 خط CSS) |
| FrontOffice | Pages/_Host.cshtml |
+landing.js script reference |
| ~15 فایل ویرایشی |
13. جدول زمانی
هفته ۱:
├─ فاز ۱: موجودیتهای بکند (Entities + Protos + CQRS) [۲-۳ روز] ✅ تکمیل
└─ فاز ۲: پنل مدیریت بلاگ BackOffice [۲-۳ روز] ✅ تکمیل
هفته ۲:
├─ فاز ۳: صفحات دینامیک (About + Contact) [۱-۲ روز] ✅ تکمیل
├─ فاز ۴: نوسازی لندینگ پیج [۲-۳ روز] ✅ تکمیل
└─ فاز ۵: صفحات بلاگ FrontOffice [۲-۳ روز] ✅ تکمیل
هفته ۳:
├─ فاز ۶: بهبود داشبورد کاربر [۱-۲ روز] ✅ تکمیل
├─ فاز ۷: بهینهسازی موبایل [۱-۲ روز] ✅ تکمیل
└─ تست + رفع باگ + دیپلوی [۱-۲ روز]
مجموع تخمین: ۱۲-۲۰ روز کاری (۲.۵ تا ۴ هفته)
ترتیب وابستگی
فاز ۱ (Backend) ──► فاز ۲ (Admin Blog)
│
├──────────► فاز ۳ (Dynamic Pages)
│
├──────────► فاز ۵ (FrontOffice Blog)
│ │
│ ▼
└──────────► فاز ۴ (Landing) ──► فاز ۷ (Mobile)
▲
فاز ۶ (Dashboard) ───────┘
14. ریسکها و وابستگیها
| ریسک | احتمال | تأثیر | راهحل |
|---|---|---|---|
| WYSIWYG Editor محدودیت RTL | متوسط | متوسط | تست اولیه MudBlazor.HtmlEditor با فارسی، fallback به textarea + markdown |
| حجم Migration بزرگ | کم | بالا | Migration را تکهتکه اجرا کن (Blog اول، SitePage بعد) |
| عملکرد لندینگ با انیمیشنها | متوسط | متوسط | Lazy load + Intersection Observer + حداقل JS |
| FMS قطعی هنگام آپلود تصویر | کم | بالا | Retry policy + پیام خطای مناسب |
| Slug فارسی در URL | متوسط | کم | استفاده از ID-based URLs با slug فقط برای SEO |
| سازگاری Dark Mode | متوسط | کم | تست هر بخش در هر دو حالت |
ضمیمه: نمونه کد الگوهای کلیدی
A. الگوی Entity (مطابق پروژه)
// Domain/Entities/Blog/BlogPost.cs
public class BlogPost : BaseAuditableEntity
{
public string Title { get; set; } = default!;
public string Slug { get; set; } = default!;
public string? Summary { get; set; }
public string HtmlContent { get; set; } = default!;
public string? FeaturedImagePath { get; set; }
public string? FeaturedImageThumbnailPath { get; set; }
public BlogPostStatus Status { get; set; } = BlogPostStatus.Draft;
public DateTime? PublishedAt { get; set; }
public int ViewCount { get; set; }
public long AuthorUserId { get; set; }
public bool IsFeatured { get; set; }
public int SortOrder { get; set; }
public ICollection<BlogPostCategory> BlogPostCategories { get; set; } = new List<BlogPostCategory>();
public ICollection<BlogPostTag> BlogPostTags { get; set; } = new List<BlogPostTag>();
public ICollection<BlogPostImage> BlogPostImages { get; set; } = new List<BlogPostImage>();
}
B. الگوی Proto (مطابق پروژه)
// blogpost.proto
syntax = "proto3";
option csharp_namespace = "CMSMicroservice.Protobuf";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
service BlogPostContract {
rpc CreateBlogPost (CreateBlogPostRequest) returns (BlogPostResponse);
rpc GetPublishedBlogPosts (GetPublishedBlogPostsRequest) returns (BlogPostListResponse);
// ...
}
message CreateBlogPostRequest {
string title = 1;
string slug = 2;
string summary = 3;
string html_content = 4;
bytes featured_image = 5;
string featured_image_file_name = 6;
repeated int64 category_ids = 7;
repeated int64 tag_ids = 8;
bool is_featured = 9;
}
message BlogPostResponse {
int64 id = 1;
string title = 2;
string slug = 3;
string summary = 4;
string html_content = 5;
string featured_image_path = 6;
string featured_image_thumbnail_path = 7;
int32 status = 8;
google.protobuf.Timestamp published_at = 9;
int32 view_count = 10;
bool is_featured = 11;
repeated BlogCategoryInfo categories = 12;
repeated TagInfo tags = 13;
}
C. الگوی CQRS Handler (مطابق پروژه)
// Application/BlogPostCQ/Commands/CreateBlogPost/CreateBlogPostCommandHandler.cs
public class CreateBlogPostCommandHandler : IRequestHandler<CreateBlogPostCommand, long>
{
private readonly IApplicationDbContext _context;
private readonly IFileManagerService _fileManager;
public CreateBlogPostCommandHandler(
IApplicationDbContext context,
IFileManagerService fileManager)
{
_context = context;
_fileManager = fileManager;
}
public async Task<long> Handle(CreateBlogPostCommand request, CancellationToken ct)
{
var post = new BlogPost
{
Title = request.Title,
Slug = request.Slug,
Summary = request.Summary,
HtmlContent = request.HtmlContent,
Status = BlogPostStatus.Draft,
AuthorUserId = request.AuthorUserId,
};
if (request.FeaturedImage?.Length > 0)
{
var (path, thumb) = await _fileManager.UploadFileAsync(
request.FeaturedImage, request.FeaturedImageFileName);
post.FeaturedImagePath = path;
post.FeaturedImageThumbnailPath = thumb;
}
_context.BlogPosts.Add(post);
await _context.SaveChangesAsync(ct);
// Add categories & tags...
return post.Id;
}
}
D. الگوی gRPC Service (مطابق پروژه)
// WebApi/Services/BlogPostService.cs
public class BlogPostService : BlogPostContract.BlogPostContractBase
{
private readonly IMediator _mediator;
private readonly IMapper _mapper;
public BlogPostService(IMediator mediator, IMapper mapper)
{
_mediator = mediator;
_mapper = mapper;
}
public override async Task<BlogPostResponse> CreateBlogPost(
CreateBlogPostRequest request, ServerCallContext context)
{
var command = _mapper.Map<CreateBlogPostCommand>(request);
var id = await _mediator.Send(command);
// Get and return the created post...
}
}
یادداشت: این سند یک نقشهراه جامع است. هر فاز به صورت مستقل قابل پیادهسازی است و وابستگیها در بخش ۱۳ مشخص شدهاند. بعد از تأیید این طرح، پیادهسازی فاز به فاز شروع میشود.