Files
onboard/resources/js/Pages/Nurse/Report/Index.vue
brusnitsyn 739168d427 Обновлен стартовый экран
Переписаны запросы для статистики, отчетов
Добавлена интеграция отчета сестры
2026-05-28 22:10:00 +09:00

248 lines
8.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import AppLayout from "../../../Layouts/AppLayout.vue";
import {NFlex, NTag, NDataTable, NButton, NTabs, NTabPane} from 'naive-ui'
import AppContainer from "../../../Components/AppContainer.vue";
import AppPanel from "../../../Components/AppPanel.vue";
import ShiftPickerQuery from "../../../Components/ShiftPickerQuery.vue";
import UrgencyBadge from "../../../Components/UrgencyBadge.vue";
import {computed, h, onMounted, ref, shallowRef} from "vue"
import {TbCirclePlus, TbPencil} from 'vue-icons-plus/tb'
import {useAuthStore} from "../../../Stores/auth.js";
import {usePage} from "@inertiajs/vue3";
import AddMedicalHistoryModal from "../Components/AddMedicalHistoryModal.vue";
import EditMedicalHistoryModal from "../Components/EditMedicalHistoryModal.vue";
import {router} from "@inertiajs/vue3";
import ActionsColumnDataTable from "../Components/ActionsColumnDataTable.vue";
import {useAppDialog} from "../../../Composables/useAppDialog.js";
const props = defineProps({
patients: {
type: Array,
default: []
},
reportNurseId: {
type: Number,
default: null
},
canSaveReport: Boolean,
canEditPastReport: Boolean,
department: {
type: Object,
default: null
},
selectedUserId: {
type: Number,
default: null
},
selectedDepartmentId: {
type: Number,
default: null
},
dates: {
type: Array,
default: []
}
})
const canEdit = computed(() => props.canSaveReport || props.canEditPastReport)
const showAddMedicalHistoryModal = shallowRef(false)
const showEditMedicalHistoryModal = shallowRef(false)
const editHistoryId = ref(null)
const authStore = useAuthStore()
const userDepartment = authStore.userDepartment
const loading = ref(false)
const patientsByGroup = computed(() => {
const groups = {
urgent: [],
planned: [],
deceased: [],
in_department: [],
recipient: [],
discharged: [],
transferred: [],
};
for (const p of props.patients.data) {
// Группировка по срочности
if (p.patient_urgency === 'urgent') groups.urgent.push(p);
else if (p.patient_urgency === 'planned') groups.planned.push(p);
// Группировка по статусу (дублирование нужно, если один пациент может быть в двух таблицах)
if (groups.hasOwnProperty(p.patient_status)) {
groups[p.patient_status].push(p);
}
}
return groups;
})
const columns = [
{
title: 'ФИО',
key: 'full_name',
minWidth: 280,
maxWidth: 400,
resizable: true
},
{
title: 'Дата поступления',
key: 'latest_migration.ingoing_date',
minWidth: 180,
maxWidth: 180,
width: 180,
resizable: false
},
{
title: 'Срочность',
key: 'urgency_id',
render: (row) => {
return h(UrgencyBadge, {urgencyId: row.urgency_id})
}
},
{
title: '',
key: 'actions',
align: 'end',
render: (row) => {
return h(
ActionsColumnDataTable,
{
row: row,
canEdit: canEdit.value,
onClickDelete: (historyId) => onClickDeleteButton(historyId),
onClickEdit: (historyId) => onClickEditButton(historyId),
}
)
}
}
]
const onClickEditButton = (historyId) => {
showEditMedicalHistoryModal.value = true
editHistoryId.value = historyId
}
const onClickDeleteButton = async (historyId) => {
const confirmed = await useAppDialog({
title: 'Удалить историю?',
content: 'Это действие необратимо',
onConfirm: async () => {
await axios.delete(`/api/nurse/patients/${historyId}`)
}
})
if (confirmed) {
loading.value = true
router.reload({
only: ['patients'],
onSuccess: () => {
loading.value = false
}
})
}
}
const submit = () => {
router.post('/nurse/report/save', {
userId: props.selectedUserId,
departmentId: props.selectedDepartmentId,
}, {
onSuccess: () => {
alert('Сохранено')
}
})
}
const formattedLabel = (word, count) => {
return `${word} (${count})`
}
</script>
<template>
<AppLayout>
<AppContainer>
<AppPanel>
<NFlex justify="space-between" align="center">
<NTag type="info" :bordered="false">
{{ department?.name_full ?? userDepartment.name_full }}
</NTag>
<ShiftPickerQuery :date="dates" class="text-lg!" />
</NFlex>
</AppPanel>
<AppPanel header="Журнал пациентов" header-include-body>
<template v-if="canEdit" #header-extra>
<NButton secondary :loading="loading" @click="showAddMedicalHistoryModal = true">
<template #icon>
<TbCirclePlus />
</template>
Добавить пациента
</NButton>
</template>
<NTabs type="line">
<NTabPane name="all"
:tab="formattedLabel('В отделении', patientsByGroup.in_department.length)"
>
<NDataTable :columns="columns"
:data="patientsByGroup.in_department"
table-layout="fixed"
max-height="calc(100vh - 435px)"
min-height="calc(100vh - 435px)"
:loading="loading"
/>
</NTabPane>
<NTabPane name="income" :tab="formattedLabel('Поступившие', patientsByGroup.recipient.length)">
<NDataTable :columns="columns"
:data="patientsByGroup.recipient"
table-layout="fixed"
max-height="calc(100vh - 435px)"
min-height="calc(100vh - 435px)"
:loading="loading"
/>
</NTabPane>
<NTabPane name="outcome" :tab="formattedLabel('Выписанные', patientsByGroup.discharged.length)">
<NDataTable :columns="columns"
:data="patientsByGroup.discharged"
table-layout="fixed"
max-height="calc(100vh - 435px)"
min-height="calc(100vh - 435px)"
:loading="loading"
/>
</NTabPane>
<NTabPane name="dead" :tab="formattedLabel('Умершие', patientsByGroup.deceased.length)">
<NDataTable :columns="columns"
:data="patientsByGroup.deceased"
table-layout="fixed"
max-height="calc(100vh - 435px)"
min-height="calc(100vh - 435px)"
:loading="loading"
/>
</NTabPane>
<NTabPane name="transfer" :tab="formattedLabel('Переведенные', patientsByGroup.transferred.length)">
<NDataTable :columns="columns"
:data="patientsByGroup.transferred"
table-layout="fixed"
max-height="calc(100vh - 435px)"
min-height="calc(100vh - 435px)"
:loading="loading"
/>
</NTabPane>
</NTabs>
</AppPanel>
<NButton v-if="canSaveReport" secondary size="large" @click="submit" :loading="loading">
Сохранить отчет
</NButton>
</AppContainer>
<AddMedicalHistoryModal v-model:show="showAddMedicalHistoryModal" />
<EditMedicalHistoryModal v-model:show="showEditMedicalHistoryModal" :history-id="editHistoryId" :report-nurse-id="props.reportNurseId" />
</AppLayout>
</template>
<style scoped>
:deep(.n-data-table-th),
:deep(.n-data-table-td) {
font-size: var(--n-font-size);
}
</style>