Итерация 3: инвентарь устройств

- Миграция devices (name, type, ip, mac, hostname, vendor, os, location, importance, status)
- Device model + DeviceRepository с полным CRUD
- DeviceService для бизнес-логики
- MergeSuggestionService для предложений объединения (MAC→90%, hostname→60%)
- DeviceController: список, создание, редактирование, карточка, удаление, создание из discovered_host
- Шаблоны: devices/index, devices/form, devices/show
- Dashboard с реальными счётчиками (устройства, новые находки)
- Кнопка «Создать устройство» в Discovery для новых хостов
- DeviceRepository + DeviceService + DeviceController в DI
This commit is contained in:
2026-05-26 07:50:37 +08:00
parent 177e44f015
commit 15772bc17e
13 changed files with 760 additions and 28 deletions
+38 -26
View File
@@ -6,15 +6,7 @@
<div class="card text-white bg-primary">
<div class="card-body">
<h5 class="card-title">Устройства</h5>
<p class="card-text display-6">0</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-success">
<div class="card-body">
<h5 class="card-title">Сервисы</h5>
<p class="card-text display-6">0</p>
<p class="card-text display-6"><?= $deviceCount ?></p>
</div>
</div>
</div>
@@ -22,6 +14,14 @@
<div class="card text-white bg-info">
<div class="card-body">
<h5 class="card-title">Новые находки</h5>
<p class="card-text display-6"><?= $newDiscoveries ?></p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-success">
<div class="card-body">
<h5 class="card-title">Сервисы</h5>
<p class="card-text display-6">0</p>
</div>
</div>
@@ -39,33 +39,45 @@
<div class="row">
<div class="col-md-6">
<div class="card mb-4">
<div class="card-header">
Последние найденные хосты
</div>
<div class="card-header">Последние сканирования</div>
<div class="card-body">
<p class="text-muted">Нет данных. Запустите сканирование сети.</p>
<?php if (empty($recentScans)): ?>
<p class="text-muted">Нет запусков сканирования.</p>
<?php else: ?>
<table class="table table-sm">
<thead><tr><th>Тип</th><th>Статус</th><th>Когда</th></tr></thead>
<tbody>
<?php foreach ($recentScans as $scan): ?>
<tr>
<td><?= htmlspecialchars($scan->type) ?></td>
<td>
<?php
$badge = match ($scan->status) {
'pending' => 'bg-warning', 'running' => 'bg-info',
'done' => 'bg-success', 'failed' => 'bg-danger',
default => 'bg-secondary',
};
?>
<span class="badge <?= $badge ?>"><?= htmlspecialchars($scan->status) ?></span>
</td>
<td><?= $scan->createdAt->format('m-d H:i') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card mb-4">
<div class="card-header">
Последние события
</div>
<div class="card-header">Быстрые действия</div>
<div class="card-body">
<p class="text-muted">Нет событий.</p>
<a href="/discovery" class="btn btn-outline-primary mb-2">Сканирование сети</a>
<a href="/devices/create" class="btn btn-outline-secondary mb-2">Добавить устройство</a>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
Последний скан сети
</div>
<div class="card-body">
<p class="text-muted">Сканирование ещё не запускалось.</p>
</div>
</div>
<?php $content = ob_get_clean(); ?>
<?php require dirname(__DIR__) . '/layout.php'; ?>