Убран JS fetch. Форма отправляется напрямую на сервер. Сервер обрабатывает файлы и возвращает страницу с результатами. Нет Failed to fetch.
137 lines
6.3 KiB
HTML
137 lines
6.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Сверка договоров</title>
|
|
<link rel="icon" type="image/png" href="{{ url_for('static', filename='favicon.png') }}">
|
|
<script src="https://unpkg.com/lucide@latest"></script>
|
|
<style>
|
|
:root {
|
|
--brand-primary: #2563eb; --brand-primary-dark: #1d4ed8;
|
|
--brand-gray: #d1d5db; --brand-grey-light: #f3f4f6;
|
|
--background: #ffffff; --foreground: #1a1a1a;
|
|
--muted: #6b7280; --destructive: #ef4444; --green: #22c55e;
|
|
}
|
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
body {
|
|
font-family: system-ui, sans-serif; font-size: 14px; color: var(--foreground);
|
|
background: var(--brand-grey-light); min-height: 100vh;
|
|
}
|
|
.topbar {
|
|
background: var(--background); border-bottom: 1px solid var(--brand-gray);
|
|
padding: 0 24px; height: 56px; display: flex; align-items: center; gap: 16px;
|
|
}
|
|
.topbar img { height: 28px; }
|
|
.topbar .title { font-weight: 600; font-size: 16px; }
|
|
.content { max-width: 800px; margin: 32px auto; padding: 0 16px; }
|
|
.card {
|
|
background: var(--background); border-radius: 12px;
|
|
border: 1px solid var(--brand-gray); box-shadow: 0 1px 2px rgba(0,0,0,.05);
|
|
overflow: hidden; margin-bottom: 16px;
|
|
}
|
|
.card-header {
|
|
background: var(--brand-grey-light); padding: 12px 16px;
|
|
font-weight: 600; font-size: 16px; display: flex; align-items: center; gap: 8px;
|
|
}
|
|
.card-body { padding: 16px; }
|
|
.btn {
|
|
height: 36px; border-radius: 6px; gap: 6px; padding: 0 14px;
|
|
font-size: 14px; font-family: inherit; cursor: pointer;
|
|
display: inline-flex; align-items: center;
|
|
border: 1px solid var(--brand-gray); background: var(--background);
|
|
}
|
|
.btn-primary { background: var(--brand-primary); border-color: var(--brand-primary); color: #fff; }
|
|
.btn-primary:hover { background: var(--brand-primary-dark); }
|
|
.queue { margin-top: 12px; }
|
|
.queue-item {
|
|
display: flex; align-items: center; gap: 8px;
|
|
padding: 8px 12px; border-radius: 6px; border: 1px solid var(--brand-gray);
|
|
background: var(--brand-grey-light); margin-bottom: 4px;
|
|
}
|
|
.queue-item .name { flex: 1; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
.queue-item .size { color: var(--muted); font-size: 12px; }
|
|
.queue-item .remove { cursor: pointer; color: var(--muted); padding: 4px; }
|
|
.queue-item .remove:hover { color: var(--destructive); }
|
|
.table-wrap { border-radius: 6px; border: 1px solid var(--brand-gray); overflow: hidden; margin-top: 12px; }
|
|
table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
|
th { background: var(--brand-grey-light); text-transform: uppercase; padding: 4px 8px; border-right: 1px solid var(--brand-gray); text-align: left; font-weight: 600; }
|
|
td { padding: 4px 8px; border-right: 1px solid var(--brand-gray); border-bottom: 1px solid var(--brand-gray); }
|
|
tr:hover td { background: rgba(243,244,246,.5); }
|
|
.error-box { margin-top: 12px; padding: 12px; border-radius: 6px; border: 1px solid var(--destructive); background: rgba(239,68,68,.05); color: var(--destructive); font-size: 14px; }
|
|
.badge { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; padding: 2px 8px; border-radius: 4px; }
|
|
.badge-ok { background: rgba(34,197,94,.1); color: var(--green); }
|
|
.badge-err { background: rgba(239,68,68,.1); color: var(--destructive); }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="topbar">
|
|
<img src="{{ url_for('static', filename='nubes-logo.svg') }}" alt="Nubes">
|
|
<span class="title">Сверка договоров</span>
|
|
</div>
|
|
|
|
<div class="content">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<i data-lucide="folder-open" style="width:18px;height:18px;"></i>
|
|
Загрузка договоров / допников
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="POST" enctype="multipart/form-data">
|
|
<input type="file" name="files" accept=".docx,.doc,.pdf,.zip" multiple style="margin-bottom:12px;">
|
|
<button type="submit" class="btn btn-primary" style="width:100%;justify-content:center;">
|
|
<i data-lucide="play" style="width:16px;height:16px;"></i> Обработать
|
|
</button>
|
|
</form>
|
|
{% if error %}
|
|
<div class="error-box" style="margin-top:12px;">❌ {{ error }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
{% if results %}
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<i data-lucide="file-text" style="width:18px;height:18px;"></i>
|
|
Результаты (строк извлечено: {{ total_rows }})
|
|
</div>
|
|
<div class="card-body">
|
|
{% for r in results %}
|
|
<div class="queue-item">
|
|
<span class="badge {{ 'badge-ok' if r.ok else 'badge-err' }}">{{ '✅' if r.ok else '❌' }} {{ 'OK' if r.ok else 'Ошибка' }}</span>
|
|
<span class="name">{{ r.name }}</span>
|
|
{% if r.ok %}
|
|
<span class="size">строк: {{ r.rows }}, +{{ r.summary.added }} ~{{ r.summary.changed }} -{{ r.summary.deleted }}</span>
|
|
{% else %}
|
|
<span class="size" style="color:var(--destructive);">{{ r.error }}</span>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
|
|
{% if all_rows %}
|
|
<div class="table-wrap" style="margin-top:12px;">
|
|
<table>
|
|
<thead><tr><th>№</th><th>Услуга</th><th>Цена, руб</th><th>Кол-во</th><th>Сумма, руб</th><th>Дата</th></tr></thead>
|
|
<tbody>
|
|
{% for row in all_rows %}
|
|
<tr>
|
|
<td>{{ row.row_num }}</td>
|
|
<td>{{ row.name[:80] if row.name else '' }}</td>
|
|
<td style="text-align:right">{{ '{:,.2f}'.format(row.price) if row.price else '' }}</td>
|
|
<td style="text-align:center">{{ row.qty if row.qty else '' }}</td>
|
|
<td style="text-align:right">{{ '{:,.2f}'.format(row.sum) if row.sum else '' }}</td>
|
|
<td>{{ row.date_start if row.date_start else '' }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<script>lucide.createIcons();</script>
|
|
</body>
|
|
</html>
|