From 771bc31219a350a8248abf9203ee45568ed59972 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 22:13:10 +0000 Subject: [PATCH 1/5] Initial plan From 022dc73eb858df6dbf6aea2212cb46b76afe4f14 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 22:16:21 +0000 Subject: [PATCH 2/5] Add GitHub Pages web application for DOZ3 report generation Co-authored-by: GraphSaf <63410676+GraphSaf@users.noreply.github.com> --- .github/workflows/pages.yml | 38 ++++++ README.md | 59 ++++++++- index.html | 106 +++++++++++++++ script.js | 229 ++++++++++++++++++++++++++++++++ styles.css | 251 ++++++++++++++++++++++++++++++++++++ 5 files changed, 681 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/pages.yml create mode 100644 index.html create mode 100644 script.js create mode 100644 styles.css diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..be1ad28 --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,38 @@ +name: Deploy to GitHub Pages + +on: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Pages + uses: actions/configure-pages@v4 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: '.' + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/README.md b/README.md index 313a01e..8f82fc0 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,57 @@ -# xray -Generate DOZ3 reports +# X-Ray - DOZ3 Report Generator + +Веб-приложение для генерации отчетов ДОЗ-3 (регистрация доз облучения пациентов при рентгенологических исследованиях). + +## 🌐 GitHub Pages + +Приложение доступно онлайн: [https://graphsaf.github.io/xray/](https://graphsaf.github.io/xray/) + +## 📋 Описание + +X-Ray - это простое и удобное веб-приложение для создания отчетов ДОЗ-3, которое позволяет: + +- Заполнять данные пациента и обследования +- Генерировать форматированные отчеты +- Сохранять отчеты в формате HTML +- Печатать отчеты + +## 🚀 Использование + +### Онлайн версия +Просто откройте [https://graphsaf.github.io/xray/](https://graphsaf.github.io/xray/) в браузере. + +### Локальная версия +1. Клонируйте репозиторий: +```bash +git clone https://github.com/GraphSaf/xray.git +cd xray +``` + +2. Откройте `index.html` в браузере + +Приложение не требует установки дополнительных зависимостей - это статический HTML/CSS/JS сайт. + +## 📁 Структура проекта + +- `index.html` - главная страница приложения +- `styles.css` - стили приложения +- `script.js` - логика работы приложения +- `ТЗ ДОЗ 3.pdf` - техническое задание + +## 🔧 Возможности + +- ✅ Заполнение данных пациента +- ✅ Выбор типа обследования (флюорография, рентгенография, КТ, маммография) +- ✅ Ввод дозы облучения +- ✅ Генерация отчета +- ✅ Скачивание отчета в HTML +- ✅ Печать отчета +- ✅ Адаптивный дизайн для мобильных устройств + +## 📄 Лицензия + +MIT License + +## 👤 Автор + +GraphSaf diff --git a/index.html b/index.html new file mode 100644 index 0000000..219e7ce --- /dev/null +++ b/index.html @@ -0,0 +1,106 @@ + + + + + + X-Ray - DOZ3 Report Generator + + + +
+
+

X-Ray DOZ3 Report Generator

+

Генератор отчетов ДОЗ-3

+
+ +
+
+

Создание отчета

+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + + +
+
+ + + +
+

Информация о ДОЗ-3

+

Форма ДОЗ-3 используется для регистрации и учета доз облучения пациентов при рентгенологических исследованиях.

+

Основные параметры:

+
    +
  • Данные пациента
  • +
  • Тип и дата исследования
  • +
  • Полученная доза облучения
  • +
  • Область исследования
  • +
  • Ответственный медицинский персонал
  • +
