fix: 完善订阅加群任务并补充文档

This commit is contained in:
meoacgx committed 2025-12-21 01:44:39 +08:00
1 parent 76496f935e
commit 016a38949a
4 files changed
+77 -9

No files matched your search

+24
View File
@@ -12,11 +12,35 @@
- 📥 **多账号批量导入/登录**:支持 Session/压缩包导入;支持手机号验证码登录与 2FA 密码
- 🔁 **账号维度一键切换操作**:选择不同账号创建频道/群组、查看与管理账号创建的数据
- 👥 **批量运营能力**:批量邀请成员/机器人、批量设置管理员、导出链接等高频操作
- 🧩 **用户任务:批量订阅/加群**:任务中心新建「用户任务 → 批量订阅/加群」,支持按账号分类筛选;账号列表支持单账号“进群/订阅”入口(多链接换行分隔)
- 🔐 **二级密码(2FA)与找回邮箱**:支持单个/批量修改二级密码;支持绑定/换绑 2FA 找回邮箱(验证码确认)
- 🧯 **忘记二级密码可申请重置**:支持单个或批量向 Telegram 提交“忘记密码重置”申请(通常等待 7 天后可重新设置)
- 🪪 **账号资料管理**:支持单账号编辑昵称/Bio/用户名/头像;支持批量修改昵称(自动追加手机号后 4 位便于区分)与批量修改 Bio
- 🤖 **Bot 频道管理**:用于管理“频道创建人不在系统中”的频道(把 Bot 设为管理员即可纳入管理),支持批量导出链接、批量设置管理员(踢人能力可扩展)
## 批量订阅/加群(用户任务)
说明:这是**用户账号**任务(Bot 无法主动加群/订阅)。
### 入口 1:任务中心批量执行
1. 进入「任务中心」→ 点击「新建任务」
2. 选择:任务分类 =「用户任务」,任务类型 =「批量订阅/加群」
3. 选择执行账号(支持按**账号分类**筛选 + 搜索)
4. 粘贴链接/用户名(**换行分隔**),设置间隔(建议 1500–4000ms)
5. 提交后到「任务中心」查看进度与结果
### 入口 2:账号列表单账号执行
在「账号列表」每行账号的操作区点击「进群/订阅」,输入多个链接/用户名(换行分隔)后确认即可提交后台任务。
### 支持的链接/格式
- `https://t.me/xxx`
- `t.me/+hash`
- `@username` / `username`
- `tg://join?invite=hash`
## 🧊 防冻结指南(新号必看)
@@ -659,8 +659,8 @@ public class AccountTelegramToolsService
var title = chat switch
{
Channel c => c.title,
Chat c => c.title,
TL.Channel c => c.title,
TL.Chat c => c.title,
_ => null
};
@@ -1,5 +1,6 @@
@namespace TelegramPanel.Web.Components.Dialogs
@inject AccountManagementService AccountManagement
@inject AccountCategoryManagementService CategoryManagement
@inject TelegramPanel.Core.Services.AccountRiskService RiskService
@inject BatchTaskManagementService TaskManagement
@inject ISnackbar Snackbar
@@ -43,7 +44,7 @@
<MudDivider Class="my-2" />
<MudAlert Severity="Severity.Warning" Variant="Variant.Outlined" Dense="true">
批量订阅频道/加群(用户任务):支持输入多个链接/用户名,换行分隔。支持:<b>https://t.me/xxx</b>、<b>t.me/+hash</b>、<b>@username</b>、<b>username</b>、<b>tg://join?invite=hash</b>。
批量订阅频道/加群(用户任务):支持输入多个链接/用户名,换行分隔。支持:<b>https://t.me/xxx</b>、<b>t.me/+hash</b>、<b>@@username</b>、<b>username</b>、<b>tg://join?invite=hash</b>。
</MudAlert>
<MudTextField @bind-Value="linksText" Label="频道/群链接列表(换行分隔)" Variant="Variant.Outlined" Lines="8"
@@ -55,12 +56,26 @@
<MudStack direction="Row" AlignItems="AlignItems.Center" Spacing="2">
<MudText Typo="Typo.subtitle2">选择执行账号:@selectedAccounts.Count / @accounts.Count</MudText>
<MudSpacer />
<MudButton Variant="Variant.Outlined" Color="Color.Primary" OnClick="SelectAll" Disabled="@(accounts.Count == 0)">全选</MudButton>
<MudButton Variant="Variant.Outlined" Color="Color.Primary" OnClick="SelectAll" Disabled="@(accounts.Count == 0)">全选当前筛选</MudButton>
<MudButton Variant="Variant.Text" Color="Color.Secondary" OnClick="ClearSelection" Disabled="@(selectedAccounts.Count == 0)">清空</MudButton>
</MudStack>
<MudTextField @bind-Value="accountSearch" Placeholder="搜索账号(手机号/昵称/用户名)" Variant="Variant.Outlined"
Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" Immediate="true" />
<MudGrid>
<MudItem xs="12" md="4">
<MudSelect @bind-Value="filterAccountCategoryId" Label="账号分类筛选" Variant="Variant.Outlined" Dense="true" Style="min-width: 160px;">
<MudSelectItem Value="0">全部分类</MudSelectItem>
<MudSelectItem Value="-1">未分类</MudSelectItem>
@foreach (var c in categories)
{
<MudSelectItem Value="@c.Id">@c.Name</MudSelectItem>
}
</MudSelect>
</MudItem>
<MudItem xs="12" md="8">
<MudTextField @bind-Value="accountSearch" Placeholder="搜索账号(手机号/昵称/用户名)" Variant="Variant.Outlined"
Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" Immediate="true" />
</MudItem>
</MudGrid>
<MudTable Items="@FilteredAccounts" Dense="true" Hover="true" Breakpoint="Breakpoint.Sm"
MultiSelection="true" @bind-SelectedItems="selectedAccounts" Loading="@loadingAccounts">
@@ -68,11 +83,13 @@
<MudTh>手机号</MudTh>
<MudTh>昵称</MudTh>
<MudTh>用户名</MudTh>
<MudTh>分类</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="手机号">@context.Phone</MudTd>
<MudTd DataLabel="昵称">@(string.IsNullOrWhiteSpace(context.Nickname) ? "-" : context.Nickname)</MudTd>
<MudTd DataLabel="用户名">@(string.IsNullOrWhiteSpace(context.Username) ? "-" : "@" + context.Username)</MudTd>
<MudTd DataLabel="分类">@GetAccountCategoryName(context.CategoryId)</MudTd>
</RowTemplate>
<NoRecordsContent>
<MudText>暂无账号</MudText>
@@ -150,7 +167,9 @@
private bool loadingAccounts;
private List<Account> accounts = new();
private List<AccountCategory> categories = new();
private string accountSearch = "";
private int filterAccountCategoryId = 0;
private HashSet<Account> selectedAccounts = new();
private IEnumerable<TaskOption> AvailableOptions => Options.Where(o => o.Category == selectedCategory);
@@ -159,6 +178,11 @@
private IEnumerable<Account> FilteredAccounts =>
accounts.Where(a =>
{
if (filterAccountCategoryId > 0 && a.CategoryId != filterAccountCategoryId)
return false;
if (filterAccountCategoryId == -1 && a.CategoryId != null)
return false;
if (string.IsNullOrWhiteSpace(accountSearch))
return true;
var q = accountSearch.Trim();
@@ -170,9 +194,23 @@
protected override async Task OnInitializedAsync()
{
EnsureTaskTypeValid();
await LoadCategories();
await LoadAccounts();
}
private async Task LoadCategories()
{
try
{
var list = await CategoryManagement.GetAllCategoriesAsync();
categories = list.OrderBy(c => c.Id).ToList();
}
catch
{
categories = new List<AccountCategory>();
}
}
private async Task LoadAccounts()
{
loadingAccounts = true;
@@ -201,9 +239,16 @@
}
}
private void SelectAll() => selectedAccounts = accounts.ToHashSet();
private void SelectAll() => selectedAccounts = FilteredAccounts.ToHashSet();
private void ClearSelection() => selectedAccounts = new HashSet<Account>();
private string GetAccountCategoryName(int? categoryId)
{
if (categoryId is not > 0)
return "未分类";
return categories.FirstOrDefault(c => c.Id == categoryId)?.Name ?? $"#{categoryId}";
}
private async Task Create()
{
if (creating)
@@ -14,7 +14,7 @@
<MudAlert Severity="Severity.Warning" Variant="Variant.Outlined" Dense="true">
将使用指定账号订阅频道/加入群组。支持输入多个链接/用户名,换行分隔。
<MudText Typo="Typo.body2" Class="mt-1">
支持:<b>https://t.me/xxx</b>、<b>t.me/+hash</b>、<b>@username</b>、<b>username</b>、<b>tg://join?invite=hash</b>
支持:<b>https://t.me/xxx</b>、<b>t.me/+hash</b>、<b>@@username</b>、<b>username</b>、<b>tg://join?invite=hash</b>
</MudText>
</MudAlert>
@@ -155,4 +155,3 @@
private void Cancel() => MudDialog.Close();
}