Измение дизайна документов

This commit is contained in:
2026-09-11 13:29:18 +03:00
parent 999cc0f5c5
commit 2092f096a0
2 changed files with 100 additions and 102 deletions
+9 -8
View File
@@ -14,13 +14,6 @@ from django.views.decorators.http import require_POST
from apps.reports.access import user_can_edit_template, user_can_manage_templates
from apps.reports.engine import TemplateRenderError, render_report
from apps.reports.it_monthly import (
available_report_months,
build_monthly_report,
parse_month_id,
user_can_manage_it_monthly_report,
user_can_view_it_monthly_report,
)
from apps.reports.documents import (
report_document_relpath,
unique_filename,
@@ -29,6 +22,13 @@ from apps.reports.documents import (
user_can_view_report_document,
visible_report_documents,
)
from apps.reports.it_monthly import (
available_report_months,
build_monthly_report,
parse_month_id,
user_can_manage_it_monthly_report,
user_can_view_it_monthly_report,
)
from apps.reports.models import ReportDocument, ReportTemplate
from apps.reports.publication import (
available_months_for_user,
@@ -97,10 +97,11 @@ def reports_hub_view(request):
if not _can_open_reports_hub(request.user):
return deny_section_access(request)
specs = visible_reports(request.user)
docs = list(visible_report_documents(request.user))
return render_page(request, 'reports.html', {
'report_specs': specs,
'report_rows': report_list_rows(request.user),
'report_documents': list(visible_report_documents(request.user)),
'report_documents': docs,
'can_create_report_document': user_can_create_report_document(request.user),
'onlyoffice_ready': _onlyoffice_ready(),
'reports_message': request.session.pop('reports_message', ''),
+91 -94
View File
@@ -1,7 +1,7 @@
{% load i18n %}
<div class="page-content">
<div style="display:flex; align-items:flex-start; justify-content:space-between; gap:1rem; flex-wrap:wrap; margin-bottom:1.5rem;">
<div style="display:flex; align-items:flex-start; justify-content:space-between; gap:1rem; flex-wrap:wrap; margin-bottom:1.25rem;">
<div>
<h1 style="font-size:1.25rem; font-weight:500; color:var(--color-foreground);">{% trans "Отчёты" %}</h1>
<p style="font-size:0.875rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "Аналитика и выгрузки по отделам" %}</p>
@@ -12,48 +12,121 @@
{% endif %}
</div>
{% if report_rows %}
{% if reports_message %}
<div style="margin-bottom:1rem; padding:0.65rem 0.9rem; border-radius:0.5rem; background:color-mix(in srgb, #16a34a 12%, var(--color-card)); border:1px solid color-mix(in srgb, #16a34a 30%, var(--color-border)); font-size:0.8125rem;">{{ reports_message }}</div>
{% endif %}
{% if reports_error %}
<div style="margin-bottom:1rem; padding:0.65rem 0.9rem; border-radius:0.5rem; background:color-mix(in srgb, #dc2626 12%, var(--color-card)); border:1px solid color-mix(in srgb, #dc2626 30%, var(--color-border)); font-size:0.8125rem;">{{ reports_error }}</div>
{% endif %}
{% if report_rows or report_documents or can_create_report_document %}
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0/0.05); overflow:hidden;">
<table style="width:100%; border-collapse:collapse; font-size:0.8125rem;">
<thead>
<tr style="background:var(--color-muted);">
<th style="padding:0.625rem 1.25rem; text-align:left; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground);">{% trans "Отчёт" %}</th>
<th style="padding:0.625rem 1rem; text-align:left; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground);">{% trans "Отдел" %}</th>
<th style="padding:0.625rem 1rem; text-align:left; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground);">{% trans "Период" %}</th>
<th style="padding:0.625rem 1rem; text-align:left; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground);">{% trans "Статус" %}</th>
<th style="padding:0.625rem 1rem;"></th>
<th style="padding:0.5rem 1.25rem; text-align:left; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground);">{% trans "Название" %}</th>
<th style="padding:0.5rem 1rem; text-align:left; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground);">{% trans "Отдел" %}</th>
<th style="padding:0.5rem 1rem; text-align:left; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground);">{% trans "Период" %}</th>
<th style="padding:0.5rem 1rem; text-align:left; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground);">{% trans "Статус" %}</th>
<th style="padding:0.5rem 1rem;"></th>
</tr>
</thead>
{% if report_rows %}
<tbody>
{% for row in report_rows %}
<tr class="tr-hover" style="border-top:1px solid var(--color-border);">
<td style="padding:0.875rem 1.25rem; vertical-align:top;">
<td style="padding:0.75rem 1.25rem; vertical-align:middle;">
<a href="{{ row.path }}"
hx-get="{{ row.path }}" hx-target="#main-content" hx-push-url="{{ row.path }}" hx-indicator="#loader"
style="font-weight:600; color:var(--color-foreground); text-decoration:none;">{{ row.title }}</a>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem; line-height:1.4; max-width:36rem;">{{ row.description }}</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.2rem; line-height:1.35; max-width:36rem;">{{ row.description }}</div>
</td>
<td style="padding:0.875rem 1rem; color:var(--color-foreground); white-space:nowrap;">{{ row.department_label }}</td>
<td style="padding:0.875rem 1rem; color:var(--color-foreground); white-space:nowrap;">{{ row.latest_month|default:"—" }}</td>
<td style="padding:0.875rem 1rem; white-space:nowrap;">
<td style="padding:0.75rem 1rem; white-space:nowrap;">{{ row.department_label }}</td>
<td style="padding:0.75rem 1rem; white-space:nowrap;">{{ row.latest_month|default:"—" }}</td>
<td style="padding:0.75rem 1rem; white-space:nowrap;">
{% if row.status == 'published' %}
<span class="badge badge-success">{{ row.status_label }}</span>
{% elif row.status == 'draft' %}
<span class="badge badge-muted">{{ row.status_label }}</span>
{% else %}
<span class="badge badge-muted">{{ row.status_label }}</span>
{% endif %}
</td>
<td style="padding:0.875rem 1.25rem; text-align:right; white-space:nowrap;">
<td style="padding:0.75rem 1.25rem; text-align:right; white-space:nowrap;">
<a href="{{ row.path }}"
hx-get="{{ row.path }}" hx-target="#main-content" hx-push-url="{{ row.path }}" hx-indicator="#loader"
class="btn btn-secondary" style="font-size:0.75rem; text-decoration:none; border:1px solid var(--color-border);">
{% trans "Открыть" %}
</a>
style="font-size:0.75rem; color:var(--color-primary); text-decoration:none;">{% trans "Открыть" %}</a>
</td>
</tr>
{% endfor %}
</tbody>
{% endif %}
<tbody>
<tr style="background:var(--color-muted); border-top:1px solid var(--color-border);">
<td colspan="5" style="padding:0.45rem 1.25rem; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground); font-weight:600;">
{% trans "Документы отдела" %}
</td>
</tr>
{% for doc in report_documents %}
<tr class="tr-hover" style="border-top:1px solid var(--color-border);">
<td style="padding:0.65rem 1.25rem; vertical-align:middle;">
{% if onlyoffice_ready %}
<a href="/documents/edit/?report_doc={{ doc.pk }}"
style="font-weight:600; color:var(--color-foreground); text-decoration:none;">{{ doc.title }}</a>
{% else %}
<span style="font-weight:600;">{{ doc.title }}</span>
{% endif %}
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.15rem;">
{{ doc.filename }}
{% if doc.kind == 'snapshot' %} · {% trans "снимок отчёта" %}{% endif %}
</div>
</td>
<td style="padding:0.65rem 1rem; white-space:nowrap;">{{ doc.department.name }}</td>
<td style="padding:0.65rem 1rem; white-space:nowrap; color:var(--color-muted-foreground);">{{ doc.updated_at|date:"d.m.Y H:i" }}</td>
<td style="padding:0.65rem 1rem; white-space:nowrap;">
{% if doc.filename|slice:"-5:" == ".xlsx" %}
<span class="badge badge-muted">Excel</span>
{% else %}
<span class="badge badge-muted">Word</span>
{% endif %}
</td>
<td style="padding:0.65rem 1.25rem; text-align:right; white-space:nowrap;">
<a href="{% url 'report_document_download' doc.pk %}"
style="font-size:0.75rem; color:var(--color-muted-foreground); text-decoration:none;">{% trans "Скачать" %}</a>
{% if can_create_report_document %}
<form method="post" action="{% url 'report_document_delete' doc.pk %}" style="display:inline; margin-left:0.75rem;"
onsubmit="return confirm('{% trans "Удалить документ?" %}');">
{% csrf_token %}
<button type="submit" class="nc-file-act nc-file-act-danger">{% trans "Удалить" %}</button>
</form>
{% endif %}
</td>
</tr>
{% empty %}
<tr>
<td colspan="5" style="padding:0.75rem 1.25rem; font-size:0.8125rem; color:var(--color-muted-foreground);">
{% trans "Пока нет файлов отдела." %}
</td>
</tr>
{% endfor %}
{% if can_create_report_document %}
<tr style="border-top:1px solid var(--color-border);">
<td colspan="5" style="padding:0.65rem 1.25rem;">
<form method="post" action="{% url 'report_document_create' %}"
class="nc-mkdir" style="margin:0;">
{% csrf_token %}
<input type="text" name="title" required class="input" maxlength="200"
placeholder="{% trans 'Новый Word или Excel' %}"
style="max-width:18rem; font-size:0.8125rem;">
<select name="file_type" class="input" style="width:auto; max-width:8rem; font-size:0.8125rem;">
<option value="docx">{% trans "Word" %}</option>
<option value="xlsx">{% trans "Excel" %}</option>
</select>
<button type="submit" class="btn btn-secondary" style="font-size:0.8125rem;">{% trans "Создать" %}</button>
</form>
</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
{% else %}
@@ -62,80 +135,4 @@
</div>
{% endif %}
{% if reports_message %}
<div style="margin-top:1rem; padding:0.65rem 0.9rem; border-radius:0.5rem; background:color-mix(in srgb, #16a34a 12%, var(--color-card)); border:1px solid color-mix(in srgb, #16a34a 30%, var(--color-border)); font-size:0.8125rem;">{{ reports_message }}</div>
{% endif %}
{% if reports_error %}
<div style="margin-top:1rem; padding:0.65rem 0.9rem; border-radius:0.5rem; background:color-mix(in srgb, #dc2626 12%, var(--color-card)); border:1px solid color-mix(in srgb, #dc2626 30%, var(--color-border)); font-size:0.8125rem;">{{ reports_error }}</div>
{% endif %}
<div style="margin-top:1.5rem; background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0/0.05); overflow:hidden;">
<div style="display:flex; flex-wrap:wrap; align-items:flex-start; justify-content:space-between; gap:0.75rem; padding:0.875rem 1.25rem; border-bottom:1px solid var(--color-border);">
<div>
<div style="font-size:0.9375rem; font-weight:500;">{% trans "Документы отдела" %}</div>
<p style="font-size:0.75rem; color:var(--color-muted-foreground); margin:0.25rem 0 0;">
{% trans "Дополнительные файлы и сохранённые отчёты. Правка — в OnlyOffice." %}
</p>
</div>
{% if can_create_report_document %}
<form method="post" action="{% url 'report_document_create' %}"
style="display:flex; gap:0.5rem; flex-wrap:wrap; align-items:center; margin:0;">
{% csrf_token %}
<input type="text" name="title" required class="input" maxlength="200"
placeholder="{% trans 'Название документа' %}" style="min-width:14rem;">
<select name="file_type" class="input">
<option value="docx">{% trans "Word" %}</option>
<option value="xlsx">{% trans "Excel" %}</option>
</select>
<button type="submit" class="btn btn-primary" style="font-size:0.75rem;">{% trans "Создать" %}</button>
</form>
{% endif %}
</div>
{% if report_documents %}
<table style="width:100%; border-collapse:collapse; font-size:0.8125rem;">
<thead>
<tr style="background:var(--color-muted);">
<th style="padding:0.625rem 1.25rem; text-align:left; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground);">{% trans "Документ" %}</th>
<th style="padding:0.625rem 1rem; text-align:left; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground);">{% trans "Отдел" %}</th>
<th style="padding:0.625rem 1rem; text-align:left; font-size:0.7rem; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-muted-foreground);">{% trans "Обновлён" %}</th>
<th style="padding:0.625rem 1rem;"></th>
</tr>
</thead>
<tbody>
{% for doc in report_documents %}
<tr class="tr-hover" style="border-top:1px solid var(--color-border);">
<td style="padding:0.75rem 1.25rem;">
<div style="font-weight:600;">{{ doc.title }}</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.15rem;">
{% if doc.kind == 'snapshot' %}{% trans "Снимок отчёта" %}{% else %}{% trans "Документ" %}{% endif %}
· {{ doc.filename }}
</div>
</td>
<td style="padding:0.75rem 1rem; white-space:nowrap;">{{ doc.department.name }}</td>
<td style="padding:0.75rem 1rem; white-space:nowrap; color:var(--color-muted-foreground);">{{ doc.updated_at|date:"d.m.Y H:i" }}</td>
<td style="padding:0.75rem 1.25rem; text-align:right; white-space:nowrap;">
{% if onlyoffice_ready %}
<a href="/documents/edit/?report_doc={{ doc.pk }}" class="btn btn-secondary" style="font-size:0.75rem; text-decoration:none; border:1px solid var(--color-border);">{% trans "Открыть" %}</a>
{% endif %}
<a href="{% url 'report_document_download' doc.pk %}" class="btn btn-secondary" style="font-size:0.75rem; text-decoration:none; border:1px solid var(--color-border);">{% trans "Скачать" %}</a>
{% if can_create_report_document %}
<form method="post" action="{% url 'report_document_delete' doc.pk %}" style="display:inline;"
onsubmit="return confirm('{% trans "Удалить документ?" %}');">
{% csrf_token %}
<button type="submit" class="btn btn-ghost" style="font-size:0.75rem;">{% trans "Удалить" %}</button>
</form>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div style="padding:1.25rem; font-size:0.8125rem; color:var(--color-muted-foreground);">
{% trans "Пока нет дополнительных документов." %}
{% if can_create_report_document %}{% trans "Создайте Word или Excel — файл откроется в OnlyOffice." %}{% endif %}
</div>
{% endif %}
</div>
</div>