/
icedev
/
eks-present
Обзор
Документация
Войти
/
icedev
/
eks-present
Код
Запросы
0
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
building.html
324 строки
16 KB
ICEDEV
init
12 май 2026, 12:50
12 май 2026, 12:50
872c4b8
Код
Авторство
О чём код?
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Объект — подробности | EKS</title> <link rel="stylesheet" href="styles.css" /> </head> <body> <div class="container"> <header class="topbar"> <div class="brand" id="building-title">EKS | Объект</div> <nav class="nav"> <a class="nav-link" href="objects.html">← Ко всем объектам</a> <a class="nav-link" href="contractor.html">Подрядчик</a> <a class="nav-link" href="manager.html">Руководитель</a> <a class="nav-link" href="information.html">Информация</a> <a class="nav-link" href="requests.html">Реестр заявок</a> </nav> </header> <section class="glass-card section-card" id="building-summary"> <h1 class="title" id="building-name">Объект</h1> <p class="subtitle" id="building-description"> Загрузка данных по объекту… </p> <div class="grid" id="building-meta"> <!-- сюда JS подставит краткие метаданные --> </div> </section> <section class="glass-card section-card"> <h2 class="title" style="font-size: 22px; margin-bottom: 12px;">Системы объекта</h2> <p class="subtitle" style="margin-bottom: 16px;"> Список инженерных систем по объекту с ответственными подрядчиками и статусом готовности. </p> <form id="add-system-form" class="inline-form"> <div class="field" style="margin-bottom: 0;"> <label for="system-name">Система</label> <input id="system-name" name="name" type="text" placeholder="Вентиляция" required /> </div> <div class="field" style="margin-bottom: 0;"> <label for="system-contractor">Подрядчик</label> <input id="system-contractor" name="contractor" type="text" placeholder='ООО "Подрядчик"' required /> </div> <div class="field" style="margin-bottom: 0;"> <label for="system-progress">Готовность (%)</label> <input id="system-progress" name="progress" type="number" min="0" max="100" placeholder="75" required /> </div> <div style="display: flex; align-items: flex-end;"> <button class="btn btn-primary" type="submit" style="width: 100%;">Добавить систему</button> </div> </form> <div class="table-wrap"> <table id="systems-table"> <thead> <tr> <th>Система</th> <th>Подрядчик</th> <th>Степень готовности</th> <th class="actions-cell">Действия</th> </tr> </thead> <tbody> </tbody> </table> </div> </section> <section class="glass-card section-card"> <h2 class="title" style="font-size: 22px; margin-bottom: 12px;">Информация по системам</h2> <p class="subtitle" style="margin-bottom: 16px;"> Основная информация: проектная документация, исполнительная, акты и спецификации. </p> <form id="add-document-form" class="inline-form"> <div class="field" style="margin-bottom: 0;"> <label for="doc-system">Система</label> <input id="doc-system" name="system" type="text" placeholder="Вентиляция" required /> </div> <div class="field" style="margin-bottom: 0;"> <label for="doc-type">Тип документа</label> <input id="doc-type" name="type" type="text" placeholder="Проект" required /> </div> <div class="field" style="margin-bottom: 0;"> <label for="doc-code">Код/номер</label> <input id="doc-code" name="code" type="text" placeholder="HVAC-404-P-01" required /> </div> <div style="display: flex; align-items: flex-end;"> <button class="btn btn-primary" type="submit" style="width: 100%;">Добавить документ</button> </div> </form> <div id="documents-list" class="grid"> <!-- сюда JS подставит карточки документов --> </div> </section> </div> <script> const BUILDINGS_STORAGE_KEY = "eks_buildings_data"; const BUILDINGS = { "404": { name: 'Здание 404', description: 'Деловой центр, 6 инженерных систем, активная стадия отделочных работ.', meta: [ { label: 'Тип', value: 'Бизнес-центр' }, { label: 'Количество систем', value: '6' }, { label: 'Генподрядчик', value: 'ООО "ТехМонтаж"' }, { label: 'Степень готовности', value: '85%' }, ], systems: [ { id: "sys1", name: 'Вентиляция', contractor: 'ООО "ТехМонтаж"', progress: '90%', status: 'success' }, { id: "sys2", name: 'Отопление', contractor: 'ООО "ТехМонтаж"', progress: '80%', status: 'success' }, { id: "sys3", name: 'Кондиционирование', contractor: 'ООО "КлиматПро"', progress: '76%', status: 'success' }, { id: "sys4", name: 'Электроснабжение', contractor: 'ООО "ЭнергоСтрой"', progress: '70%', status: 'success' }, { id: "sys5", name: 'Слаботочные сети', contractor: 'ООО "СигналПро"', progress: '60%', status: 'warn' }, { id: "sys6", name: 'Пожарная автоматика', contractor: 'ООО "Безопасность+"', progress: '45%', status: 'warn' }, ], documents: [ { id: "doc1", system: 'Вентиляция', type: 'Проект', code: 'HVAC-404-P-01' }, { id: "doc2", system: 'Вентиляция', type: 'Исполнительная документация', code: 'HVAC-404-I-01' }, { id: "doc3", system: 'Электроснабжение', type: 'Схемы и спецификации', code: 'EL-404-S-02' }, { id: "doc4", system: 'Пожарная автоматика', type: 'Акт ПНР', code: 'FIRE-404-A-01' }, ], }, "405": { name: 'Здание 405', description: 'Жилой комплекс, 8 систем, в работе инженерные и отделочные этапы.', meta: [ { label: 'Тип', value: 'Жилой комплекс' }, { label: 'Количество систем', value: '8' }, { label: 'Генподрядчик', value: 'ООО "СигналПро"' }, { label: 'Степень готовности', value: '57%' }, ], systems: [ { id: "sys7", name: 'Слаботочные сети', contractor: 'ООО "СигналПро"', progress: '55%', status: 'warn' }, { id: "sys8", name: 'Интернет и ТВ', contractor: 'ООО "СигналПро"', progress: '60%', status: 'warn' }, { id: "sys9", name: 'Видеонаблюдение', contractor: 'ООО "СигналПро"', progress: '50%', status: 'warn' }, { id: "sys10", name: 'Лифтовое оборудование', contractor: 'ООО "ЛифтСервис"', progress: '45%', status: 'warn' }, ], documents: [ { id: "doc5", system: 'Слаботочные сети', type: 'Проект', code: 'LV-405-P-01' }, { id: "doc6", system: 'Слаботочные сети', type: 'Спецификация оборудования', code: 'LV-405-S-01' }, { id: "doc7", system: 'Видеонаблюдение', type: 'Паспорт системы', code: 'CCTV-405-PAS' }, ], }, "406": { name: 'Здание 406', description: 'Торгово-развлекательный центр, 7 систем, активно ведутся пусконаладочные работы.', meta: [ { label: 'Тип', value: 'ТРЦ' }, { label: 'Количество систем', value: '7' }, { label: 'Генподрядчик', value: 'ООО "Безопасность+"' }, { label: 'Степень готовности', value: '34%' }, ], systems: [ { id: "sys11", name: 'Пожарная автоматика', contractor: 'ООО "Безопасность+"', progress: '30%', status: 'danger' }, { id: "sys12", name: 'Система оповещения', contractor: 'ООО "Безопасность+"', progress: '40%', status: 'warn' }, { id: "sys13", name: 'Спринклерная система', contractor: 'ООО "Безопасность+"', progress: '32%', status: 'danger' }, ], documents: [ { id: "doc8", system: 'Пожарная автоматика', type: 'Проект', code: 'FIRE-406-P-01' }, { id: "doc9", system: 'Пожарная автоматика', type: 'Расчёты и схемы', code: 'FIRE-406-R-01' }, { id: "doc10", system: 'Система оповещения', type: 'Проект', code: 'PA-406-P-01' }, ], }, "407": { name: 'Здание 407', description: 'Логистический парк, 9 систем, основной фокус на энергетику и безопасность.', meta: [ { label: 'Тип', value: 'Логистический парк' }, { label: 'Количество систем', value: '9' }, { label: 'Генподрядчик', value: 'ООО "ЭнергоСтрой"' }, { label: 'Степень готовности', value: '76%' }, ], systems: [ { id: "sys14", name: 'Электроснабжение', contractor: 'ООО "ЭнергоСтрой"', progress: '80%', status: 'success' }, { id: "sys15", name: 'Освещение складов', contractor: 'ООО "ЭнергоСтрой"', progress: '78%', status: 'success' }, { id: "sys16", name: 'Системы контроля доступа', contractor: 'ООО "СигналПро"', progress: '65%', status: 'warn' }, ], documents: [ { id: "doc11", system: 'Электроснабжение', type: 'Проект', code: 'EL-407-P-01' }, { id: "doc12", system: 'Электроснабжение', type: 'Исполнительная документация', code: 'EL-407-I-01' }, { id: "doc13", system: 'Контроль доступа', type: 'Схемы и спецификации', code: 'ACS-407-S-01' }, ], }, }; function getBuildings() { const raw = localStorage.getItem(BUILDINGS_STORAGE_KEY); if (!raw) { localStorage.setItem(BUILDINGS_STORAGE_KEY, JSON.stringify(BUILDINGS)); return JSON.parse(JSON.stringify(BUILDINGS)); } try { const parsed = JSON.parse(raw); return parsed && typeof parsed === "object" ? parsed : JSON.parse(JSON.stringify(BUILDINGS)); } catch (error) { localStorage.setItem(BUILDINGS_STORAGE_KEY, JSON.stringify(BUILDINGS)); return JSON.parse(JSON.stringify(BUILDINGS)); } } function saveBuildings(data) { localStorage.setItem(BUILDINGS_STORAGE_KEY, JSON.stringify(data)); } function statusByProgress(value) { if (value >= 70) return "success"; if (value >= 40) return "warn"; return "danger"; } function getBuildingId() { const params = new URLSearchParams(window.location.search); return params.get('id') || '404'; } function renderBuilding() { const id = getBuildingId(); const BUILDINGS_DATA = getBuildings(); const data = BUILDINGS_DATA[id] || BUILDINGS_DATA["404"]; document.title = data.name + ' | EKS'; document.getElementById('building-title').textContent = 'EKS | ' + data.name; document.getElementById('building-name').textContent = data.name; document.getElementById('building-description').textContent = data.description; const metaWrap = document.getElementById('building-meta'); metaWrap.innerHTML = ''; data.meta.forEach(item => { const card = document.createElement('article'); card.className = 'tile'; card.innerHTML = '<h3>' + item.label + '</h3><p>' + item.value + '</p>'; metaWrap.appendChild(card); }); const tbody = document.querySelector('#systems-table tbody'); tbody.innerHTML = ''; data.systems.forEach(sys => { const tr = document.createElement('tr'); const statusClass = sys.status || 'success'; tr.innerHTML = '<td>' + sys.name + '</td>' + '<td>' + sys.contractor + '</td>' + '<td><span class="badge ' + statusClass + '">' + sys.progress + '</span></td>' + '<td><button class="btn btn-danger" type="button" data-delete-system="' + sys.id + '">Удалить</button></td>'; tbody.appendChild(tr); }); tbody.querySelectorAll("[data-delete-system]").forEach((button) => { button.addEventListener("click", () => { const map = getBuildings(); map[id].systems = (map[id].systems || []).filter((sys) => sys.id !== button.getAttribute("data-delete-system")); saveBuildings(map); renderBuilding(); }); }); const docsWrap = document.getElementById('documents-list'); docsWrap.innerHTML = ''; data.documents.forEach(doc => { const card = document.createElement('article'); card.className = 'tile'; card.innerHTML = '<h3>' + doc.system + '</h3>' + '<p><strong>' + doc.type + '</strong></p>' + '<p>Код / номер: ' + doc.code + '</p>' + '<button class="btn btn-danger" type="button" data-delete-document="' + doc.id + '" style="margin-top: 12px;">Удалить</button>'; docsWrap.appendChild(card); }); docsWrap.querySelectorAll("[data-delete-document]").forEach((button) => { button.addEventListener("click", () => { const map = getBuildings(); map[id].documents = (map[id].documents || []).filter((doc) => doc.id !== button.getAttribute("data-delete-document")); saveBuildings(map); renderBuilding(); }); }); } document.getElementById("add-system-form").addEventListener("submit", (event) => { event.preventDefault(); const id = getBuildingId(); const formData = new FormData(event.target); const name = String(formData.get("name") || "").trim(); const contractor = String(formData.get("contractor") || "").trim(); const progress = Number(formData.get("progress")); if (!name || !contractor || Number.isNaN(progress)) return; const map = getBuildings(); if (!map[id]) return; const normalized = Math.min(100, Math.max(0, progress)); map[id].systems = map[id].systems || []; map[id].systems.push({ id: String(Date.now()), name, contractor, progress: normalized + "%", status: statusByProgress(normalized), }); saveBuildings(map); event.target.reset(); renderBuilding(); }); document.getElementById("add-document-form").addEventListener("submit", (event) => { event.preventDefault(); const id = getBuildingId(); const formData = new FormData(event.target); const system = String(formData.get("system") || "").trim(); const type = String(formData.get("type") || "").trim(); const code = String(formData.get("code") || "").trim(); if (!system || !type || !code) return; const map = getBuildings(); if (!map[id]) return; map[id].documents = map[id].documents || []; map[id].documents.push({ id: String(Date.now()), system, type, code }); saveBuildings(map); event.target.reset(); renderBuilding(); }); renderBuilding(); </script> </body> </html>