diff --git a/src/TelegramPanel.Web/Components/Dialogs/ChannelDetailsDialog.razor b/src/TelegramPanel.Web/Components/Dialogs/ChannelDetailsDialog.razor
new file mode 100644
index 0000000..2916b1a
--- /dev/null
+++ b/src/TelegramPanel.Web/Components/Dialogs/ChannelDetailsDialog.razor
@@ -0,0 +1,230 @@
+@namespace TelegramPanel.Web.Components.Dialogs
+@inject ChannelManagementService ChannelManagement
+@inject AccountManagementService AccountManagement
+@inject IChannelService ChannelService
+@inject ISnackbar Snackbar
+@inject IDialogService DialogService
+@using TelegramPanel.Data.Entities
+
+
+
+ @if (loading)
+ {
+
+ }
+ else if (channel == null)
+ {
+ 未找到频道数据
+ }
+ else
+ {
+
+ @channel.Title
+
+
+
+ TelegramId:@channel.TelegramId
+ 用户名:@(string.IsNullOrWhiteSpace(channel.Username) ? "(私密)" : "@" + channel.Username)
+ 成员数:@channel.MemberCount
+
+
+ 创建者:@creatorDisplay
+ 创建时间:@(channel.CreatedAt?.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") ?? "(未知)")
+ 最后同步:@channel.SyncedAt.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")
+
+
+
+ @if (!string.IsNullOrWhiteSpace(channel.About))
+ {
+ 简介:
+
+ @channel.About
+
+ }
+
+
+
+
+ 管理员
+
+
+ 刷新
+
+
+
+ @if (adminsLoading)
+ {
+
+ }
+ else if (admins.Count == 0)
+ {
+ 暂无管理员数据(或无权限获取)
+ }
+ else
+ {
+
+
+ 身份
+ 昵称
+ 用户名
+ 头衔
+
+
+
+
+ @(context.IsCreator ? "创建者" : "管理员")
+
+
+ @context.DisplayName
+ @(!string.IsNullOrWhiteSpace(context.Username) ? "@" + context.Username : "-")
+ @(string.IsNullOrWhiteSpace(context.Rank) ? "-" : context.Rank)
+
+
+ }
+
+
+
+ 踢出成员
+
+ 输入 @@用户名 执行踢出;“非永久”会使用短时间封禁达到踢出效果,随后自动解除,方便对方重新加入。
+
+
+
+
+
+ @if (kickLoading)
+ {
+
+ 处理中...
+ }
+ else
+ {
+ 踢出
+ }
+
+
+
+ }
+
+
+ @if (channel != null)
+ {
+ 编辑频道
+ }
+ 关闭
+
+
+
+@code
+{
+ [CascadingParameter] private MudDialogInstance MudDialog { get; set; } = default!;
+ [Parameter] public int ChannelDbId { get; set; }
+
+ private bool loading = true;
+ private Channel? channel;
+ private string creatorDisplay = "-";
+
+ private bool adminsLoading;
+ private List admins = new();
+
+ private string kickUsername = "";
+ private bool kickPermanent;
+ private bool kickLoading;
+
+ protected override async Task OnInitializedAsync()
+ {
+ await LoadChannel();
+ await LoadAdmins();
+ }
+
+ private async Task LoadChannel()
+ {
+ loading = true;
+ try
+ {
+ channel = await ChannelManagement.GetChannelAsync(ChannelDbId);
+ if (channel == null)
+ return;
+
+ var creator = await AccountManagement.GetAccountAsync(channel.CreatorAccountId);
+ creatorDisplay = creator == null
+ ? $"账号 {channel.CreatorAccountId}"
+ : $"{creator.Phone}({creator.Nickname ?? creator.Username ?? creator.UserId.ToString()})";
+ }
+ catch (Exception ex)
+ {
+ Snackbar.Add($"加载频道失败:{ex.Message}", Severity.Error);
+ }
+ finally
+ {
+ loading = false;
+ }
+ }
+
+ private async Task LoadAdmins()
+ {
+ if (channel == null)
+ return;
+
+ adminsLoading = true;
+ try
+ {
+ admins = await ChannelService.GetAdminsAsync(channel.CreatorAccountId, channel.TelegramId);
+ }
+ catch (Exception ex)
+ {
+ admins.Clear();
+ Snackbar.Add($"加载管理员失败:{ex.Message}", Severity.Error);
+ }
+ finally
+ {
+ adminsLoading = false;
+ }
+ }
+
+ private async Task KickUser()
+ {
+ if (channel == null)
+ return;
+
+ kickLoading = true;
+ try
+ {
+ await ChannelService.KickUserAsync(channel.CreatorAccountId, channel.TelegramId, kickUsername, kickPermanent);
+ Snackbar.Add("已执行踢出操作", Severity.Success);
+ kickUsername = "";
+ }
+ catch (Exception ex)
+ {
+ Snackbar.Add($"踢出失败:{ex.Message}", Severity.Error);
+ }
+ finally
+ {
+ kickLoading = false;
+ }
+ }
+
+ private async Task OpenEdit()
+ {
+ if (channel == null)
+ return;
+
+ var parameters = new DialogParameters { ["ChannelDbId"] = ChannelDbId };
+ var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Medium, FullWidth = true };
+ var dialog = DialogService.Show("编辑频道", parameters, options);
+ var result = await dialog.Result;
+ if (!result.Canceled)
+ {
+ await LoadChannel();
+ await LoadAdmins();
+ }
+ }
+
+ private void Close()
+ {
+ MudDialog.Close();
+ }
+}
diff --git a/src/TelegramPanel.Web/Components/Dialogs/ChannelEditDialog.razor b/src/TelegramPanel.Web/Components/Dialogs/ChannelEditDialog.razor
new file mode 100644
index 0000000..089bd1b
--- /dev/null
+++ b/src/TelegramPanel.Web/Components/Dialogs/ChannelEditDialog.razor
@@ -0,0 +1,136 @@
+@namespace TelegramPanel.Web.Components.Dialogs
+@inject ChannelManagementService ChannelManagement
+@inject IChannelService ChannelService
+@inject ISnackbar Snackbar
+@using TelegramPanel.Data.Entities
+
+
+
+ @if (loading)
+ {
+
+ }
+ else if (channel == null)
+ {
+ 未找到频道数据
+ }
+ else
+ {
+
+
+
+
+
+ @if (isPublic)
+ {
+
+ }
+
+
+
+ }
+
+
+ 取消
+
+ @if (saving)
+ {
+
+ 保存中...
+ }
+ else
+ {
+ 保存
+ }
+
+
+
+
+@code
+{
+ [CascadingParameter] private MudDialogInstance MudDialog { get; set; } = default!;
+ [Parameter] public int ChannelDbId { get; set; }
+
+ private bool loading = true;
+ private bool saving;
+ private Channel? channel;
+
+ private string title = "";
+ private string? about;
+ private bool isPublic;
+ private string username = "";
+ private bool forwardingAllowed = true;
+
+ private bool CanSave => channel != null && !string.IsNullOrWhiteSpace(title) && (!isPublic || !string.IsNullOrWhiteSpace(username));
+
+ protected override async Task OnInitializedAsync()
+ {
+ await LoadChannel();
+ }
+
+ private async Task LoadChannel()
+ {
+ loading = true;
+ try
+ {
+ channel = await ChannelManagement.GetChannelAsync(ChannelDbId);
+ if (channel == null)
+ return;
+
+ title = channel.Title;
+ about = channel.About;
+ isPublic = !string.IsNullOrWhiteSpace(channel.Username);
+ username = channel.Username ?? "";
+ }
+ catch (Exception ex)
+ {
+ Snackbar.Add($"加载频道失败:{ex.Message}", Severity.Error);
+ }
+ finally
+ {
+ loading = false;
+ }
+ }
+
+ private async Task Save()
+ {
+ if (channel == null)
+ return;
+
+ saving = true;
+ try
+ {
+ var newTitle = title.Trim();
+ var newAbout = string.IsNullOrWhiteSpace(about) ? null : about.Trim();
+ var newUsername = string.IsNullOrWhiteSpace(username) ? null : username.Trim().TrimStart('@');
+
+ await ChannelService.UpdateChannelInfoAsync(channel.CreatorAccountId, channel.TelegramId, newTitle, newAbout);
+ await ChannelService.SetChannelVisibilityAsync(channel.CreatorAccountId, channel.TelegramId, isPublic, newUsername);
+ await ChannelService.SetForwardingAllowedAsync(channel.CreatorAccountId, channel.TelegramId, forwardingAllowed);
+
+ channel.Title = newTitle;
+ channel.About = newAbout;
+ channel.Username = isPublic ? newUsername : null;
+
+ await ChannelManagement.UpdateChannelAsync(channel);
+
+ Snackbar.Add("保存成功", Severity.Success);
+ MudDialog.Close(DialogResult.Ok(true));
+ }
+ catch (Exception ex)
+ {
+ Snackbar.Add($"保存失败:{ex.Message}", Severity.Error);
+ }
+ finally
+ {
+ saving = false;
+ }
+ }
+
+ private void Cancel()
+ {
+ MudDialog.Cancel();
+ }
+}
diff --git a/src/TelegramPanel.Web/Components/Pages/Channels.razor b/src/TelegramPanel.Web/Components/Pages/Channels.razor
index 6fb3ca1..61bbda1 100644
--- a/src/TelegramPanel.Web/Components/Pages/Channels.razor
+++ b/src/TelegramPanel.Web/Components/Pages/Channels.razor
@@ -4,6 +4,7 @@
@inject ISnackbar Snackbar
@inject IDialogService DialogService
@inject NavigationManager Navigation
+@using TelegramPanel.Web.Components.Dialogs
@using TelegramPanel.Data.Entities
频道列表 - Telegram Panel
@@ -82,8 +83,9 @@
@context.SyncedAt.ToString("yyyy-MM-dd HH:mm")
- 查看详情
- 编辑频道
+ 查看详情
+ 编辑频道
+ 踢人
邀请用户
复制链接
@@ -169,14 +171,28 @@
return false;
}
- private void ShowDetails(Channel channel)
+ private async Task ShowDetails(Channel channel)
{
- Snackbar.Add($"查看频道详情:{channel.Title}", Severity.Info);
+ var parameters = new DialogParameters { ["ChannelDbId"] = channel.Id };
+ var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Large, FullWidth = true };
+ DialogService.Show("频道详情", parameters, options);
+ await Task.CompletedTask;
}
- private void EditChannel(Channel channel)
+ private async Task EditChannel(Channel channel)
{
- Snackbar.Add($"编辑频道:{channel.Title}", Severity.Info);
+ var parameters = new DialogParameters { ["ChannelDbId"] = channel.Id };
+ var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Medium, FullWidth = true };
+ var dialog = DialogService.Show("编辑频道", parameters, options);
+ var result = await dialog.Result;
+ if (!result.Canceled)
+ await LoadChannels();
+ }
+
+ private async Task KickUser(Channel channel)
+ {
+ // 复用详情弹窗里的“踢人”能力,减少重复 UI
+ await ShowDetails(channel);
}
private void InviteUsers(Channel channel)
diff --git a/src/TelegramPanel.Web/Components/Pages/Home.razor b/src/TelegramPanel.Web/Components/Pages/Home.razor
index 91fd424..6724cf2 100644
--- a/src/TelegramPanel.Web/Components/Pages/Home.razor
+++ b/src/TelegramPanel.Web/Components/Pages/Home.razor
@@ -208,7 +208,8 @@
IsBroadcast = channelInfo.IsBroadcast,
MemberCount = channelInfo.MemberCount,
About = channelInfo.About,
- CreatorAccountId = account.Id
+ CreatorAccountId = account.Id,
+ CreatedAt = channelInfo.CreatedAt
};
await ChannelManagement.CreateOrUpdateChannelAsync(channel);
totalChannelsSynced++;
diff --git a/src/TelegramPanel.Web/Components/Pages/Settings.razor b/src/TelegramPanel.Web/Components/Pages/Settings.razor
index 94c35b3..99d7b87 100644
--- a/src/TelegramPanel.Web/Components/Pages/Settings.razor
+++ b/src/TelegramPanel.Web/Components/Pages/Settings.razor
@@ -245,7 +245,8 @@
IsBroadcast = channelInfo.IsBroadcast,
MemberCount = channelInfo.MemberCount,
About = channelInfo.About,
- CreatorAccountId = account.Id
+ CreatorAccountId = account.Id,
+ CreatedAt = channelInfo.CreatedAt
};
await ChannelManagement.CreateOrUpdateChannelAsync(channel);
totalChannelsSynced++;