Добавлено формирование отчета
И индикатор реанимации
This commit is contained in:
23
app/Exports/ReportPageExport.php
Normal file
23
app/Exports/ReportPageExport.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exports;
|
||||||
|
|
||||||
|
use App\Exports\Sheets\ArraySheetExport;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
|
||||||
|
|
||||||
|
class ReportPageExport implements WithMultipleSheets
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly array $summaryRows,
|
||||||
|
private readonly array $patientRows
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function sheets(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new ArraySheetExport('Сводка', $this->summaryRows),
|
||||||
|
new ArraySheetExport('Пациенты', $this->patientRows),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
92
app/Exports/Sheets/ArraySheetExport.php
Normal file
92
app/Exports/Sheets/ArraySheetExport.php
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exports\Sheets;
|
||||||
|
|
||||||
|
use Maatwebsite\Excel\Concerns\FromArray;
|
||||||
|
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithStyles;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithTitle;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
|
class ArraySheetExport implements FromArray, WithTitle, WithStyles, ShouldAutoSize
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly string $sheetTitle,
|
||||||
|
private readonly array $rows
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function array(): array
|
||||||
|
{
|
||||||
|
return $this->rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function title(): string
|
||||||
|
{
|
||||||
|
return $this->sheetTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function styles(Worksheet $sheet): array
|
||||||
|
{
|
||||||
|
$sheet->getPageSetup()->setPaperSize(PageSetup::PAPERSIZE_A4);
|
||||||
|
$sheet->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE);
|
||||||
|
$sheet->getPageSetup()->setFitToPage(true);
|
||||||
|
$sheet->getPageSetup()->setFitToWidth(1);
|
||||||
|
$sheet->getPageSetup()->setFitToHeight(0);
|
||||||
|
|
||||||
|
$sheet->getPageMargins()->setTop(0.2);
|
||||||
|
$sheet->getPageMargins()->setBottom(0.2);
|
||||||
|
$sheet->getPageMargins()->setLeft(0.2);
|
||||||
|
$sheet->getPageMargins()->setRight(0.2);
|
||||||
|
|
||||||
|
$highestRow = $sheet->getHighestRow();
|
||||||
|
$highestColumn = $sheet->getHighestColumn();
|
||||||
|
|
||||||
|
$sheet->getStyle("A1:{$highestColumn}{$highestRow}")->applyFromArray([
|
||||||
|
'alignment' => [
|
||||||
|
'horizontal' => Alignment::HORIZONTAL_LEFT,
|
||||||
|
'vertical' => Alignment::VERTICAL_CENTER,
|
||||||
|
'wrapText' => true,
|
||||||
|
],
|
||||||
|
'borders' => [
|
||||||
|
'allBorders' => [
|
||||||
|
'borderStyle' => Border::BORDER_THIN,
|
||||||
|
'color' => ['argb' => 'D0D7DE'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$sheet->getStyle("A1:{$highestColumn}1")->applyFromArray([
|
||||||
|
'font' => [
|
||||||
|
'bold' => true,
|
||||||
|
],
|
||||||
|
'fill' => [
|
||||||
|
'fillType' => Fill::FILL_SOLID,
|
||||||
|
'startColor' => ['argb' => 'EEF2FF'],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
for ($row = 1; $row <= $highestRow; $row++) {
|
||||||
|
$firstCell = (string) $sheet->getCell("A{$row}")->getValue();
|
||||||
|
$secondCell = (string) $sheet->getCell("B{$row}")->getValue();
|
||||||
|
|
||||||
|
// Строки секций (МИС / Спец. контингент)
|
||||||
|
if (in_array($firstCell, ['МИС', 'Спец. контингент'], true) && $secondCell === '') {
|
||||||
|
$sheet->getStyle("A{$row}:{$highestColumn}{$row}")->applyFromArray([
|
||||||
|
'font' => ['bold' => true],
|
||||||
|
'fill' => [
|
||||||
|
'fillType' => Fill::FILL_SOLID,
|
||||||
|
'startColor' => ['argb' => 'F4F6F8'],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sheet->freezePane('A2');
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/Models/ReanimationPatientIndicator.php
Normal file
19
app/Models/ReanimationPatientIndicator.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class ReanimationPatientIndicator extends Model
|
||||||
|
{
|
||||||
|
protected $primaryKey = 'reanimation_patient_indicator_id';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'rf_department_id',
|
||||||
|
'rf_report_id',
|
||||||
|
'rf_medicalhistory_id',
|
||||||
|
'indicator',
|
||||||
|
'comment',
|
||||||
|
'created_by',
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('reanimation_patient_indicators', function (Blueprint $table) {
|
||||||
|
$table->id('reanimation_patient_indicator_id');
|
||||||
|
$table->unsignedBigInteger('rf_department_id');
|
||||||
|
$table->unsignedBigInteger('rf_report_id')->nullable();
|
||||||
|
$table->unsignedBigInteger('rf_medicalhistory_id');
|
||||||
|
$table->string('indicator', 100);
|
||||||
|
$table->text('comment')->nullable();
|
||||||
|
$table->unsignedBigInteger('created_by')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->index(
|
||||||
|
['rf_department_id', 'rf_medicalhistory_id', 'created_at'],
|
||||||
|
'idx_reanimation_indicator_department_history_created_at'
|
||||||
|
);
|
||||||
|
$table->index(['rf_report_id'], 'idx_reanimation_indicator_report');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('reanimation_patient_indicators');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
<script setup>
|
||||||
|
import {computed, reactive, watch} from "vue";
|
||||||
|
import {NButton, NForm, NFormItem, NInput, NModal, NSelect} from "naive-ui";
|
||||||
|
import {useReportStore} from "../../../Stores/report.js";
|
||||||
|
|
||||||
|
const show = defineModel('show')
|
||||||
|
const props = defineProps({
|
||||||
|
patient: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const reportStore = useReportStore()
|
||||||
|
const form = reactive({
|
||||||
|
indicator: '',
|
||||||
|
comment: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const indicatorOptions = [
|
||||||
|
{ label: 'Стабильный', value: 'stable' },
|
||||||
|
{ label: 'Средней тяжести', value: 'moderate' },
|
||||||
|
{ label: 'Тяжелый', value: 'severe' },
|
||||||
|
{ label: 'Критический', value: 'critical' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const isDisabled = computed(() => !props.patient?.medical_history_id)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.patient,
|
||||||
|
(patient) => {
|
||||||
|
form.indicator = patient?.reanimation_indicator ?? ''
|
||||||
|
form.comment = patient?.reanimation_comment ?? ''
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
if (isDisabled.value || !form.indicator) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await reportStore.saveReanimationIndicator({
|
||||||
|
medical_history_id: props.patient.medical_history_id,
|
||||||
|
indicator: form.indicator,
|
||||||
|
comment: form.comment || null,
|
||||||
|
})
|
||||||
|
|
||||||
|
show.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NModal
|
||||||
|
v-model:show="show"
|
||||||
|
preset="card"
|
||||||
|
title="Индикатор состояния"
|
||||||
|
class="max-w-lg"
|
||||||
|
:mask-closable="false"
|
||||||
|
>
|
||||||
|
<NForm :model="form">
|
||||||
|
<NFormItem label="Состояние">
|
||||||
|
<NSelect
|
||||||
|
v-model:value="form.indicator"
|
||||||
|
:options="indicatorOptions"
|
||||||
|
placeholder="Выберите состояние"
|
||||||
|
/>
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="Комментарий">
|
||||||
|
<NInput
|
||||||
|
v-model:value="form.comment"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
:resizable="false"
|
||||||
|
placeholder="Дополнительная информация"
|
||||||
|
/>
|
||||||
|
</NFormItem>
|
||||||
|
</NForm>
|
||||||
|
|
||||||
|
<template #action>
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<NButton
|
||||||
|
type="primary"
|
||||||
|
:disabled="isDisabled || !form.indicator"
|
||||||
|
@click="handleSave"
|
||||||
|
>
|
||||||
|
Сохранить
|
||||||
|
</NButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</NModal>
|
||||||
|
</template>
|
||||||
Reference in New Issue
Block a user