Исправление: кнопки работают, добавлены характеристики/срок/место поставки, пустые срезы
This commit is contained in:
parent
1621309339
commit
ba1d4344aa
101
index.html
101
index.html
@ -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();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user