/
Starolat
/
DeepDive
Обзор
Документация
Войти
/
Starolat
/
DeepDive
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
index.html
287 строк
14 KB
Starolat Sergei
feat: меню функций в шапке вместо ряда иконок
30 июл 2026, 15:56
30 июл 2026, 15:56
e6bb0eb
Код
Авторство
О чём код?
<!DOCTYPE html> <html lang="ru" data-theme="consta-light"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate, proxy-revalidate"> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Expires" content="0"> <title>DeepDive Analytics</title> <link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/png" sizes="32x32" href="assets/icons/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="16x16" href="assets/icons/favicon-16x16.png"> <link rel="apple-touch-icon" sizes="180x180" href="assets/icons/apple-touch-icon.png"> <link rel="stylesheet" href="assets/fonts/fonts.css?__BUILD_ID__"> <!-- Consta Icons используются через SVG (js/components/ConstaIcons.js) --> <!-- Theme Variables (переключается через ThemeManager) --> <link id="theme-stylesheet" rel="stylesheet" href="css/themes/consta-light.css?__BUILD_ID__"> <!-- Main Styles (Consta Design System) --> <link rel="stylesheet" href="css/main.css?__BUILD_ID__"> <style> /* Стили для состояний загрузки в компонентах - Compact */ .waiting-database-state, .loading-state, .error-state, .empty-state { padding: 24px; text-align: center; } .waiting-database-state .state-icon, .error-state .state-icon, .empty-state .state-icon { width: 32px; height: 32px; margin-bottom: 12px; display: inline-flex; align-items: center; justify-content: center; } .waiting-database-state .state-icon svg, .error-state .state-icon svg, .empty-state .state-icon svg { width: 100%; height: 100%; } .waiting-database-state h3, .error-state h3, .empty-state h3 { margin: 0 0 4px 0; font-weight: 500; font-size: 14px; } .waiting-database-state p, .error-state p, .empty-state p { margin: 0; max-width: 320px; font-size: 11px; } /* Boot-спиннер: показывается сразу, до загрузки CSS/JS приложения */ #app-boot-loader { position: fixed; inset: 0; z-index: 99999; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; background: #ffffff; font-family: 'Inter', sans-serif; } #app-boot-loader .app-boot-spinner { width: 40px; height: 40px; border: 3px solid rgba(0, 66, 105, 0.15); border-top-color: #0078d2; border-radius: 50%; animation: app-boot-spin 0.8s linear infinite; } #app-boot-loader .app-boot-text { font-size: 12px; color: rgba(0, 32, 51, 0.6); } @keyframes app-boot-spin { to { transform: rotate(360deg); } } </style> </head> <body> <!-- Boot-спиннер: первый элемент в DOM, виден пока загружаются ресурсы приложения. Скрывается из js/app.js после инициализации (уведомление "Приложение готово к работе"). --> <div id="app-boot-loader" role="status" aria-label="Загрузка приложения"> <div class="app-boot-spinner"></div> <div class="app-boot-text">Загрузка приложения…</div> </div> <script> // Подхватываем сохранённую тёмную тему до загрузки theme.js, // чтобы boot-спиннер не давал белую вспышку. try { if (localStorage.getItem('deepdive-theme') === 'consta-dark') { var bootLoader = document.getElementById('app-boot-loader'); bootLoader.style.background = '#22272b'; bootLoader.querySelector('.app-boot-text').style.color = 'rgba(255, 255, 255, 0.7)'; } } catch (e) { /* localStorage недоступен — остаётся светлый фон */ } </script> <header class="app-header"> <div class="app-header-title"> <span class="app-header-home" id="app-header-home" title="На начальный экран"> <span class="app-logo-icon" id="app-logo-icon"></span> <span>DeepDive Analytics</span> </span> <span class="app-header-version" id="app-header-version" title="История изменений">__APP_VERSION__</span> <span class="app-header-divider" aria-hidden="true">|</span> <span class="app-header-project" id="app-header-project"></span> <span class="app-header-divider app-header-data-date-divider" aria-hidden="true">|</span> <span class="app-header-data-date" id="app-header-data-date"></span> </div> <header-filter-bar class="header-filter-bar"></header-filter-bar> <div class="header-actions"> <input type="file" id="db-file-input" accept=".dddb,.dddb.zip,.dddb.zst,.dddb.gz,.zip,.zst,.gz,application/zip,application/zstd,application/gzip" style="display: none;"> <div class="header-menu-container" id="header-menu-container"> <button class="header-menu-btn" id="header-menu-btn" title="Меню" aria-haspopup="true" aria-expanded="false"> <span class="header-menu-icon" id="header-menu-icon"></span> <span class="header-menu-btn-label">Меню</span> </button> <div class="header-menu" id="header-menu" role="menu"> <button class="header-open-btn" id="header-open-btn" role="menuitem"> <span class="header-open-icon" id="header-open-icon"></span> <span class="header-menu-item-label">Открыть файл проекта</span> </button> <button class="header-compare-btn" id="header-compare-btn" role="menuitem"> <span class="header-compare-icon" id="header-compare-icon"></span> <span class="header-menu-item-label">Сравнить версии проекта</span> </button> <button class="header-export-btn" id="header-export-btn" role="menuitem"> <span class="header-export-icon" id="header-export-icon"></span> <span class="header-menu-item-label">Экспортировать базу данных</span> </button> <button class="header-load-btn" id="header-load-btn" role="menuitem"> <span class="header-load-icon" id="header-load-icon"></span> <span class="header-menu-item-label">Загрузить данные из Primavera</span> </button> <button class="header-material-delivery-btn" id="header-material-delivery-btn" role="menuitem"> <span class="header-material-delivery-icon" id="header-material-delivery-icon"></span> <span class="header-menu-item-label">Загрузить реестр поставок МТР</span> </button> <div class="header-menu-divider" role="separator"></div> <button class="header-report-btn" id="header-report-btn" role="menuitem"> <span class="header-report-icon" id="header-report-icon"></span> <span class="header-menu-item-label">Статистика по проекту</span> </button> <div class="header-menu-divider" role="separator"></div> <button class="header-theme-btn" id="header-theme-btn" role="menuitem"> <span class="theme-icon-wrapper"> <span class="theme-icon-svg theme-icon-sun" id="theme-icon-sun"></span> <span class="theme-icon-svg theme-icon-moon" id="theme-icon-moon"></span> </span> <span class="header-menu-item-label">Переключить тему</span> </button> <button class="header-zen-btn" id="header-zen-btn" role="menuitem"> <span class="header-zen-icon" id="header-zen-icon"></span> <span class="header-menu-item-label">Скрыть панели (F10)</span> </button> <button class="header-settings-btn" id="header-settings-btn" role="menuitem"> <span class="header-settings-icon" id="header-settings-icon"></span> <span class="header-menu-item-label">Настройки</span> </button> </div> </div> </div> </header> <welcome-screen id="welcome-screen"></welcome-screen> <div id="dashboard" class="dashboard-grid" style="display: none;"> <!-- Панель настроек и макетов (слева) --> <left-sidebar id="left-sidebar" class="sidebar"></left-sidebar> <div class="resizer-y" id="left-resizer"></div> <!-- Основной контент (центр) --> <main id="main-content" class="main-content module-container"> <main-content-tabs id="data-module" class="module module-elastic" active-tab="summary" row-height="20"></main-content-tabs> <div class="resizer-x" id="data-timeline-resizer"></div> <timeline-panel id="timeline-module" class="module module-dockable"></timeline-panel> </main> <div class="resizer-y" id="right-resizer"></div> <!-- Панель фильтров и группировки (справа) --> <aside id="right-sidebar" class="sidebar"> <div class="sidebar-content module-container"> <filter-resource-tabs id="filter-resource-tabs-module" class="module module-elastic module-dockable"></filter-resource-tabs> <div class="resizer-x" id="filter-grouping-resizer"></div> <grouping-panel id="grouping-module" class="module module-elastic module-dockable"></grouping-panel> </div> </aside> </div> <!-- Environment Configuration (env.js - НЕ коммитится!) --> <script src="./env.js" onerror="console.warn('[env.js] Not found. Copy env.example.js to env.js and fill your values.');"></script> <!-- Scripts --> <script src="lib/echarts.min.js?__BUILD_ID__"></script> <script src="lib/fflate.min.js?__BUILD_ID__"></script> <script src="lib/xlsx.full.min.js?__BUILD_ID__"></script> <script type="module"> import fzstd from './lib/fzstd.min.js?__BUILD_ID__'; window.fzstd = fzstd; console.log('[fzstd] Loaded (fallback decompressor for legacy .zst files)'); </script> <script src="lib/jszip.min.js?__BUILD_ID__"></script> <script type="module"> import JSZip from './lib/jszip.esm.js?__BUILD_ID__'; window.JSZip = JSZip; console.log('[JSZip] Loaded (zip fallback)'); </script> <script type="module" src="js/app.js?__BUILD_ID__"></script> <script type="module" src="js/theme.js?__BUILD_ID__"></script> <!-- Modal for App Settings --> <app-settings-modal id="app-settings-modal"></app-settings-modal> <!-- Modal for Data Loading --> <primavera-data-loader id="primavera-data-loader"></primavera-data-loader> <!-- Modal for Material Delivery Import --> <material-delivery-import-modal id="material-delivery-import-modal"></material-delivery-import-modal> <!-- Project Report Modal --> <project-report-modal id="project-report-modal"></project-report-modal> <!-- Project Compare Modal --> <project-compare-modal id="project-compare-modal"></project-compare-modal> <!-- Project Stats Modal --> <project-stats-modal id="project-stats-modal"></project-stats-modal> <!-- Changelog Modal --> <changelog-modal id="changelog-modal"></changelog-modal> <!-- Toast Manager --> <toast-manager id="toast-manager" position="bottom-right"></toast-manager> <!-- Modal for Adding Filters --> <div id="add-filter-modal" class="modal" style="display: none;"> <div class="modal-content"> <div class="modal-header"> <h3>Новый фильтр</h3> <button id="modal-close-btn" class="icon-button"><span class="modal-close-icon" id="modal-close-icon"></span></button> </div> <div class="modal-body"> <div class="form-group"> <label for="filter-field">Поле</label> <select id="filter-field"> <option value="status">Статус</option> <option value="date">Дата начала</option> <option value="taskName">Название</option> </select> </div> <div class="form-group"> <label for="filter-condition">Условие</label> <select id="filter-condition"> <option value="Равно">Равно</option> <option value="Не равно">Не равно</option> <option value="Больше">Больше</option> <option value="Меньше">Меньше</option> </select> </div> <div class="form-group"> <label for="filter-value">Значение</label> <input type="text" id="filter-value" placeholder="Введите значение..."> </div> </div> <div class="modal-footer"> <button id="modal-cancel-btn" class="secondary">Отмена</button> <button id="modal-add-btn" class="primary">Добавить</button> </div> </div> </div> </body> </html>