+ +
+
+ + +
+ + + + diff --git a/script.js b/script.js new file mode 100644 index 0000000..31f65ee --- /dev/null +++ b/script.js @@ -0,0 +1,229 @@ +// Report data storage +let currentReport = null; + +// Form elements +const reportForm = document.getElementById('reportForm'); +const clearFormBtn = document.getElementById('clearForm'); +const reportSection = document.getElementById('reportSection'); +const reportContent = document.getElementById('reportContent'); +const downloadBtn = document.getElementById('downloadBtn'); +const printBtn = document.getElementById('printBtn'); +const newReportBtn = document.getElementById('newReportBtn'); + +// Initialize date input with today's date +document.getElementById('examDate').valueAsDate = new Date(); + +// Form submission handler +reportForm.addEventListener('submit', function(e) { + e.preventDefault(); + + // Collect form data + const formData = new FormData(reportForm); + currentReport = { + patientName: formData.get('patientName'), + patientId: formData.get('patientId'), + examDate: formData.get('examDate'), + examType: formData.get('examType'), + examTypeLabel: getExamTypeLabel(formData.get('examType')), + dose: formData.get('dose'), + bodyPart: formData.get('bodyPart'), + doctor: formData.get('doctor'), + notes: formData.get('notes'), + generatedDate: new Date().toLocaleString('ru-RU') + }; + + // Generate and display report + generateReport(currentReport); + + // Hide form, show report + document.querySelector('.form-section').style.display = 'none'; + reportSection.style.display = 'block'; + + // Scroll to report + reportSection.scrollIntoView({ behavior: 'smooth' }); +}); + +// Clear form handler +clearFormBtn.addEventListener('click', function() { + if (confirm('Вы уверены, что хотите очистить форму?')) { + reportForm.reset(); + document.getElementById('examDate').valueAsDate = new Date(); + } +}); + +// Download PDF handler +downloadBtn.addEventListener('click', function() { + // In a real application, this would generate a PDF + // For now, we'll create a simple HTML version + const reportHTML = generateReportHTML(currentReport); + const blob = new Blob([reportHTML], { type: 'text/html' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `DOZ3_Report_${currentReport.patientId}_${new Date().getTime()}.html`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); +}); + +// Print handler +printBtn.addEventListener('click', function() { + window.print(); +}); + +// New report handler +newReportBtn.addEventListener('click', function() { + reportForm.reset(); + document.getElementById('examDate').valueAsDate = new Date(); + document.querySelector('.form-section').style.display = 'block'; + reportSection.style.display = 'none'; + currentReport = null; + window.scrollTo({ top: 0, behavior: 'smooth' }); +}); + +// Helper function to get exam type label +function getExamTypeLabel(examType) { + const labels = { + 'fluorography': 'Флюорография', + 'radiography': 'Рентгенография', + 'ct': 'Компьютерная томография', + 'mammography': 'Маммография' + }; + return labels[examType] || examType; +} + +// Generate report HTML +function generateReport(data) { + const html = ` +

Отчет ДОЗ-3 - Регистрация дозы облучения

+ +
+ Номер отчета: DOZ3-${data.patientId}-${Date.now()} +
+ +
+ Дата генерации: ${data.generatedDate} +
+ +
+ +

Данные пациента

+ +
+ ФИО пациента: ${escapeHtml(data.patientName)} +
+ +
+ Номер пациента: ${escapeHtml(data.patientId)} +
+ +

Данные обследования

+ +
+ Дата обследования: ${formatDate(data.examDate)} +
+ +
+ Тип обследования: ${escapeHtml(data.examTypeLabel)} +
+ +
+ Область обследования: ${escapeHtml(data.bodyPart)} +
+ +
+ Доза облучения: ${escapeHtml(data.dose)} мЗв +
+ +

Медицинский персонал

+ +
+ Врач: ${escapeHtml(data.doctor)} +
+ + ${data.notes ? ` +

Примечания

+
+ ${escapeHtml(data.notes)} +
+ ` : ''} + +
+ +

+ Этот отчет сгенерирован автоматически системой X-Ray DOZ3 Report Generator. +

