ty-poluchil-opisanie-etot-ek/index.html

327 lines
13 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ru" data-theme="light" data-kt-data-mode="demo">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Учёт кабельной продукции</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<style>
a.kt-ai-btn { text-decoration: none; }
.kt-ai-app { min-height: 100vh; background: var(--kt-ai-bg); color: var(--kt-ai-fg); font-family: var(--kt-ai-font-sans); }
.app-header { display: flex; align-items: center; gap: var(--kt-ai-space-4); padding: var(--kt-ai-space-4) 0; }
.app-title { font-size: var(--kt-ai-text-xl); font-weight: var(--kt-ai-weight-semibold); }
.kpi-section { padding: var(--kt-ai-space-6) 0; }
.filters-section { padding: var(--kt-ai-space-4) 0; display: flex; gap: var(--kt-ai-space-4); flex-wrap: wrap; align-items: center; }
.table-section { padding: var(--kt-ai-space-4) 0; }
.kt-ai-table-wrap { overflow-x: auto; }
.kt-ai-table { width: 100%; border-collapse: collapse; }
.kt-ai-table th { text-align: left; padding: var(--kt-ai-space-3) var(--kt-ai-space-4); font-weight: var(--kt-ai-weight-medium); color: var(--kt-ai-fg-muted); border-bottom: 1px solid var(--kt-ai-border); }
.kt-ai-table td { padding: var(--kt-ai-space-3) var(--kt-ai-space-4); border-bottom: 1px solid var(--kt-ai-border-strong); vertical-align: middle; }
.kt-ai-table tr:hover td { background: var(--kt-ai-bg-soft); }
.kt-ai-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.kt-ai-table .actions { white-space: nowrap; }
.empty-state { text-align: center; padding: var(--kt-ai-space-12) var(--kt-ai-space-4); color: var(--kt-ai-fg-muted); }
.form-section { padding: var(--kt-ai-space-6) 0; }
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--kt-ai-space-4); max-width: 800px; }
.filter-note { font-size: var(--kt-ai-text-xs); color: var(--kt-ai-fg-faint); margin-left: var(--kt-ai-space-2); }
</style>
</head>
<body class="kt-ai-app">
<div class="kt-ai-wrap">
<header class="app-header">
<img src="https://code.vibe42.kz/tore/aitu/kt-logo.svg" alt="Казахтелеком" height="28">
<span class="app-title">Учёт кабельной продукции</span>
<span class="kt-ai-spacer"></span>
<span class="kt-ai-chip" data-tone="orange">Демо-данные</span>
</header>
</div>
<section class="kpi-section">
<div class="kt-ai-wrap">
<div class="kt-ai-kpi-strip">
<div class="kt-ai-kpi">
<div class="value" id="kpi-total">0</div>
<div class="label">Всего</div>
<div class="hint">кабельных позиций</div>
</div>
<div class="kt-ai-kpi">
<div class="value" id="kpi-in-work">0</div>
<div class="label">В работе</div>
<div class="hint">активных задач</div>
</div>
<div class="kt-ai-kpi">
<div class="value" id="kpi-ready">0</div>
<div class="label">Готово</div>
<div class="hint">завершено</div>
</div>
<div class="kt-ai-kpi">
<div class="value" id="kpi-meters">0</div>
<div class="label">Метров</div>
<div class="hint">общая длина</div>
</div>
</div>
</div>
</section>
<section class="filters-section">
<div class="kt-ai-wrap">
<div class="kt-ai-field" style="min-width: 180px;">
<label>Тип кабеля</label>
<select class="kt-ai-select" id="filter-type">
<option value="">Все типы</option>
<option value="Силовой">Силовой</option>
<option value="Оптоволоконный">Оптоволоконный</option>
<option value="Коаксиальный">Коаксиальный</option>
<option value="Контрольный">Контрольный</option>
</select>
</div>
<div class="kt-ai-field" style="min-width: 160px;">
<label>Статус</label>
<select class="kt-ai-select" id="filter-status">
<option value="">Все статусы</option>
<option value="new">Новый</option>
<option value="in-work">В работе</option>
<option value="ready">Готово</option>
<option value="archived">Архив</option>
</select>
<span class="filter-note" data-kt-filter-note>в демо не меняет KPI</span>
</div>
<div class="kt-ai-field" style="min-width: 200px;">
<label>Поиск</label>
<input class="kt-ai-input" id="filter-search" placeholder="Название или сечение...">
</div>
<span class="kt-ai-spacer"></span>
<button class="kt-ai-btn" data-variant="ghost" id="btn-reset">Сбросить</button>
</div>
</section>
<section class="table-section">
<div class="kt-ai-wrap">
<div class="kt-ai-table-wrap">
<table class="kt-ai-table">
<thead>
<tr>
<th>Название</th>
<th>Тип</th>
<th class="num">Сечение, мм²</th>
<th class="num">Длина, м</th>
<th>Статус</th>
<th>Дата</th>
<th class="actions">Действия</th>
</tr>
</thead>
<tbody id="cable-table-body"></tbody>
</table>
</div>
<div class="kt-ai-empty" id="empty-state" style="display: none;">
<div class="empty-state">
<p style="font-size: var(--kt-ai-text-lg); margin-bottom: var(--kt-ai-space-2);">Нет данных</p>
<p>По выбранным фильтрам ничего не найдено</p>
</div>
</div>
</div>
</section>
<section class="form-section">
<div class="kt-ai-wrap">
<div class="kt-ai-section-head">
<h2>Добавить кабель</h2>
<p>Заполните форму для создания новой записи</p>
</div>
<form id="add-cable-form" class="form-grid">
<div class="kt-ai-field">
<label>Название *</label>
<input class="kt-ai-input" name="name" required placeholder="Например: АВВГ 3х2.5">
</div>
<div class="kt-ai-field">
<label>Тип *</label>
<select class="kt-ai-select" name="type" required>
<option value="">Выберите тип</option>
<option value="Силовой">Силовой</option>
<option value="Оптоволоконный">Оптоволоконный</option>
<option value="Коаксиальный">Коаксиальный</option>
<option value="Контрольный">Контрольный</option>
</select>
</div>
<div class="kt-ai-field">
<label>Сечение, мм² *</label>
<input class="kt-ai-input" name="section" type="number" step="0.1" required placeholder="2.5">
</div>
<div class="kt-ai-field">
<label>Длина, м *</label>
<input class="kt-ai-input" name="length" type="number" required placeholder="100">
</div>
<div class="kt-ai-field">
<label>Статус *</label>
<select class="kt-ai-select" name="status" required>
<option value="new">Новый</option>
<option value="in-work">В работе</option>
<option value="ready">Готово</option>
</select>
</div>
<div class="kt-ai-field">
<label>Дата *</label>
<input class="kt-ai-input" name="date" type="date" required>
</div>
<div style="grid-column: 1 / -1;">
<button class="kt-ai-btn" data-variant="primary" type="submit">Добавить в учёт</button>
</div>
</form>
</div>
</section>
<div class="kt-ai-wrap kt-ai-pagefoot">
<span>© 2026 Казахтелеком — Учёт кабельной продукции</span>
<span class="kt-ai-spacer"></span>
<span>Демо-прототип</span>
</div>
<script>
const STORAGE_KEY = 'kt_cables_data';
const DEFAULT_CABLES = [
{ id: 1, name: 'АВВГ 3х2.5', type: 'Силовой', section: 2.5, length: 150, status: 'in-work', date: '2026-09-10' },
{ id: 2, name: 'АВВГ 3х4.0', type: 'Силовой', section: 4.0, length: 200, status: 'new', date: '2026-09-12' },
{ id: 3, name: 'АВВГ 3х2.5', type: 'Силовой', section: 2.5, length: 80, status: 'ready', date: '2026-09-08' },
{ id: 4, name: 'ОКЛ-Т 4х9', type: 'Оптоволоконный', section: 9, length: 500, status: 'in-work', date: '2026-09-11' },
{ id: 5, name: 'КВВГ 7х1.5', type: 'Контрольный', section: 1.5, length: 120, status: 'archived', date: '2026-09-05' }
];
function getCables() {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored) {
const parsed = JSON.parse(stored);
return parsed.userCables || [];
}
return DEFAULT_CABLES;
}
function saveCable(cable) {
const stored = localStorage.getItem(STORAGE_KEY);
let data = stored ? JSON.parse(stored) : { userCables: [] };
if (!data.userCables) data.userCables = [];
cable.id = Date.now();
data.userCables.push(cable);
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
}
function deleteCable(id) {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored) {
let data = JSON.parse(stored);
if (data.userCables) {
data.userCables = data.userCables.filter(c => c.id !== id);
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
}
}
}
function getStatusChip(status) {
const map = {
'new': { label: 'Новый', tone: 'blue' },
'in-work': { label: 'В работе', tone: 'orange' },
'ready': { label: 'Готово', tone: 'green' },
'archived': { label: 'Архив', tone: 'gray' }
};
const s = map[status] || { label: status, tone: 'gray' };
return `<span class="kt-ai-chip" data-tone="${s.tone}">${s.label}</span>`;
}
function formatDate(dateStr) {
const d = new Date(dateStr);
return d.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year: '2-digit' });
}
function updateKPI(cables) {
document.getElementById('kpi-total').textContent = cables.length;
document.getElementById('kpi-in-work').textContent = cables.filter(c => c.status === 'in-work').length;
document.getElementById('kpi-ready').textContent = cables.filter(c => c.status === 'ready').length;
document.getElementById('kpi-meters').textContent = cables.reduce((sum, c) => sum + (parseInt(c.length) || 0), 0);
}
function renderTable(cables) {
const tbody = document.getElementById('cable-table-body');
const empty = document.getElementById('empty-state');
if (cables.length === 0) {
tbody.innerHTML = '';
empty.style.display = 'block';
return;
}
empty.style.display = 'none';
tbody.innerHTML = cables.map(c => `
<tr>
<td>${c.name}</td>
<td>${c.type}</td>
<td class="num">${c.section}</td>
<td class="num">${c.length}</td>
<td>${getStatusChip(c.status)}</td>
<td>${formatDate(c.date)}</td>
<td class="actions">
<button class="kt-ai-btn" data-variant="ghost" data-size="sm" onclick="deleteRow(${c.id})">Удалить</button>
</td>
</tr>
`).join('');
}
function applyFilters() {
const typeFilter = document.getElementById('filter-type').value;
const statusFilter = document.getElementById('filter-status').value;
const searchFilter = document.getElementById('filter-search').value.toLowerCase();
let cables = getCables();
if (typeFilter) cables = cables.filter(c => c.type === typeFilter);
if (statusFilter) cables = cables.filter(c => c.status === statusFilter);
if (searchFilter) cables = cables.filter(c =>
c.name.toLowerCase().includes(searchFilter) ||
String(c.section).includes(searchFilter)
);
updateKPI(cables);
renderTable(cables);
}
function deleteRow(id) {
deleteCable(id);
applyFilters();
}
document.getElementById('filter-type').addEventListener('change', applyFilters);
document.getElementById('filter-status').addEventListener('change', applyFilters);
document.getElementById('filter-search').addEventListener('input', applyFilters);
document.getElementById('btn-reset').addEventListener('click', () => {
document.getElementById('filter-type').value = '';
document.getElementById('filter-status').value = '';
document.getElementById('filter-search').value = '';
applyFilters();
});
document.getElementById('add-cable-form').addEventListener('submit', (e) => {
e.preventDefault();
const form = e.target;
const cable = {
name: form.name.value,
type: form.type.value,
section: parseFloat(form.section.value),
length: parseInt(form.length.value),
status: form.status.value,
date: form.date.value
};
saveCable(cable);
form.reset();
applyFilters();
});
applyFilters();
</script>
</body>
</html>