feat: drhider PDF→DOCX conversion (LibreOffice), collision dialog (v1.9)
Deploy contracts-flask / validate (push) Successful in 0s
Deploy contracts-flask / validate (push) Successful in 0s
This commit is contained in:
@@ -84,7 +84,7 @@
|
||||
<a href="https://contractor.pythonk8s.services.ngcloud.ru/">Сверка договоров</a>
|
||||
<span class="sep">|</span>
|
||||
<strong>DrHider</strong>
|
||||
<span style="font-size:11px;color:var(--muted);">v1.8</span>
|
||||
<span style="font-size:11px;color:var(--muted);">v1.9</span>
|
||||
<button class="help-btn" onclick="openModal()" title="О сервисе">?</button>
|
||||
</header>
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
<h3>✅ Форматы файлов</h3>
|
||||
<ul>
|
||||
<li><strong>.docx</strong> — полная замена с сохранением структуры документа. ⚠️ Форматирование (жирный, курсив) заменённых фрагментов может сброситься.</li>
|
||||
<li><strong>.pdf</strong> — текст извлекается и обфусцируется. Результат: <code>.txt</code>. Форматирование, таблицы и графика не сохраняются.</li>
|
||||
<li><strong>.pdf</strong> — конвертируется в .docx (через LibreOffice), затем обфусцируется с сохранением форматирования. При совпадении имён с существующим .docx добавляется суффикс <code>_из_pdf</code>.</li>
|
||||
<li><strong>.doc</strong> — бинарный формат, <strong>не обфусцируется</strong>. Файл возвращается как есть. Конвертируйте в .docx перед загрузкой.</li>
|
||||
<li><strong>.zip</strong> — автоматически распаковывается, все файлы внутри обрабатываются.</li>
|
||||
</ul>
|
||||
@@ -139,7 +139,7 @@
|
||||
<strong>.doc не обрабатывается:</strong> старые Word-файлы возвращаются без изменений.
|
||||
</div>
|
||||
<div class="warn">
|
||||
<strong>PDF → текст:</strong> таблицы, графика и форматирование теряются.
|
||||
<strong>PDF → DOCX:</strong> конвертация через LibreOffice может незначительно изменить форматирование сложных PDF.
|
||||
</div>
|
||||
<div class="warn">
|
||||
<strong>Сканы/изображения:</strong> текст на картинках не распознаётся (нет OCR).
|
||||
@@ -211,6 +211,44 @@ function render() {
|
||||
|
||||
BTN.onclick = () => {
|
||||
if (!files.length) return;
|
||||
// Проверить коллизии PDF→DOCX
|
||||
const collisions = [];
|
||||
const names = files.map(f => f.name);
|
||||
files.forEach(f => {
|
||||
if (f.name.toLowerCase().endsWith('.pdf')) {
|
||||
const docxName = f.name.slice(0, -4) + '.docx';
|
||||
if (names.includes(docxName)) {
|
||||
collisions.push({pdf: f.name, docx: docxName});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (collisions.length) {
|
||||
showCollisionModal(collisions);
|
||||
return;
|
||||
}
|
||||
doSubmit();
|
||||
};
|
||||
|
||||
function showCollisionModal(collisions) {
|
||||
const list = collisions.map(c => `<div style="margin-bottom:4px">📄 <b>${esc(c.pdf)}</b> → <b>${esc(c.docx)}</b> (уже есть)</div>`).join('');
|
||||
document.getElementById('collisionList').innerHTML = list;
|
||||
document.getElementById('collisionOverlay').classList.add('show');
|
||||
window._collisions = collisions;
|
||||
}
|
||||
|
||||
function closeCollision(skipAll) {
|
||||
document.getElementById('collisionOverlay').classList.remove('show');
|
||||
if (skipAll) {
|
||||
// Удалить PDF-файлы из списка
|
||||
const pdfNames = window._collisions.map(c => c.pdf);
|
||||
files = files.filter(f => !pdfNames.includes(f.name));
|
||||
render();
|
||||
}
|
||||
// В любом случае отправляем (бэкенд сам переименует)
|
||||
setTimeout(doSubmit, 100);
|
||||
}
|
||||
|
||||
function doSubmit() {
|
||||
BTN.disabled = true;
|
||||
setStatus('progress', '⏳ Отправка...');
|
||||
const xhr = new XMLHttpRequest();
|
||||
@@ -248,7 +286,24 @@ function fmt(n) { return n>1e6 ? (n/1e6).toFixed(1)+' MB' : n>1e3 ? (n/1e3).toFi
|
||||
// ── Модальное окно ─────────────────────────────────────────────
|
||||
function openModal() { document.getElementById('modalOverlay').classList.add('show'); }
|
||||
function closeModal() { document.getElementById('modalOverlay').classList.remove('show'); }
|
||||
document.addEventListener('keydown', e => { if (e.key === 'Escape') closeModal(); });
|
||||
// ── Коллизия PDF→DOCX ──────────────────────────────────────────
|
||||
document.addEventListener('keydown', e => { if (e.key === 'Escape') closeCollision(true); });
|
||||
</script>
|
||||
|
||||
<!-- Модальное окно: коллизия PDF→DOCX -->
|
||||
<div class="modal-overlay" id="collisionOverlay">
|
||||
<div class="modal" style="max-width:480px">
|
||||
<div class="modal-header">⚠️ Конфликт имён</div>
|
||||
<div class="modal-body">
|
||||
<p style="margin-bottom:10px">PDF-файлы конвертируются в DOCX. Имена совпадают:</p>
|
||||
<div id="collisionList" style="margin-bottom:12px"></div>
|
||||
<p style="font-size:12px;color:var(--muted)">«Перезаписать» — PDF-файл заменит DOCX.<br>«Пропустить» — PDF будут удалены из списка.</p>
|
||||
</div>
|
||||
<div style="display:flex;gap:8px;padding:12px 16px;border-top:1px solid var(--brand-gray)">
|
||||
<button class="btn" onclick="closeCollision(true)" style="flex:1">Пропустить PDF</button>
|
||||
<button class="btn btn-primary" onclick="closeCollision(false)" style="flex:1">Перезаписать</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user