+ `; + + reportContent.innerHTML = html; +} + +// Generate standalone HTML for download +function generateReportHTML(data) { + return ` + + + + + + Отчет ДОЗ-3 - ${escapeHtml(data.patientName)} + + + + ${reportContent.innerHTML} + + + `.trim(); +} + +// Helper function to escape HTML +function escapeHtml(text) { + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; +} + +// Helper function to format date +function formatDate(dateString) { + const date = new Date(dateString); + return date.toLocaleDateString('ru-RU', { + year: 'numeric', + month: 'long', + day: 'numeric' + }); +} + +// Save reports to localStorage +function saveReportToHistory(report) { + let history = JSON.parse(localStorage.getItem('doz3Reports') || '[]'); + history.unshift({ + ...report, + id: Date.now() + }); + // Keep only last 50 reports + history = history.slice(0, 50); + localStorage.setItem('doz3Reports', JSON.stringify(history)); +} + +// Initialize +console.log('X-Ray DOZ3 Report Generator initialized'); diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..67311fe --- /dev/null +++ b/styles.css @@ -0,0 +1,251 @@ +:root { + --primary-color: #2563eb; + --secondary-color: #64748b; + --success-color: #10b981; + --danger-color: #ef4444; + --light-bg: #f8fafc; + --white: #ffffff; + --text-dark: #1e293b; + --text-light: #64748b; + --border-color: #e2e8f0; + --shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + line-height: 1.6; + color: var(--text-dark); + background-color: var(--light-bg); +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; +} + +header { + text-align: center; + margin-bottom: 40px; + padding: 40px 20px; + background: linear-gradient(135deg, var(--primary-color) 0%, #1d4ed8 100%); + color: var(--white); + border-radius: 12px; + box-shadow: var(--shadow-lg); +} + +header h1 { + font-size: 2.5rem; + margin-bottom: 10px; +} + +.subtitle { + font-size: 1.2rem; + opacity: 0.9; +} + +main { + display: grid; + gap: 30px; +} + +section { + background: var(--white); + padding: 30px; + border-radius: 12px; + box-shadow: var(--shadow); +} + +h2 { + color: var(--text-dark); + margin-bottom: 20px; + font-size: 1.8rem; + border-bottom: 3px solid var(--primary-color); + padding-bottom: 10px; +} + +.form-group { + margin-bottom: 20px; +} + +.form-group label { + display: block; + margin-bottom: 8px; + font-weight: 600; + color: var(--text-dark); +} + +.form-group input, +.form-group select, +.form-group textarea { + width: 100%; + padding: 12px; + border: 2px solid var(--border-color); + border-radius: 8px; + font-size: 1rem; + transition: border-color 0.3s ease; +} + +.form-group input:focus, +.form-group select:focus, +.form-group textarea:focus { + outline: none; + border-color: var(--primary-color); +} + +.form-group textarea { + resize: vertical; + font-family: inherit; +} + +.btn { + padding: 12px 24px; + border: none; + border-radius: 8px; + font-size: 1rem; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + margin-right: 10px; + margin-bottom: 10px; +} + +.btn-primary { + background-color: var(--primary-color); + color: var(--white); +} + +.btn-primary:hover { + background-color: #1d4ed8; + transform: translateY(-2px); + box-shadow: var(--shadow-lg); +} + +.btn-secondary { + background-color: var(--secondary-color); + color: var(--white); +} + +.btn-secondary:hover { + background-color: #475569; + transform: translateY(-2px); + box-shadow: var(--shadow-lg); +} + +.btn-link { + background-color: transparent; + color: var(--primary-color); + border: 2px solid var(--primary-color); + text-decoration: none; + display: inline-block; +} + +.btn-link:hover { + background-color: var(--primary-color); + color: var(--white); +} + +.report-content { + background-color: var(--light-bg); + padding: 30px; + border-radius: 8px; + margin-bottom: 20px; + border-left: 4px solid var(--primary-color); +} + +.report-content h3 { + color: var(--primary-color); + margin-bottom: 15px; +} + +.report-content .report-field { + margin-bottom: 15px; + padding: 10px; + background-color: var(--white); + border-radius: 6px; +} + +.report-content .report-field strong { + color: var(--text-dark); + display: inline-block; + min-width: 200px; +} + +.report-actions { + display: flex; + flex-wrap: wrap; + gap: 10px; +} + +.info-section ul { + margin-left: 20px; + margin-top: 15px; +} + +.info-section li { + margin-bottom: 8px; + color: var(--text-light); +} + +.info-section p { + color: var(--text-light); + margin-bottom: 15px; +} + +.documentation { + margin-top: 25px; + padding-top: 20px; + border-top: 1px solid var(--border-color); +} + +footer { + text-align: center; + margin-top: 40px; + padding: 20px; + color: var(--text-light); +} + +@media print { + body { + background-color: var(--white); + } + + .form-section, + .info-section, + .report-actions, + header, + footer { + display: none !important; + } + + .report-section { + display: block !important; + box-shadow: none; + } +} + +@media (max-width: 768px) { + header h1 { + font-size: 2rem; + } + + .subtitle { + font-size: 1rem; + } + + section { + padding: 20px; + } + + .btn { + width: 100%; + margin-right: 0; + } +} From 29436b19fe8f55284c2c074099be810a8d3d4a02 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 22:18:54 +0000 Subject: [PATCH 3/5] Fix: Update button text and comments to accurately reflect HTML download functionality Co-authored-by: GraphSaf <63410676+GraphSaf@users.noreply.github.com> --- index.html | 2 +- script.js | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index 219e7ce..4840f58 100644 --- a/index.html +++ b/index.html @@ -73,7 +73,7 @@

Создание отчета

Сгенерированный отчет

- +
diff --git a/script.js b/script.js index 31f65ee..2efd5f0 100644 --- a/script.js +++ b/script.js @@ -51,10 +51,9 @@ clearFormBtn.addEventListener('click', function() { } }); -// Download PDF handler +// Download report handler downloadBtn.addEventListener('click', function() { - // In a real application, this would generate a PDF - // For now, we'll create a simple HTML version + // Generate and download the report as an HTML file const reportHTML = generateReportHTML(currentReport); const blob = new Blob([reportHTML], { type: 'text/html' }); const url = URL.createObjectURL(blob); From 705d3f4367381109a4131e51fb52b53e3234ccaf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 22:20:42 +0000 Subject: [PATCH 4/5] Refactor: Fix circular dependency and remove dead code Co-authored-by: GraphSaf <63410676+GraphSaf@users.noreply.github.com> --- script.js | 96 +++++++++++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 52 deletions(-) diff --git a/script.js b/script.js index 2efd5f0..b4fa74e 100644 --- a/script.js +++ b/script.js @@ -94,7 +94,50 @@ function getExamTypeLabel(examType) { // Generate report HTML function generateReport(data) { - const html = ` + reportContent.innerHTML = generateReportContent(data); +} + +// Generate standalone HTML for download +function generateReportHTML(data) { + const reportHTML = generateReportContent(data); + return ` + + + + + + Отчет ДОЗ-3 - ${escapeHtml(data.patientName)} + + + + ${reportHTML} + + + `.trim(); +} + +// Helper to generate report content HTML +function generateReportContent(data) { + return `

