302 lines
11 KiB
Vue
302 lines
11 KiB
Vue
<script setup>
|
|
import AppLayout from "../../Layouts/AppLayout.vue";
|
|
import {useReportStore} from "../../Stores/report.js";
|
|
import {onMounted, ref, watch, provide} from "vue";
|
|
import {useAuthStore} from "../../Stores/auth.js";
|
|
import {
|
|
NFormItem,
|
|
NFlex,
|
|
NInputNumber,
|
|
NTabPane,
|
|
NTabs,
|
|
NTag,
|
|
NRow, NCol, NDivider, NButton, NSpace
|
|
} from "naive-ui";
|
|
import DatePickerQuery from "../../Components/DatePickerQuery.vue";
|
|
import AppPanel from "../../Components/AppPanel.vue";
|
|
import AppContainer from "../../Components/AppContainer.vue";
|
|
import ReportWidget from "./Components/ReportWidget.vue";
|
|
import {router} from "@inertiajs/vue3";
|
|
import HeaderWidget from "./Components/HeaderWidget.vue";
|
|
import DutyPatientsPane from "./Components/DutyPatientsPane.vue";
|
|
import NursePatientsPane from "./Components/NursePatientsPane.vue";
|
|
import OperationWidget from "./Components/Widgets/OperationWidget.vue";
|
|
import LoadedWidget from "./Components/Widgets/LoadedWidget.vue";
|
|
import UnwantedEventModal from "./Components/Modals/UnwantedEventModal.vue";
|
|
import RecipientWidget from "./Components/Widgets/RecipientWidget.vue";
|
|
|
|
const props = defineProps({
|
|
department: {
|
|
type: Object,
|
|
default: {}
|
|
},
|
|
report: {
|
|
type: Object,
|
|
default: {}
|
|
},
|
|
metrikaItems: {
|
|
type: Array,
|
|
default: []
|
|
},
|
|
|
|
canSaveReport: Boolean,
|
|
canEditPastReport: Boolean,
|
|
canSaveNurseReport: Boolean,
|
|
stats: {
|
|
type: Object,
|
|
default: () => ({
|
|
duty: {
|
|
beds: 0,
|
|
loaded: 0,
|
|
current: 0,
|
|
urgent: 0,
|
|
discharged: 0,
|
|
},
|
|
nurse: {
|
|
current: 0,
|
|
urgent: 0,
|
|
discharged: 0,
|
|
},
|
|
})
|
|
},
|
|
latestReport: {
|
|
type: Object,
|
|
default: () => ({ })
|
|
},
|
|
patients: {
|
|
type: Array,
|
|
default: () => ([])
|
|
},
|
|
nursePatients: {
|
|
type: Array,
|
|
default: () => ([])
|
|
},
|
|
dates: {
|
|
type: Array,
|
|
default: []
|
|
},
|
|
selectedUserId: {
|
|
type: Number,
|
|
default: null
|
|
},
|
|
selectedDepartmentId: {
|
|
type: Number,
|
|
default: null
|
|
}
|
|
})
|
|
|
|
const reportStore = useReportStore()
|
|
const authStore = useAuthStore()
|
|
const userDepartment = authStore.userDepartment
|
|
|
|
const patientCollection = ref({...props.patients})
|
|
const nursePatientCollection = ref({...props.nursePatients})
|
|
const latestReportObj = ref(props.latestReport ?? {
|
|
unwanted_events: []
|
|
})
|
|
const loading = ref(false)
|
|
const showUnwantedEventModal = ref(false)
|
|
const reportForm = ref({
|
|
recipient: props.stats.duty.recipient,
|
|
discharged: props.stats.duty.discharged,
|
|
current: props.stats.duty.current,
|
|
staff: 0,
|
|
observables: []
|
|
})
|
|
const updateReportForm = (form) => {
|
|
reportForm.value = {
|
|
...reportForm.value,
|
|
...form
|
|
}
|
|
}
|
|
const updateUnwantedEvents = (unwanted_events) => {
|
|
reportForm.value = {
|
|
...reportForm.value,
|
|
unwanted_events
|
|
}
|
|
|
|
latestReportObj.value = {
|
|
...latestReportObj.value,
|
|
unwanted_events
|
|
}
|
|
}
|
|
|
|
// Прокидываем reportForm всем потомкам
|
|
provide('reportForm', {
|
|
reportForm,
|
|
updateReportForm
|
|
})
|
|
|
|
const submit = () => {
|
|
const queryString = window.location.search;
|
|
const params = new URLSearchParams(queryString);
|
|
const url = new URL(`${window.location.origin}/duty/report/save`)
|
|
const startAt = params.get('startAt')
|
|
const endAt = params.get('endAt')
|
|
if (startAt && startAt !== 'null') url.searchParams.append('startAt', startAt)
|
|
if (endAt && endAt !== 'null') url.searchParams.append('endAt', endAt)
|
|
|
|
router.post(url.toString(), {
|
|
...reportForm.value,
|
|
userId: props.selectedUserId,
|
|
departmentId: props.selectedDepartmentId,
|
|
}, {
|
|
onSuccess: () => {
|
|
alert('Сохранено')
|
|
}
|
|
})
|
|
}
|
|
|
|
const onShowUnwantedEventModal = () => {
|
|
showUnwantedEventModal.value = true
|
|
}
|
|
|
|
const addObservablePatient = (observable) => {
|
|
const collection = patientCollection.value.data
|
|
const item = collection.find(obs => obs.id === observable.id)
|
|
if (item) {
|
|
item.in_observable = true
|
|
item.observable = { observable_reason: observable.observable_reason }
|
|
}
|
|
}
|
|
|
|
const removeObservablePatient = (patient) => {
|
|
const collection = patientCollection.value.data
|
|
const item = collection.find(p => p.id === patient.id)
|
|
if (item) {
|
|
item.in_observable = false
|
|
}
|
|
}
|
|
|
|
const syncPageProps = (pageProps = props) => {
|
|
reportStore.initializeFromPage(pageProps)
|
|
|
|
patientCollection.value = {...pageProps.patients}
|
|
nursePatientCollection.value = {...pageProps.nursePatients}
|
|
latestReportObj.value = pageProps.latestReport ?? { unwanted_events: [] }
|
|
reportForm.value = {
|
|
...reportForm.value,
|
|
recipient: pageProps.stats.duty.recipient,
|
|
discharged: pageProps.stats.duty.discharged,
|
|
current: pageProps.stats.duty.current,
|
|
}
|
|
}
|
|
|
|
onMounted(syncPageProps)
|
|
|
|
watch(() => props, (newProps) => {
|
|
syncPageProps(newProps)
|
|
}, {
|
|
deep: true,
|
|
immediate: true
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<AppLayout>
|
|
<!-- <template #headerSuffix>-->
|
|
<!-- <StatisticRecipientPlanOfYear :plan="reportStore.reportInfo.department.recipientPlanOfYear" :progress="reportStore.reportInfo.department.progressPlanOfYear" />-->
|
|
<!-- </template>-->
|
|
<!-- <ReportForm :mode />-->
|
|
|
|
<AppContainer>
|
|
<AppPanel>
|
|
<NFlex justify="space-between" align="center">
|
|
<NSpace>
|
|
<NTag type="info" :bordered="false">
|
|
{{ department.name_full }}
|
|
</NTag>
|
|
<NTag v-if="props.latestReport" type="warning" :bordered="false">
|
|
Отчет создан: {{ `${props.latestReport.doctor.FAM_V} ${props.latestReport.doctor.IM_V} ${props.latestReport.doctor.OT_V}` }}
|
|
</NTag>
|
|
</NSpace>
|
|
<DatePickerQuery :date="dates" :is-head-or-admin="true" class="text-lg!" />
|
|
</NFlex>
|
|
<NDivider dashed class="my-4! mt-3!" />
|
|
<NRow class="grow space-x-2 h-[82.78px]">
|
|
<NCol :span="3">
|
|
<HeaderWidget label="Коек"
|
|
:counter="stats.duty.beds" />
|
|
</NCol>
|
|
<NCol :span="3">
|
|
<LoadedWidget :counter="stats.duty.loaded" />
|
|
</NCol>
|
|
<NCol :span="3">
|
|
<RecipientWidget :beds="stats.duty.beds"
|
|
:duty-current="stats.duty.current"
|
|
:nurse-current="stats.nurse.current"
|
|
/>
|
|
</NCol>
|
|
<NCol :span="3">
|
|
<HeaderWidget label="Поступило"
|
|
is-double-counter
|
|
:counter="stats.duty.recipient"
|
|
:counter-suffix="stats.nurse.recipient"
|
|
/>
|
|
</NCol>
|
|
<NCol :span="3">
|
|
<HeaderWidget label="Выбыло"
|
|
is-double-counter
|
|
:counter="stats.duty.discharged"
|
|
:counter-suffix="stats.nurse.discharged"
|
|
/>
|
|
</NCol>
|
|
</NRow>
|
|
</AppPanel>
|
|
<div class="grid grid-cols-[1fr_auto] gap-x-2">
|
|
<AppPanel>
|
|
<NFlex align="center" :wrap="false">
|
|
<NFormItem label="Поступило" :show-feedback="false">
|
|
<NInputNumber :disabled="!canSaveReport" :min="0" v-model:value="reportForm.recipient" />
|
|
</NFormItem>
|
|
<NFormItem label="Выбыло" :show-feedback="false">
|
|
<NInputNumber :disabled="!canSaveReport" :min="0" v-model:value="reportForm.discharged" />
|
|
</NFormItem>
|
|
<NFormItem label="Состоит" :show-feedback="false">
|
|
<NInputNumber :disabled="!canSaveReport" :min="0" v-model:value="reportForm.current" />
|
|
</NFormItem>
|
|
<NFormItem label="Мед. персонал" :show-feedback="false">
|
|
<NInputNumber :disabled="!canSaveReport" :min="0" v-model:value="reportForm.staff" />
|
|
</NFormItem>
|
|
</NFlex>
|
|
</AppPanel>
|
|
<NFlex :wrap="false" :size="8">
|
|
<ReportWidget :counter="stats.duty.deceased">
|
|
Умерло
|
|
</ReportWidget>
|
|
<ReportWidget :counter="stats.duty.deceased">
|
|
<NSpace vertical :size="1">
|
|
<div>Летальность</div>
|
|
<div>%</div>
|
|
</NSpace>
|
|
</ReportWidget>
|
|
<OperationWidget :planned="stats.duty.surgical_planned" :urgent="stats.duty.surgical_urgent" />
|
|
</NFlex>
|
|
</div>
|
|
<AppPanel>
|
|
<NTabs type="segment">
|
|
<NTabPane name="mis" tab="МИС" display-directive="show">
|
|
<DutyPatientsPane :patients="patientCollection" :nurse-patients="nursePatientCollection" @create-observable="addObservablePatient" @remove-observable="removeObservablePatient" />
|
|
</NTabPane>
|
|
<NTabPane name="nurse" tab="Журнал пациентов" display-directive="show">
|
|
<NursePatientsPane :patients="nursePatientCollection" />
|
|
</NTabPane>
|
|
</NTabs>
|
|
</AppPanel>
|
|
<AppPanel>
|
|
<NFlex justify="space-between">
|
|
<NButton v-if="props.canSaveReport || props.canEditPastReport"
|
|
secondary type="error" :loading="loading" @click="onShowUnwantedEventModal">
|
|
Нежелательные события ({{ latestReportObj.unwanted_events?.length ?? 0 }})
|
|
</NButton>
|
|
<NButton v-if="props.canSaveReport" secondary @click="submit" :loading="loading">
|
|
Сохранить отчет
|
|
</NButton>
|
|
</NFlex>
|
|
</AppPanel>
|
|
</AppContainer>
|
|
|
|
<UnwantedEventModal v-model:show="showUnwantedEventModal" :can-save-report="props.canSaveReport" :report="latestReportObj" @onSubmit="updateUnwantedEvents" />
|
|
</AppLayout>
|
|
</template>
|