Add instructions management functionality and update related components
- Introduced new endpoints for managing instruction intros and tabs, allowing admins to create, update, and delete instructional content. - Enhanced the FactoryResetCommandHandler to include the seeding of instruction data during a factory reset. - Updated the database schema to include InstructionIntro and InstructionTab entities, with corresponding migrations. - Improved frontend routing and components to support the new instructions section, including a dedicated page for displaying instructions and tabs. - Enhanced API documentation to reflect the new instruction management features and their expected request/response formats. - Added localization support for the new instructions functionality in both Russian and English.
This commit is contained in:
+26
-3
@@ -105,6 +105,27 @@ status, createdAt }`. `expiresAt` всегда `null` (лимиты по сро
|
||||
```
|
||||
Значение `OsPlatform` в C#/JSON — `IOS` (не `iOS`).
|
||||
|
||||
## Instructions — страница инструкций
|
||||
|
||||
Вводный markdown-текст (singleton) над вкладками + дополнительные вкладки, обе части редактируются
|
||||
из админки. Встроенная вкладка «Приложения» (каталог `ClientApp`) в этот API не входит — фронт
|
||||
всегда рисует её первой, сама её достаёт через `GET /api/apps`.
|
||||
|
||||
| Метод | Путь | Роль | Тело запроса | Тело ответа |
|
||||
| ------ | ------------------------------------- | ----- | ----------------------------------- | ------------- |
|
||||
| GET | `/api/instructions/intro` | user | — | `InstructionIntroDto` |
|
||||
| GET | `/api/instructions/tabs` | user | — | `InstructionTabDto[]` (сортировка `SortOrder asc`) |
|
||||
| PUT | `/api/admin/instructions/intro` | admin | `{ body }` | `InstructionIntroDto` |
|
||||
| POST | `/api/admin/instructions/tabs` | admin | `{ title, body, sortOrder }` | `InstructionTabDto` |
|
||||
| PUT | `/api/admin/instructions/tabs/{id}` | admin | `{ title, body, sortOrder }` | `InstructionTabDto` |
|
||||
| DELETE | `/api/admin/instructions/tabs/{id}` | admin | — | `204 No Content` |
|
||||
|
||||
`PUT /api/admin/instructions/intro` — get-or-create (строка одна на всю систему; если её ещё нет,
|
||||
создаётся, иначе обновляется на месте). `GET /api/instructions/intro` никогда не 404-ит — если строка
|
||||
ещё не создана, отдаёт `{ id: "00000000-0000-0000-0000-000000000000", body: "", updatedAt: <MinValue> }`,
|
||||
чтобы публичная страница не падала. Вкладки — обычный CRUD без статуса черновик/опубликовано, как
|
||||
у `NewsPostDto`.
|
||||
|
||||
## News — лента новостей
|
||||
|
||||
| Метод | Путь | Роль | Тело запроса | Тело ответа |
|
||||
@@ -200,9 +221,11 @@ Support.CannotRequestAdminRole`), либо все три поля новой р
|
||||
(«Опасная зона») и требует ввести фразу-подтверждение в диалоге (не просто `confirm()`). Удаляет:
|
||||
всех пользователей кроме текущего админа, все `VpnConfig`/`TrafficSample` (конфиги сначала best-effort
|
||||
отзываются на нодах через `IXuiPanelGateway.RemoveClientAsync` — недоступная нода не блокирует сброс),
|
||||
все `Node`/`Inbound`, тикеты с перепиской/вложениями (+файлы), `NewsPost`, весь `AuditLog`, все
|
||||
кастомные роли (`AppRole.IsSystem == false`) и `ClientApp` — каталог приложений затем пересеивается
|
||||
через `IClientAppCatalogSeeder` (тот же сервис, что использует `DbInitializer` при первом старте).
|
||||
все `Node`/`Inbound`, тикеты с перепиской/вложениями (+файлы), `NewsPost`, `InstructionIntro`/
|
||||
`InstructionTab`, весь `AuditLog`, все кастомные роли (`AppRole.IsSystem == false`) и `ClientApp` —
|
||||
каталог приложений и вводный текст инструкций затем пересеиваются дефолтными значениями через
|
||||
`IClientAppCatalogSeeder`/`IInstructionIntroSeeder` (те же сервисы, что использует `DbInitializer`
|
||||
при первом старте); вкладки инструкций дефолтами не пересеиваются, как и новости.
|
||||
Не атомарно целиком (несколько `SaveChangesAsync` внутри хендлера, как и в `DeleteUserCommandHandler`) —
|
||||
при сбое посередине возможно частичное состояние, компенсации нет, это осознанный компромисс для
|
||||
редкой ручной админской операции. Финальная запись `FactoryReset` в аудит добавляется уже после
|
||||
|
||||
+36
-3
@@ -159,6 +159,38 @@ AppUser
|
||||
Массовая очистка отключённых (`IsEnabled = false`) — вкладка «Обслуживание»,
|
||||
`DELETE /api/admin/maintenance/apps/disabled`.
|
||||
|
||||
### InstructionIntro — вводный текст страницы инструкций
|
||||
Единственная строка в таблице (singleton) — markdown-текст над вкладками на странице «Инструкции»,
|
||||
редактируется админом. Никакой поддержки нескольких версий/языков нет.
|
||||
|
||||
| Поле | Тип | Заметки |
|
||||
| ----------- | ----------------- | ------------------------------------------------ |
|
||||
| `Id` | `Guid` | PK |
|
||||
| `Body` | `string` | Markdown-текст |
|
||||
| `UpdatedAt` | `DateTimeOffset` | |
|
||||
|
||||
`GET /api/instructions/intro` (активированным) читает; `PUT /api/admin/instructions/intro` (админ)
|
||||
делает get-or-create — если строки ещё нет (не сидировано), создаёт, иначе обновляет на месте.
|
||||
Сидируется дефолтным текстом при старте (`IInstructionIntroSeeder`, если таблица пуста) и заново
|
||||
после полного сброса панели (см. «Полный сброс панели» выше).
|
||||
|
||||
### InstructionTab — дополнительные вкладки инструкций
|
||||
Заголовок + markdown-текст, ведёт админ; на странице «Инструкции» отображаются вкладками рядом с
|
||||
встроенной вкладкой «Приложения» (каталог `ClientApp`, не хранится как `InstructionTab`).
|
||||
|
||||
| Поле | Тип | Заметки |
|
||||
| ----------- | ----------------- | ------------------------------------------------------- |
|
||||
| `Id` | `Guid` | PK |
|
||||
| `Title` | `string` | Заголовок вкладки |
|
||||
| `Body` | `string` | Markdown-текст |
|
||||
| `SortOrder` | `int` | Порядок вкладок (та же конвенция, что у `ClientApp`) |
|
||||
| `CreatedAt` | `DateTimeOffset` | |
|
||||
| `UpdatedAt` | `DateTimeOffset?` | |
|
||||
|
||||
Нет статуса черновик/опубликовано — публикация мгновенная, как у `NewsPost`. Полный CRUD только
|
||||
у админа (`/api/admin/instructions/tabs`); чтение — `GET /api/instructions/tabs` (активированным).
|
||||
Не пересеивается дефолтными вкладками — при полном сбросе панели просто удаляются.
|
||||
|
||||
### NewsPost — новости для пользователей
|
||||
Публикуются админом немедленно, видны всем залогиненным пользователям в хронологической ленте.
|
||||
|
||||
@@ -197,9 +229,10 @@ AppUser
|
||||
Вкладка «Обслуживание» → «Опасная зона» (спойлер + подтверждение фразой в диалоге, не просто
|
||||
`confirm()`) — `DELETE /api/admin/maintenance/factory-reset`. Возвращает панель к состоянию свежего
|
||||
деплоя: удаляет всех пользователей кроме текущего админа, конфиги (сначала best-effort отзываются
|
||||
на нодах 3x-ui), ноды/инбаунды, тикеты, новости, весь аудит и кастомные роли; каталог приложений
|
||||
пересеивается из `seed/client-apps.json`. Необратимо, не атомарно целиком — подробности и полный
|
||||
список удаляемого см. [api-design.md](api-design.md#admin--maintenance).
|
||||
на нодах 3x-ui), ноды/инбаунды, тикеты, новости, вводный текст и вкладки инструкций, весь аудит и
|
||||
кастомные роли; каталог приложений и вводный текст инструкций пересеиваются дефолтными значениями,
|
||||
вкладки инструкций — нет (пусто, как у новостей). Необратимо, не атомарно целиком — подробности и
|
||||
полный список удаляемого см. [api-design.md](api-design.md#admin--maintenance).
|
||||
|
||||
### AppUser — расширения (Identity)
|
||||
`AppUser` живёт в Identity (`Infrastructure`). **Логин — по `UserName`** (уникальный, обязательный).
|
||||
|
||||
Reference in New Issue
Block a user