Отчет ДОЗ-3 - Регистрация дозы облучения

@@ -154,45 +197,6 @@ function generateReport(data) { Этот отчет сгенерирован автоматически системой X-Ray DOZ3 Report Generator.

`; - - reportContent.innerHTML = html; -} - -// Generate standalone HTML for download -function generateReportHTML(data) { - return ` - - - - - - Отчет ДОЗ-3 - ${escapeHtml(data.patientName)} - - - - ${reportContent.innerHTML} - - - `.trim(); } // Helper function to escape HTML @@ -212,17 +216,5 @@ function formatDate(dateString) { }); } -// Save reports to localStorage -function saveReportToHistory(report) { - let history = JSON.parse(localStorage.getItem('doz3Reports') || '[]'); - history.unshift({ - ...report, - id: Date.now() - }); - // Keep only last 50 reports - history = history.slice(0, 50); - localStorage.setItem('doz3Reports', JSON.stringify(history)); -} - // Initialize console.log('X-Ray DOZ3 Report Generator initialized'); From e9e0a06feffd4726b41909e401909735a3428c08 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 22:21:58 +0000 Subject: [PATCH 5/5] Add date validation in formatDate function Co-authored-by: GraphSaf <63410676+GraphSaf@users.noreply.github.com> --- script.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/script.js b/script.js index b4fa74e..c2b5e27 100644 --- a/script.js +++ b/script.js @@ -209,6 +209,9 @@ function escapeHtml(text) { // Helper function to format date function formatDate(dateString) { const date = new Date(dateString); + if (isNaN(date.getTime())) { + return dateString; // Return original string if invalid + } return date.toLocaleDateString('ru-RU', { year: 'numeric', month: 'long',