feat(admin): панельная идентичность под Remnawave 3.0.0

Remnawave 3.0.0 удалил `uuid` из модели пользователя — панельный аккаунт
адресуется числовым `id`, и бот переименовал соответствующие поля своего
API. Без этих правок вкладка Sync показывала бы «не привязан» у ВСЕХ
пользователей: оба операнда стали бы undefined, причём без ошибки TS —
интерфейсы продолжали бы декларировать несуществующие поля.

Типы: `UserDetailResponse.remnawave_uuid` → `remnawave_id: number | null`,
`PanelSyncStatusResponse.remnawave_uuid` → `remnawave_id`,
`SyncToPanelResponse.panel_uuid` → `panel_user_id`,
`PanelUserInfo.uuid` → `id: number` (бэкенд отдаёт его обязательным).

В SyncTab используется `??`, а не `||`: идентификатор числовой, и `0`
нужно отличать от отсутствия значения. Ярлык — «Remnawave ID».

Локаль: ключ настройки бота переименован в TRAFFIC_EXCLUDED_USER_IDS,
подпись обновлена — значения теперь числовые id, а не UUID.
This commit is contained in:
Fringg
2026-08-02 19:38:11 +03:00
parent 653d683835
commit e840ed2b60
3 changed files with 10 additions and 10 deletions

View File

@@ -142,7 +142,7 @@ export interface UserDetailResponse {
promo_offer_discount_source: string | null;
promo_offer_discount_expires_at: string | null;
recent_transactions: UserTransactionItem[];
remnawave_uuid: string | null;
remnawave_id: number | null;
}
export interface UserPanelInfo {
@@ -271,7 +271,7 @@ export interface UserAvailableTariffsResponse {
// Sync types
export interface PanelUserInfo {
uuid: string | null;
id: number;
short_uuid: string | null;
username: string | null;
status: string | null;
@@ -295,7 +295,7 @@ export interface SyncToPanelResponse {
success: boolean;
message: string;
action: string;
panel_uuid: string | null;
panel_user_id: number | null;
changes: Record<string, unknown>;
errors: string[];
}
@@ -303,7 +303,7 @@ export interface SyncToPanelResponse {
export interface PanelSyncStatusResponse {
user_id: number;
telegram_id: number;
remnawave_uuid: string | null;
remnawave_id: number | null;
subscription_id: number | null;
subscription_tariff_name: string | null;
last_sync: string | null;

View File

@@ -151,16 +151,16 @@ export function SyncTab({
</div>
)}
{/* UUID info */}
{/* Panel identity */}
<div className="rounded-xl bg-dark-800/50 p-4">
{syncStatus?.subscription_tariff_name && (
<div className="mb-2 text-xs text-dark-500">{syncStatus.subscription_tariff_name}</div>
)}
<div className="mb-1 text-sm text-dark-400">Remnawave UUID</div>
<div className="mb-1 text-sm text-dark-400">Remnawave ID</div>
<div className="break-all font-mono text-sm text-dark-100">
{syncStatus?.remnawave_uuid ||
user.remnawave_uuid ||
t('admin.users.detail.sync.notLinked')}
{/* Remnawave 3.0.0 identifies a panel user by a numeric id, so 0 is not
a valid id but ?? would still render it — check for null explicitly. */}
{syncStatus?.remnawave_id ?? user.remnawave_id ?? t('admin.users.detail.sync.notLinked')}
</div>
</div>

View File

@@ -2580,7 +2580,7 @@
"Traffic Daily Check Enabled": "Ежедневная проверка",
"Traffic Daily Check Time": "Время проверки",
"Traffic Daily Threshold Gb": "Порог в день (ГБ)",
"Traffic Excluded User Uuids": "Исключённые UUID",
"Traffic Excluded User Ids": "Исключённые ID пользователей панели",
"Traffic Fast Check Enabled": "Быстрая проверка",
"Traffic Fast Check Interval Minutes": "Интервал (мин)",
"Traffic Fast Check Threshold Gb": "Порог (ГБ)",