@page "/network/tree" @attribute [Authorize] @implements IAsyncDisposable @inject IJSRuntime JS @using CMSMicroservice.Protobuf.Protos.NetworkMembership @using BackOffice.Pages.AutoComplete
درخت شبکه @* Search & Filter Panel *@
نمایش درخت
3 سطح 5 سطح 10 سطح 15 سطح همه همه فعال غیرفعال
@* Chart Toolbar *@ @if (_treeData != null && _treeData.Nodes.Any()) { @if (_currentViewUserId.HasValue && _currentViewUserId != _searchUserId) { بازگشت ریشه } کل: @_totalMembers چپ: @_leftCount راست: @_rightCount } @* Chart Container *@ @if (_isLoading) { در حال بارگذاری درخت شبکه... } else if (_hasError) { خطا در بارگذاری درخت تلاش مجدد } else if (_treeData != null && _treeData.Nodes.Any()) {
@* Data Grid *@ جدول اعضای شبکه @(context.Item.NetworkLeg == 0 ? "چپ" : "راست") @(context.Item.IsClubActive ? "فعال" : "غیرفعال") @if (context.Item.ClubActivatedAt != null) { @context.Item.ClubActivatedAt.ToDateTime().ToLocalTime().MiladiToJalali() } else { - } @if (context.Item.ActivationWeekDefinitionId != null) { W@context.Item.ActivationWeekDefinitionId } else { - } موردی یافت نشد. } else { برای نمایش درخت شبکه، کاربر مورد نظر را جستجو کرده و دکمه "نمایش درخت" را بزنید. }
@code { [Inject] public NetworkMembershipContract.NetworkMembershipContractClient NetworkContract { get; set; } [Inject] public NavigationManager NavigationManager { get; set; } private long? _searchUserId; private long? _currentViewUserId; private GetNetworkTreeResponse _treeData; private bool _isLoading; private bool _hasError; private int _totalMembers; private int _leftCount; private int _rightCount; private int _selectedDepth = 10; private bool? _clubActiveFilter; private long? _activationWeekFilter; private DotNetObjectReference _dotNetRef; private Stack _navigationHistory = new(); private bool _chartNeedsInit = false; protected override void OnInitialized() { _dotNetRef = DotNetObjectReference.Create(this); } protected override async Task OnAfterRenderAsync(bool firstRender) { if (_chartNeedsInit && _treeData != null && _treeData.Nodes.Any()) { _chartNeedsInit = false; await RenderChart(); } } private async Task LoadTree() { if (!_searchUserId.HasValue || _searchUserId.Value <= 0) { Snackbar.Add("لطفاً کاربر را انتخاب کنید", Severity.Warning); return; } _isLoading = true; _hasError = false; StateHasChanged(); try { var request = new GetNetworkTreeRequest { UserId = _searchUserId.Value, MaxDepth = _selectedDepth, IsClubActive = _clubActiveFilter, ActivationWeekDefinitionId = _activationWeekFilter?.ToString() }; _treeData = await NetworkContract.GetNetworkTreeAsync(request); _currentViewUserId = _searchUserId; _navigationHistory.Clear(); CalculateStats(); _isLoading = false; _chartNeedsInit = true; StateHasChanged(); Snackbar.Add($"درخت بارگذاری شد - {_treeData.Nodes.Count} عضو", Severity.Success); } catch (Exception ex) { _hasError = true; _isLoading = false; Snackbar.Add($"خطا در بارگذاری درخت: {ex.Message}", Severity.Error); StateHasChanged(); } } private async Task LoadSubTree(long userId) { _isLoading = true; StateHasChanged(); try { var request = new GetNetworkTreeRequest { UserId = userId, MaxDepth = _selectedDepth, IsClubActive = _clubActiveFilter, ActivationWeekDefinitionId = _activationWeekFilter?.ToString() }; _treeData = await NetworkContract.GetNetworkTreeAsync(request); if (_currentViewUserId.HasValue && _currentViewUserId != userId) { _navigationHistory.Push(_currentViewUserId.Value); } _currentViewUserId = userId; CalculateStats(); _isLoading = false; _chartNeedsInit = true; StateHasChanged(); } catch (Exception ex) { _isLoading = false; Snackbar.Add($"خطا: {ex.Message}", Severity.Error); StateHasChanged(); } } private async Task RenderChart() { if (_treeData == null || !_treeData.Nodes.Any()) return; try { await Task.Delay(50); // Wait for DOM var jsNodes = _treeData.Nodes.Select(n => new { id = n.UserId.ToString(), parentId = n.ParentId > 0 ? n.ParentId.ToString() : "", userId = n.UserId, userName = n.UserName ?? $"کاربر {n.UserId}", networkLevel = n.NetworkLevel, networkLeg = n.NetworkLeg, isClubActive = n.IsClubActive, isActivatedInTargetWeek = n.IsActivatedInTargetWeek, activationWeekDefinitionId = n.ActivationWeekDefinitionId, clubActivatedAt = n.ClubActivatedAt?.ToDateTime().ToLocalTime().MiladiToJalali() ?? "" }).ToArray(); var options = new { filterWeek = _activationWeekFilter }; await JS.InvokeVoidAsync("AdminOrgChart.init", "admin-org-chart-container", jsNodes, _dotNetRef, options); } catch (Exception ex) { } } [JSInvokable] public async Task OnNodeClicked(long userId) { if (userId == _currentViewUserId) return; await LoadSubTree(userId); } private void CalculateStats() { if (_treeData == null || !_treeData.Nodes.Any()) { _totalMembers = _leftCount = _rightCount = 0; return; } _totalMembers = _treeData.Nodes.Count; _leftCount = _treeData.Nodes.Count(n => n.NetworkLeg == 0); _rightCount = _treeData.Nodes.Count(n => n.NetworkLeg == 1); } private async Task ExpandAll() { try { await JS.InvokeVoidAsync("AdminOrgChart.expandAll"); } catch { } } private async Task CollapseAll() { try { await JS.InvokeVoidAsync("AdminOrgChart.collapseAll"); } catch { } } private async Task FitChart() { try { await JS.InvokeVoidAsync("AdminOrgChart.fit"); } catch { } } private async Task ExportPng() { try { await JS.InvokeVoidAsync("AdminOrgChart.exportPng"); } catch { } } private async Task GoBack() { if (_navigationHistory.Count > 0) { var previousUserId = _navigationHistory.Pop(); _currentViewUserId = previousUserId; await LoadSubTree(previousUserId); } } private async Task GoToRoot() { if (_searchUserId.HasValue) { _navigationHistory.Clear(); await LoadSubTree(_searchUserId.Value); } } private async Task ViewUserTree(long userId) { await LoadSubTree(userId); } private void ViewUserDetails(long userId) { NavigationManager.NavigateTo($"/network/user-info/{userId}"); } public async ValueTask DisposeAsync() { try { await JS.InvokeVoidAsync("AdminOrgChart.dispose"); } catch { } _dotNetRef?.Dispose(); } }