Files
AI_portal/dwg-counting/static/index.html
2026-07-07 13:16:26 +02:00

280 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="cs">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Počítání symbolů z PDF výkresu | Colsys AI</title>
<base href="/apps/dwg-counting/">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&display=swap">
<link rel="stylesheet" href="static/styles.css?v=blocks11">
<link rel="stylesheet" href="static/extra.css?v=blocks11">
<script>
// Theme bootstrap — read source-of-truth in this order:
// ?theme= URL → portal_theme cookie → app_theme localStorage → OS
// The cookie is set by the portal landing on every resolvedTheme change,
// so it always reflects the portal's current state.
(function () {
var t = null;
try {
var p = new URL(window.location.href).searchParams.get("theme");
if (p === "dark" || p === "light") t = p;
} catch (e) {}
if (!t) {
var m = document.cookie.match(/(?:^|;\s*)portal_theme=([^;]+)/);
if (m) t = decodeURIComponent(m[1]);
}
if (!t) { try { t = localStorage.getItem("app_theme"); } catch (e) {} }
if (!t && typeof matchMedia !== "undefined") {
try {
t = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
} catch (e) {}
}
if (t === "dark" || t === "light") {
document.documentElement.classList.add(t);
try { localStorage.setItem("app_theme", t); } catch (e) {}
}
})();
// bfcache rehydration — re-sync the class when the page is restored
// (e.g. user toggled theme on the portal, then hit Back).
// Same as pageshow, but fires when the user switches tabs.
// Covers: portal tab toggles theme → user comes back to app tab.
document.addEventListener("visibilitychange", function () {
if (document.visibilityState !== "visible") return;
var m = document.cookie.match(/(?:^|;\s*)portal_theme=([^;]+)/);
if (!m) return;
var t = decodeURIComponent(m[1]);
if (t !== "dark" && t !== "light") return;
var cls = document.documentElement.classList;
if (cls.contains(t)) return;
cls.remove(t === "dark" ? "light" : "dark");
cls.add(t);
try { localStorage.setItem("app_theme", t); } catch (e) {}
});
window.addEventListener("pageshow", function () {
var m = document.cookie.match(/(?:^|;\s*)portal_theme=([^;]+)/);
if (!m) return;
var t = decodeURIComponent(m[1]);
if (t !== "dark" && t !== "light") return;
var cls = document.documentElement.classList;
if (cls.contains(t)) return;
cls.remove(t === "dark" ? "light" : "dark");
cls.add(t);
try { localStorage.setItem("app_theme", t); } catch (e) {}
});
</script>
</head>
<body>
<header class="header">
<div class="header-inner">
<a href="/" class="brand">
<span class="brand-icon">C</span>
<span class="brand-name">Colsys <span class="brand-ai">AI</span></span>
</a>
<span class="header-crumb">Počítání symbolů z PDF výkresu</span>
<a href="/" class="back-link" title="Zpět na portál">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="m15 18-6-6 6-6"/>
</svg>
<span>Zpět na portál</span>
</a>
</div>
</header>
<main class="main">
<!-- ── Upload ────────────────────────────── -->
<section id="s-upload">
<div class="section-intro">
<h1 class="section-title">Počítání symbolů z PDF výkresu</h1>
<p class="section-desc">
Nahrajte výkres ve formátu <strong>PDF</strong>, vyznačte symboly, které
chcete spočítat, a aplikace najde jejich výskyty v celém výkresu.
Výsledek lze stáhnout jako Excel nebo jako PDF s vyznačením.
</p>
</div>
<div id="drop-zone" class="drop-zone">
<svg class="drop-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M12 16.5V4.5m0 0-3.75 3.75M12 4.5l3.75 3.75M4.5 19.5h15"/>
</svg>
<p class="drop-text">Přetáhněte výkres sem (PDF, DWG nebo DXF)</p>
<p class="drop-or">nebo</p>
<button class="btn btn-secondary" id="browse-btn" type="button">Vybrat soubor</button>
<p class="drop-formats">Podporované formáty: .pdf, .dwg, .dxf</p>
<input type="file" id="file-input" accept=".pdf,.dwg,.dxf" style="display:none">
</div>
</section>
<!-- ── Processing ────────────────────────── -->
<section id="s-processing" class="hidden">
<div class="processing-card">
<div class="spinner"></div>
<h2 class="processing-title" id="processing-title">Hledám legendu ve výkresu…</h2>
<p class="processing-sub" id="processing-sub">Toto může trvat 2060 sekund.</p>
</div>
</section>
<!-- ── Symbol selection ──────────────────── -->
<section id="s-symbols" class="hidden">
<div class="results-header">
<div>
<h2 class="results-title">Vyberte symboly k spočítání</h2>
<p class="results-meta" id="symbols-meta"></p>
</div>
<div class="results-actions">
<button class="btn btn-secondary" id="reset-btn" type="button">Nahrát jiný</button>
<button class="btn btn-secondary" id="auto-detect-btn" type="button" title="Najít legendu pomocí AI">
Auto-detekce z legendy
</button>
<button class="btn btn-primary" id="add-symbol-btn" type="button">
+ Vyříznout symbol z výkresu
</button>
<button class="btn btn-secondary" id="upload-symbol-btn" type="button">
+ Nahrát PNG
</button>
<input type="file" id="symbol-file-input" accept="image/*" style="display:none">
<button class="btn btn-primary" id="count-btn" type="button" disabled>
Spočítat vybrané
</button>
</div>
</div>
<div class="threshold-row">
<label for="threshold-slider">Citlivost (práh shody):</label>
<input type="range" id="threshold-slider" min="0.40" max="0.95" step="0.01" value="0.70">
<span id="threshold-value">0.70</span>
<span class="threshold-hint">nižší = víc nálezů (i falešných), vyšší = jen přesné shody</span>
</div>
<div class="symbols-grid" id="symbols-grid"></div>
</section>
<!-- ── Block picker (DWG/DXF — exact counting) ─────── -->
<section id="s-blocks" class="hidden">
<div class="results-header">
<div>
<h2 class="results-title">Vyberte symboly k spočítání</h2>
<p class="results-meta" id="blocks-meta"></p>
</div>
<div class="results-actions">
<button class="btn btn-secondary" id="blocks-reset-btn" type="button">Nahrát jiný</button>
<label class="blocks-shownoise">
<input type="checkbox" id="blocks-shownoise"> Zobrazit i pomocné bloky
</label>
<button class="btn btn-secondary" id="region-match-btn" type="button">Symbol není blok? Vyznačit ve výkresu</button>
<button class="btn btn-secondary" id="blocks-pdf-btn" type="button" disabled>PDF s vyznačením</button>
<button class="btn btn-primary" id="blocks-export-btn" type="button" disabled>Exportovat Excel</button>
</div>
</div>
<p class="blocks-hint">
Výkres je CAD soubor — počty jsou <strong>přesné</strong>, čtené přímo
z dat (žádné falešné nálezy). Klikněte na bloky, které představují
hledaný symbol. Pokud symbol není samostatný blok, použijte
<strong>„Vyznačit ve výkresu"</strong> a označte ho přímo — najdeme
všechny jeho přesné kopie (i otočené/zrcadlené).
</p>
<div class="blocks-total" id="blocks-total"></div>
<div class="blocks-grid" id="blocks-grid"></div>
</section>
<!-- ── Debug modal ───────────────────────── -->
<div id="debug-modal" class="modal hidden">
<div class="modal-content" style="max-width:760px">
<div class="modal-header">
<h3 id="debug-title">Debug symbolu</h3>
<button class="btn-close" id="debug-close" type="button">×</button>
</div>
<div id="debug-body" class="debug-body"></div>
<div class="modal-actions">
<button class="btn btn-primary" id="debug-ok" type="button">Zavřít</button>
</div>
</div>
</div>
<!-- ── Crop editor modal ─────────────────── -->
<div id="crop-modal" class="modal hidden">
<div class="modal-content">
<div class="modal-header">
<h3 id="crop-modal-title">Vyznačte symbol</h3>
<button class="btn-close" id="crop-close" type="button">×</button>
</div>
<p class="modal-hint" id="crop-modal-hint">Kliknutím a tažením vyberte oblast obsahující grafický symbol.</p>
<div class="crop-name-row hidden" id="crop-name-row">
<label for="crop-name">Název symbolu:</label>
<input type="text" id="crop-name" placeholder="např. Zásuvka 230V">
</div>
<div class="crop-toolbar">
<button class="btn btn-secondary btn-sm" id="crop-zoom-in" type="button" title="Přiblížit (kolečko myši)">+</button>
<button class="btn btn-secondary btn-sm" id="crop-zoom-out" type="button" title="Oddálit"></button>
<button class="btn btn-secondary btn-sm" id="crop-zoom-fit" type="button" title="Celý výkres">Vejít</button>
<button class="btn btn-secondary btn-sm" id="crop-zoom-one" type="button" title="100 % (skutečná velikost)">100&nbsp;%</button>
<span class="crop-hint">Kolečko = přiblížit · Shift+tažení = posunout · Tažení = vybrat</span>
</div>
<div class="crop-canvas-wrap" id="crop-canvas-wrap">
<img id="crop-img" alt="" draggable="false">
<div id="crop-selection"></div>
</div>
<div class="threshold-row hidden" id="crop-threshold-row">
<label for="crop-threshold">Citlivost (práh shody):</label>
<input type="range" id="crop-threshold" min="0.40" max="0.95" step="0.01" value="0.70">
<span id="crop-threshold-value">0.70</span>
<span class="threshold-hint">nižší = víc nálezů (i falešných), vyšší = jen přesné shody</span>
</div>
<div class="modal-actions">
<button class="btn btn-secondary hidden" id="crop-back-btn" type="button">Zpět na celý výkres</button>
<button class="btn btn-secondary" id="crop-cancel" type="button">Zrušit</button>
<button class="btn btn-primary" id="crop-save" type="button" disabled>Uložit výřez</button>
</div>
</div>
</div>
<!-- ── Results ───────────────────────────── -->
<section id="s-results" class="hidden">
<div class="results-header">
<div>
<h2 class="results-title">Výsledky počítání</h2>
<p class="results-meta" id="results-meta"></p>
</div>
<div class="results-actions">
<button class="btn btn-secondary" id="back-btn" type="button">Zpět na výběr</button>
<button class="btn btn-secondary" id="pdf-btn" type="button">
<svg class="btn-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v12m0 0-3.75-3.75M12 16.5l3.75-3.75M4.5 19.5h15"/>
</svg>
PDF s vyznačením
</button>
<button class="btn btn-primary" id="export-btn" type="button">
<svg class="btn-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v12m0 0-3.75-3.75M12 16.5l3.75-3.75M4.5 19.5h15"/>
</svg>
Exportovat Excel
</button>
</div>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th style="width:80px">Symbol</th>
<th>Popis</th>
<th style="width:80px">Počet</th>
<th style="width:120px">Spolehlivost</th>
<th>Poznámka</th>
</tr>
</thead>
<tbody id="results-tbody"></tbody>
</table>
</div>
</section>
</main>
<script src="static/app.js?v=blocks11"></script>
</body>
</html>