Исправление: кнопки работают, добавлены характеристики/срок/место поставки, пустые срезы

This commit is contained in:
tore 2026-09-14 20:33:55 +00:00
parent 1621309339
commit ba1d4344aa

View File

@ -20,7 +20,7 @@
.group-card { border: 1px solid var(--kt-ai-border); border-radius: var(--kt-ai-radius-xl); padding: var(--kt-ai-space-5); background: var(--kt-ai-card-bg); }
.group-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-3); }
.group-items { display: flex; flex-direction: column; gap: var(--kt-ai-space-2); margin: var(--kt-ai-space-3) 0; }
.group-item { display: grid; grid-template-columns: auto 1fr auto auto auto; gap: var(--kt-ai-space-3); align-items: center; padding: var(--kt-ai-space-3); border: 1px solid var(--kt-ai-border); border-radius: var(--kt-ai-radius-lg); }
.group-item { display: grid; grid-template-columns: auto 1.8fr auto auto auto; gap: var(--kt-ai-space-3); align-items: start; padding: var(--kt-ai-space-3); border: 1px solid var(--kt-ai-border); border-radius: var(--kt-ai-radius-lg); }
.group-item.selected { background: var(--kt-ai-bg-soft); border-color: var(--kt-ai-primary); }
.item-checkbox { width: 18px; height: 18px; cursor: pointer; }
.item-name { font-size: var(--kt-ai-text-sm); }
@ -100,6 +100,8 @@
<option value="2025">2025 год</option>
<option value="q1">Q1 2026</option>
<option value="q2">Q2 2026</option>
<option value="q3">Q3 2026</option>
<option value="q4">Q4 2026</option>
</select>
<span data-kt-filter-note style="font-size:var(--kt-ai-text-xs);color:var(--kt-ai-fg-muted);margin-left:var(--kt-ai-space-2)">в демо не меняет набор</span>
</div>
@ -108,9 +110,9 @@
</div>
<div id="empty-state" class="empty-state" style="display:none">
<div class="empty-icon">✅</div>
<h3 style="margin-bottom:var(--kt-ai-space-2)">Все позиции разобраны</h3>
<p>Нет групп для обработки с выбранными фильтрами</p>
<div class="empty-icon" id="empty-icon">✅</div>
<h3 style="margin-bottom:var(--kt-ai-space-2)" id="empty-title">Все позиции разобраны</h3>
<p id="empty-text">Нет групп для обработки с выбранными фильтрами</p>
</div>
<div class="groups-list" id="groups-container"></div>
@ -134,56 +136,79 @@
</div>
<script>
// Реестр фильтров по требованию брифа
const FILTERS = [
{ id: 'category', label: 'Категория', affects: ['table', 'kpi'] },
{ id: 'status', label: 'Статус', affects: ['table', 'kpi'] },
{ id: 'period', label: 'Период', affects: ['table'], demoOnly: true }
];
// Демо-данные: группы похожих позиций годового плана закупок
const DEMO_DATA = [
{
id: 'group-1',
status: 'new',
items: [
{ code: 'ZKP-2026-00142', name: 'Поставка компьютерного оборудования для нужд департамента', amount: 2450000, category: 'it', year: '2026', quarter: 'q1' },
{ code: 'ZKP-2026-00189', name: 'Закупка компьютерной техники для офисов', amount: 2380000, category: 'it', year: '2026', quarter: 'q1' },
{ code: 'ZKP-2026-00201', name: 'Поставка ПК и периферийного оборудования', amount: 2510000, category: 'it', year: '2026', quarter: 'q1' }
{ code: 'ZKP-2026-00142', name: 'Поставка компьютерного оборудования для нужд департамента', amount: 2450000, category: 'it', year: '2026', quarter: 'q1', specs: 'ПК: Core i5, 16GB, 512GB SSD; Мониторы 24"', deliveryDate: '15.04.2026', deliveryPlace: 'г. Алматы, пр. Абая 125, склад №3' },
{ code: 'ZKP-2026-00189', name: 'Закупка компьютерной техники для офисов', amount: 2380000, category: 'it', year: '2026', quarter: 'q1', specs: 'Ноутбуки: Core i5, 8GB, 256GB SSD; Мыши, клавиатуры', deliveryDate: '20.04.2026', deliveryPlace: 'г. Астана, ул. Сыганак 23, офис 401' },
{ code: 'ZKP-2026-00201', name: 'Поставка ПК и периферийного оборудования', amount: 2510000, category: 'it', year: '2026', quarter: 'q1', specs: 'Моноблоки 24", Core i3, 8GB, 1TB HDD; Принтеры МФУ', deliveryDate: '10.05.2026', deliveryPlace: 'г. Алматы, пр. Абая 125, склад №3' }
]
},
{
id: 'group-2',
status: 'new',
items: [
{ code: 'ZKP-2026-00312', name: 'Услуги по технической поддержке программного обеспечения', amount: 890000, category: 'services', year: '2026', quarter: 'q2' },
{ code: 'ZKP-2026-00345', name: 'Техническая поддержка и сопровождение ПО', amount: 920000, category: 'services', year: '2026', quarter: 'q2' }
{ code: 'ZKP-2026-00312', name: 'Услуги по технической поддержке программного обеспечения', amount: 890000, category: 'services', year: '2026', quarter: 'q2', specs: 'ПО: 1С, Windows Server, антивирусы; 12 месяцев', deliveryDate: '01.06.2026', deliveryPlace: 'Удалённая поддержка + выезд в офисы' },
{ code: 'ZKP-2026-00345', name: 'Техническая поддержка и сопровождение ПО', amount: 920000, category: 'services', year: '2026', quarter: 'q2', specs: 'Сопровождение: 1С, CRM, документооборот; 12 месяцев', deliveryDate: '15.06.2026', deliveryPlace: 'г. Алматы, пр. Абая 125, серверная' }
]
},
{
id: 'group-3',
status: 'new',
items: [
{ code: 'ZKP-2026-00478', name: 'Приобретение кабельной продукции для магистральных линий', amount: 15600000, category: 'materials', year: '2026', quarter: 'q2' },
{ code: 'ZKP-2026-00489', name: 'Поставка кабеля и проводников для сетей связи', amount: 15200000, category: 'materials', year: '2026', quarter: 'q2' },
{ code: 'ZKP-2026-00501', name: 'Кабельно-проводниковая продукция для строительства ЛЭП', amount: 14900000, category: 'materials', year: '2026', quarter: 'q2' }
{ code: 'ZKP-2026-00478', name: 'Приобретение кабельной продукции для магистральных линий', amount: 15600000, category: 'materials', year: '2026', quarter: 'q2', specs: 'Кабель оптический 48 волокон, 12 км; муфты, кроссы', deliveryDate: '10.07.2026', deliveryPlace: 'г. Шымкент, ул. Желтоксан 45, склад связи' },
{ code: 'ZKP-2026-00489', name: 'Поставка кабеля и проводников для сетей связи', amount: 15200000, category: 'materials', year: '2026', quarter: 'q2', specs: 'Кабель медный UTP cat.6, 25 км; коннекторы RJ45', deliveryDate: '25.07.2026', deliveryPlace: 'г. Тараз, пр. Толе би 89, РТС' },
{ code: 'ZKP-2026-00501', name: 'Кабельно-проводниковая продукция для строительства ЛЭП', amount: 14900000, category: 'materials', year: '2026', quarter: 'q2', specs: 'Провод СИП-3 70мм², 8 км; арматура, изоляторы', deliveryDate: '05.08.2026', deliveryPlace: 'г. Кызылорда, ул. Байтурсынова 12, склад №7' }
]
},
{
id: 'group-4',
status: 'new',
items: [
{ code: 'ZKP-2026-00623', name: 'Строительно-монтажные работы по реконструкции здания', amount: 42000000, category: 'construction', year: '2026', quarter: 'q1' },
{ code: 'ZKP-2026-00634', name: 'Реконструкция административного здания с капитальным ремонтом', amount: 43500000, category: 'construction', year: '2026', quarter: 'q1' }
{ code: 'ZKP-2026-00623', name: 'Строительно-монтажные работы по реконструкции здания', amount: 42000000, category: 'construction', year: '2026', quarter: 'q1', specs: 'Реконструкция 2 этажа, 850 м²; фасад, кровля, инженерия', deliveryDate: '30.09.2026', deliveryPlace: 'г. Алматы, пр. Абая 125, здание А' },
{ code: 'ZKP-2026-00634', name: 'Реконструкция административного здания с капитальным ремонтом', amount: 43500000, category: 'construction', year: '2026', quarter: 'q1', specs: 'Капремонт 1-3 этажей, 1200 м²; замена коммуникаций', deliveryDate: '15.10.2026', deliveryPlace: 'г. Астана, ул. Сыганак 23, корпус 2' }
]
},
{
id: 'group-5',
status: 'new',
items: [
{ code: 'ZKP-2025-01234', name: 'Услуги уборки служебных помещений', amount: 3200000, category: 'services', year: '2025', quarter: 'q4' },
{ code: 'ZKP-2025-01256', name: 'Клининговые услуги для офисных площадей', amount: 3100000, category: 'services', year: '2025', quarter: 'q4' }
{ code: 'ZKP-2025-01234', name: 'Услуги уборки служебных помещений', amount: 3200000, category: 'services', year: '2025', quarter: 'q4', specs: 'Ежедневная уборка, 2500 м²; моющие средства включены', deliveryDate: '01.12.2025', deliveryPlace: 'г. Алматы, пр. Абая 125, все здания' },
{ code: 'ZKP-2025-01256', name: 'Клининговые услуги для офисных площадей', amount: 3100000, category: 'services', year: '2025', quarter: 'q4', specs: 'Комплексная уборка, 2200 м²; химчистка мебели', deliveryDate: '10.12.2025', deliveryPlace: 'г. Астана, ул. Сыганак 23, офисы 3-5 этажи' }
]
},
{
id: 'group-6',
status: 'new',
items: [
{ code: 'ZKP-2026-00789', name: 'Поставка серверного оборудования и систем хранения', amount: 28700000, category: 'it', year: '2026', quarter: 'q3' },
{ code: 'ZKP-2026-00801', name: 'Закупка серверов и СХД для дата-центра', amount: 29100000, category: 'it', year: '2026', quarter: 'q3' }
{ code: 'ZKP-2026-00789', name: 'Поставка серверного оборудования и систем хранения', amount: 28700000, category: 'it', year: '2026', quarter: 'q3', specs: 'Серверы 2U: 2xXeon, 128GB, RAID; СХД 100ТБ', deliveryDate: '20.09.2026', deliveryPlace: 'г. Алматы, пр. Абая 125, ЦОД' },
{ code: 'ZKP-2026-00801', name: 'Закупка серверов и СХД для дата-центра', amount: 29100000, category: 'it', year: '2026', quarter: 'q3', specs: 'Серверы 4U: 4xXeon, 256GB, NVMe; СХД 200ТБ FC', deliveryDate: '01.10.2026', deliveryPlace: 'г. Астана, пр. Мангилик Ел 55, ЦОД' }
]
},
{
id: 'group-7',
status: 'new',
items: [
{ code: 'ZKP-2026-00912', name: 'Поставка расходных материалов для оргтехники', amount: 1850000, category: 'materials', year: '2026', quarter: 'q4', specs: 'Картриджи: HP, Canon, Kyocera; бумага А4, 500 пачек', deliveryDate: '15.11.2026', deliveryPlace: 'г. Алматы, пр. Абая 125, склад канцтоваров' },
{ code: 'ZKP-2026-00934', name: 'Закупка тонеров и картриджей для принтеров', amount: 1920000, category: 'materials', year: '2026', quarter: 'q4', specs: 'Тонер-картриджи: Samsung, Xerox, Brother; 300 шт', deliveryDate: '25.11.2026', deliveryPlace: 'г. Шымкент, ул. Желтоксан 45, склад №2' }
]
},
{
id: 'group-8',
status: 'new',
items: [
{ code: 'ZKP-2026-01045', name: 'Услуги охраны объектов связи', amount: 12500000, category: 'services', year: '2026', quarter: 'q1', specs: 'Круглосуточная охрана, 15 объектов; пультовая охрана', deliveryDate: '01.01.2026', deliveryPlace: 'г. Алматы и Алматинская область, 15 РТС' },
{ code: 'ZKP-2026-01067', name: 'Охрана зданий и территорий компании', amount: 12800000, category: 'services', year: '2026', quarter: 'q1', specs: 'Физическая охрана, 18 постов; видеонаблюдение', deliveryDate: '15.01.2026', deliveryPlace: 'г. Астана и области, офисы и склады' }
]
}
];
@ -251,9 +276,14 @@ function renderGroup(group, index) {
itemsHtml += `
<div class="group-item ${isSelected ? 'selected' : ''}" data-group="${group.id}" data-item="${itemIndex}">
<input type="checkbox" class="item-checkbox" ${isSelected ? 'checked' : ''} ${isProcessed ? 'disabled' : ''}>
<div>
<div class="item-name">${item.name}</div>
<div style="min-width:0">
<div class="item-name" style="margin-bottom:var(--kt-ai-space-1)">${item.name}</div>
<div class="item-code">${item.code}</div>
<div style="font-size:var(--kt-ai-text-xs);color:var(--kt-ai-fg-muted);margin-top:var(--kt-ai-space-1)">
<div style="margin-bottom:2px"><strong>Характеристики:</strong> ${item.specs}</div>
<div style="margin-bottom:2px"><strong>Срок поставки:</strong> ${item.deliveryDate}</div>
<div><strong>Место:</strong> ${item.deliveryPlace}</div>
</div>
</div>
<div class="item-category"><span class="kt-ai-chip" data-tone="gray">${CATEGORY_NAMES[item.category]}</span></div>
<div class="item-amount">${formatAmount(item.amount)}</div>
@ -332,12 +362,35 @@ function updateKPI() {
function renderGroups() {
const container = document.getElementById('groups-container');
const emptyState = document.getElementById('empty-state');
const emptyTitle = document.getElementById('empty-title');
const emptyText = document.getElementById('empty-text');
const emptyIcon = document.getElementById('empty-icon');
const filtered = filterGroups();
if (filtered.length === 0) {
container.style.display = 'none';
emptyState.style.display = 'block';
document.getElementById('selection-panel').style.display = 'none';
// Определяем причину пустого состояния
const hasProcessedOnly = appState.groups.every(g => g.status === 'confirmed' || g.status === 'rejected');
if (hasProcessedOnly && appState.filters.status === 'all') {
emptyIcon.textContent = '✅';
emptyTitle.textContent = 'Все позиции разобраны';
emptyText.textContent = 'Нет групп для обработки';
} else if (appState.filters.period === 'q3' || appState.filters.period === 'q4') {
emptyIcon.textContent = '📭';
emptyTitle.textContent = 'Нет данных';
emptyText.textContent = `За выбранный период (${document.getElementById('filter-period').options[document.getElementById('filter-period').selectedIndex].text}) данных нет`;
} else if (appState.filters.status !== 'all') {
emptyIcon.textContent = '🔍';
emptyTitle.textContent = 'Ничего не найдено';
emptyText.textContent = `Нет групп со статусом "${document.getElementById('filter-status').options[document.getElementById('filter-status').selectedIndex].text}"`;
} else {
emptyIcon.textContent = '📭';
emptyTitle.textContent = 'Нет данных';
emptyText.textContent = 'Нет групп для обработки с выбранными фильтрами';
}
return;
}
@ -456,12 +509,14 @@ document.addEventListener('DOMContentLoaded', function() {
document.getElementById('btn-confirm').addEventListener('click', function() {
if (appState.selectedItems.size === 0) return;
const comment = document.getElementById('group-comment').value || 'Подтверждено пользователем';
const processedGroups = new Set();
appState.selectedItems.forEach(key => {
const [groupId, itemIndex] = key.split('-');
const group = appState.groups.find(g => g.id === groupId);
if (group) {
if (group && group.status === 'new') {
group.status = 'confirmed';
group.comment = comment;
processedGroups.add(groupId);
}
});
appState.selectedItems.clear();
@ -473,12 +528,14 @@ document.addEventListener('DOMContentLoaded', function() {
document.getElementById('btn-reject').addEventListener('click', function() {
if (appState.selectedItems.size === 0) return;
const comment = document.getElementById('group-comment').value || 'Отклонено пользователем';
const processedGroups = new Set();
appState.selectedItems.forEach(key => {
const [groupId, itemIndex] = key.split('-');
const group = appState.groups.find(g => g.id === groupId);
if (group) {
if (group && group.status === 'new') {
group.status = 'rejected';
group.comment = comment;
processedGroups.add(groupId);
}
});
appState.selectedItems.clear();