diff --git a/backend/routers/oboruds.py b/backend/routers/oboruds.py index 951e888..ff85ed1 100644 --- a/backend/routers/oboruds.py +++ b/backend/routers/oboruds.py @@ -15,10 +15,12 @@ def create_oborud(item: schemas.OborudCreate, db: Session = Depends(database.get return obj @oboruds.get("/", response_model=list[schemas.OborudRead]) -def list_oboruds(aud_id: Optional[int] = None, db: Session = Depends(database.get_db)): +def list_oboruds(aud_id: Optional[int] = None, sort_by_inv: bool = False, db: Session = Depends(database.get_db)): query = db.query(models.Oboruds) if aud_id is not None: query = query.filter(models.Oboruds.aud_id == aud_id) + if sort_by_inv: + query = query.order_by(models.Oboruds.invNumber.asc()) return query.all() @oboruds.get("/{oborud_id}", response_model=schemas.OborudRead) diff --git a/frontend/app.js b/frontend/app.js index 43966c4..a6734b7 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -3,6 +3,7 @@ const { createApp } = Vue; const api = { auds: "/auditories/", oboruds: (audId) => `/oboruds/?aud_id=${encodeURIComponent(audId)}`, + allOboruds: "/oboruds/?sort_by_inv=true", owners: "/owners/", }; @@ -19,8 +20,10 @@ createApp({ auditories: [], selectedAudId: '', oboruds: [], + allOboruds: [], status: '', error: '', + printTitle: '', // auth/user management token: '', role: '', @@ -98,6 +101,34 @@ createApp({ this.status = ''; } }, + async loadAllOboruds() { + this.status = 'Загрузка всего оборудования…'; + this.error = ''; + try { + this.allOboruds = await fetchJSON(api.allOboruds); + this.status = `Загружено ${this.allOboruds.length} записей`; + } catch (e) { + console.error(e); + this.error = 'Не удалось загрузить оборудование'; + this.status = ''; + } + }, + async showAllEquipment() { + this.view = 'allEquipment'; + await this.loadAllOboruds(); + }, + getAuditoryName(audId) { + if (!audId) return ''; + const aud = this.auditories.find(a => a.id === audId); + return aud ? aud.audnazvanie : ''; + }, + printPage() { + const aud = this.auditories.find(a => a.id === this.selectedAudId); + this.printTitle = 'Аудитория № ' + (aud ? aud.audnazvanie : ''); + this.$nextTick(() => { + window.print(); + }); + }, async saveOwner(item) { try { this.status = 'Сохранение владельца…'; diff --git a/frontend/index.html b/frontend/index.html index 5a8cd58..1075bce 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -5,10 +5,10 @@ АСУ Инвентаризация - + -
+

АСУ Инвентаризация

@@ -26,6 +26,7 @@ -
+
-
+
-

Оборудование по аудитории

-
+

Оборудование по аудитории

+ +
+
-
{{ status }}
+
{{ status }}
@@ -61,9 +64,10 @@ - - - + + + + @@ -72,9 +76,9 @@ - - - + + + + + +
Инв. номер Название РасположениеКол-воТипВладелецКол-воТипВладелецПроверено
{{ it.invNumber ?? '' }} {{ it.nazvanie ?? '' }} {{ it.raspologenie ?? '' }}{{ it.kolichestvo ?? '' }}{{ it.type?.name ?? '' }} + {{ it.kolichestvo ?? '' }}{{ it.type?.name ?? '' }}
+
+
+
+
+ +
+
+
+

Всё оборудование (по инв. номеру)

+
{{ status }}
+
+ + + + + + + + + + + + + + + + + + + + +
Инв. номерНазваниеАудиторияРасположениеКол-воВладелец
{{ index + 1 }}{{ it.invNumber ?? '' }}{{ it.nazvanie ?? '' }}{{ getAuditoryName(it.aud_id) }}{{ it.raspologenie ?? '' }}{{ it.kolichestvo ?? '' }}{{ it.owner?.name ?? '' }}
@@ -95,7 +135,7 @@
-
+

Администрирование пользователей

Недостаточно прав. Войдите как администратор.
@@ -142,7 +182,7 @@
-
+

Управление аудиториями

Недостаточно прав. Войдите как администратор.
@@ -183,7 +223,7 @@
-
+

Управление владельцами

Недостаточно прав. Войдите как администратор или редактор.
diff --git a/frontend/styles.css b/frontend/styles.css index 9e21618..643c960 100644 --- a/frontend/styles.css +++ b/frontend/styles.css @@ -1,20 +1,191 @@ -:root { --bg: #0f172a; --fg: #e2e8f0; --muted: #94a3b8; --accent: #38bdf8; --err: #ef4444; --warn: #f59e0b; } -* { box-sizing: border-box; } -body { margin: 0; font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; background: var(--bg); color: var(--fg); } -header { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid #1f2937; } -header h1 { margin: 0; font-size: 20px; } -header nav a { color: var(--accent); text-decoration: none; } -main { padding: 20px; max-width: 1000px; margin: 0 auto; } -.panel { background: #0b1220; border: 1px solid #1f2937; border-radius: 8px; padding: 16px; } -.controls { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; } -select, button { padding: 8px 10px; border-radius: 6px; border: 1px solid #1f2937; background: #0a0f1a; color: var(--fg); } -button { cursor: pointer; } -button:hover { border-color: var(--accent); } -.status { min-height: 20px; color: var(--muted); margin-bottom: 8px; } -.status.error { color: var(--err); } -.status.warn { color: var(--warn); } -table { width: 100%; border-collapse: collapse; } -th, td { border-bottom: 1px solid #1f2937; padding: 8px; text-align: left; } -th { color: var(--muted); font-weight: 600; } -td.rasp { max-width: 200px; word-wrap: break-word; white-space: normal; } +* { + margin: 0; + padding: 0; +} +body { + background-color: #E2F3FD; + min-width: 580px; +} + +.row { + text-align: center; + display: flex; + justify-content: center; + border: 1px; +} + +header { + text-align: center; + background-color: #6A90B6; + padding: 2px; +} + +a:hover { + text-decoration: none; + color: #041322; +} + +a { + color: #041322; +} + +.container { + margin: 10px; +} + +button { + background-color: #E07D54; + margin-top: 5px; + margin-bottom: 5px; +} + +.card { + margin: 10px; + border-radius: 15px; + border-color: #E07D54; +} + +h5 { + text-align: center; +} + +.hidden-column { + display: none; +} + +nav { + width: 100%; +} + +table { + word-break: break-all; + border-collapse: separate !important; +} + +.table td { + font-size: 14px; + padding: 0; + max-width: 10rem; + word-break: break-all; + border-collapse: separate !important; +} + +.aud { + width: 110px; +} + +.inv { + width: 400px; +} + +.rasp { + width: 250px; + max-width: 250px; + word-break: break-word; + word-wrap: break-word; + overflow-wrap: break-word; + white-space: normal !important; +} + +#modal_matcenn { + margin-left: 20px; +} + +.datatable { + background-color: whitesmoke; +} + +.print-only { + display: none; +} + +.print-title { + text-align: center; + margin-bottom: 20px; +} + +.datatable th:nth-child(7) { + width: 200px; +} + +@media print { + * { + font-family: "Times New Roman", Times, serif; + } + + body { + margin: 0; + padding: 0; + background-color: transparent; + } + + a { + text-decoration: none; + border: none; + } + + @page { + size: A4; + margin: 10mm; + } + + @page :first { + margin-top: 10mm; + } + + html, body { + height: 100%; + } + + title { + display: none; + } + + .card { + border: none; + width: 100%; + } + + .no-print { + display: none !important; + } + + .print-only { + display: table-cell !important; + } + + h2.print-only { + display: block !important; + } + + .table { + border: 1px solid #000000; + margin-top: 20px; + font-size: 12pt; + } + + .table th, .table td { + border: 1px solid #000000; + padding: 5px; + font-size: 12pt; + } + + table.rs-table-bordered { + border: 1px solid #000000; + margin-top: 20px; + font-size: 14pt; + } + + table.rs-table-bordered > thead > tr > th { + border: 1px solid #000000; + padding: 2px; + font-size: 14pt; + } + + table.rs-table-bordered > tbody > tr > td { + border: 1px solid #000000; + padding: 10px; + font-size: 14pt; + } +}