Обновлен стартовый экран

Переписаны запросы для статистики, отчетов
Добавлена интеграция отчета сестры
This commit is contained in:
brusnitsyn
2026-05-28 22:10:00 +09:00
parent 90e0d04dfd
commit 739168d427
96 changed files with 6663 additions and 1465 deletions

View File

@@ -0,0 +1,98 @@
<script setup>
import {NButton, NForm, NFormItem, NInput, NModal, NSpace, NText, NSpin} from "naive-ui";
import {computed, ref, useTemplateRef, watch} from "vue";
const show = defineModel('show')
const props = defineProps({
patient: Object
})
const emits = defineEmits([
'onSubmit'
])
const formRef = useTemplateRef('form')
const loading = ref(true)
const model = ref({
observable_reason: null
})
const rules = {
observable_reason: {
required: true,
}
}
const resetForm = () => {
model.value = {
observable_reason: null
}
}
const actionText = computed(() => props.patient.in_observable ? 'Просмотр контроля' : 'Постановка на контроль')
const submit = () => {
formRef.value?.validate((errors) => {
if (!errors) {
emits('onSubmit', {
...props.patient,
...model.value
})
cancel()
}
else {
alert(errors)
}
})
}
const cancel = () => {
resetForm()
show.value = false
loading.value = true
}
const onAfterEnter = () => {
model.value.observable_reason = props.patient.observable?.observable_reason
loading.value = false
}
</script>
<template>
<NModal v-model:show="show"
:mask-closable="false"
@afterLeave="cancel"
@afterEnter="onAfterEnter"
segmented
draggable
class="max-w-lg relative overflow-hidden"
preset="card"
>
<template #header>
<NSpace vertical :size="1" class="text-base font-normal">
<NText strong>
{{ patient.full_name ?? '' }}
</NText>
<NText depth="3" class="text-sm">
{{ actionText }}
</NText>
</NSpace>
</template>
<NForm ref="form" :model="model" :rules="rules">
<NFormItem label="Опишите причину" path="observable_reason" :show-feedback="false">
<NInput type="textarea" :rows="6" :resizable="false" v-model:value="model.observable_reason" />
</NFormItem>
</NForm>
<template #action>
<NSpace align="center" justify="end">
<NButton type="primary" secondary @click="submit">
Сохранить
</NButton>
</NSpace>
</template>
<div v-if="loading" class="absolute inset-0 z-10 flex items-center justify-center" style="background-color: var(--n-color);">
<NSpin size="small" description="Загрузка..." />
</div>
</NModal>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,239 @@
<script setup>
import {NModal, NList, NListItem, NThing, NAvatar, NIcon, NDrawer, NDrawerContent,
NText, NDivider, NForm, NFormItem, NInput, NFlex, NButton, NScrollbar, NEmpty
} from 'naive-ui'
import {computed, ref, watch} from "vue";
import { TbAlertCircle, TbPencil, TbTrashX, TbCirclePlus, TbCheck, TbX } from 'vue-icons-plus/tb'
import {format, isValid} from "date-fns";
const show = defineModel('show')
const props = defineProps({
report: Object,
canSaveReport: Boolean
})
const emits = defineEmits([
'onSubmit'
])
const formRef = ref()
const createDrawerShow = ref(false)
const rules = {
comment: {
required: true,
message: 'Заполните этот блок',
trigger: 'blur'
}
}
const selectedEvent = ref(null)
const drawerCreatingMode = ref(true) // or false = editing
const model = ref({
unwantedEvents: []
})
// Создание в сторе и открытие drawer с формой нежелательного события
const onCreateEvent = () => {
drawerCreatingMode.value = true
const createDate = format(new Date(), 'Создано dd.MM.yyyy в HH:mm')
model.value.unwantedEvents.push({
title: `Нежелательное событие №${model.value.unwantedEvents.length + 1}`,
comment: '',
created_at: createDate
})
const length = model.value.unwantedEvents.length
selectedEvent.value = model.value.unwantedEvents[length - 1]
createDrawerShow.value = true
}
const onEditEvent = (event) => {
drawerCreatingMode.value = false
selectedEvent.value = event
createDrawerShow.value = true
}
const hasDisableAddButton = computed(() => {
return false
})
const onDeleteEvent = (event) => {
const indexOfDelete = model.value.unwantedEvents.findIndex(itm => itm === event)
if (typeof event.unwanted_event_id !== 'undefined') {
axios.delete(`/api/report/unwanted-event/${event.unwanted_event_id}`)
.then(() => {
model.value.unwantedEvents.splice(indexOfDelete, 1)
})
} else {
model.value.unwantedEvents.splice(indexOfDelete, 1)
}
}
const onCancelDrawerEvent = (event) => {
onDeleteEvent(event)
createDrawerShow.value = false
}
const onCreateDrawerEvent = () => {
formRef.value?.validate((errors) => {
if (!errors) {
createDrawerShow.value = false
}
else {
}
})
}
const onBeforeLeaveModal = () => {
selectedEvent.value = null
drawerCreatingMode.value = true
createDrawerShow.value = false
emits('onSubmit', model.value.unwantedEvents)
}
const cancel = () => {
resetForm()
show.value = false
loading.value = true
}
const onAfterEnter = () => {
model.value.unwantedEvents = props.report?.unwanted_events ?? []
}
// watch(() => props.report, (newReport) => {
// model.value.unwantedEvents = newReport?.unwanted_events ?? []
// })
</script>
<template>
<NModal v-model:show="show"
title="Нежелательные события"
preset="card"
:mask-closable="false"
:close-on-esc="false"
@afterEnter="onAfterEnter"
@before-leave="onBeforeLeaveModal"
class="max-w-4xl overflow-clip h-[calc(100vh-220px)]"
>
<template v-if="model.unwantedEvents.length">
<NScrollbar class="max-h-[calc(100vh-282px)] pr-3">
<NList>
<NListItem v-for="event in model.unwantedEvents">
<NThing>
<template #avatar>
<NAvatar>
<NIcon>
<TbAlertCircle class="text-red-400" />
</NIcon>
</NAvatar>
</template>
<template #header>
{{ event.title }}
</template>
<template #description>
<NText depth="3">
{{ event.created_at }}
</NText>
</template>
<NText>
{{ event.comment }}
</NText>
<template v-if="canSaveReport" #action>
<NFlex align="center">
<NButton secondary size="small" @click="onEditEvent(event)" :disabled="hasDisableAddButton">
<template #icon>
<TbPencil />
</template>
Редактировать
</NButton>
<NDivider vertical />
<NButton type="error" secondary size="small" @click="onDeleteEvent(event)" :disabled="hasDisableAddButton">
<template #icon>
<TbTrashX />
</template>
Удалить
</NButton>
</NFlex>
</template>
</NThing>
</NListItem>
</NList>
</NScrollbar>
</template>
<template v-else>
<div class="h-full flex items-center justify-center">
<NEmpty description="Нежелательных событий не найдено!">
<template #extra>
<NButton v-if="canSaveReport" type="primary" secondary @click="onCreateEvent()" size="small" :disabled="hasDisableAddButton">
<template #icon>
<TbCirclePlus />
</template>
Создать
</NButton>
</template>
</NEmpty>
</div>
</template>
<template v-if="canSaveReport" #action>
<NFlex id="modal-action" align="center" justify="space-between">
<NButton type="primary" secondary @click="onCreateEvent()" :disabled="hasDisableAddButton">
<template #icon>
<TbCirclePlus />
</template>
Создать событие
</NButton>
</NFlex>
</template>
<NDrawer
:show="createDrawerShow"
placement="bottom"
:max-height="600"
:min-height="400"
:default-height="400"
resizable
:trap-focus="false"
:block-scroll="false"
:mask-closable="false"
to="#modal-action"
>
<NDrawerContent>
<template #header>
<template v-if="drawerCreatingMode">Создание события</template>
<template v-else>Редактирование события</template>
</template>
<NForm ref="formRef" :model="selectedEvent" :rules="rules">
<NFormItem :show-label="false" path="comment">
<NInput type="textarea" :rows="8" v-model:value="selectedEvent.comment" />
</NFormItem>
</NForm>
<template #footer>
<NFlex align="center">
<NButton v-if="drawerCreatingMode" type="error" secondary @click="onCancelDrawerEvent(selectedEvent)">
<template #icon>
<TbX />
</template>
Отменить создание
</NButton>
<NDivider v-if="drawerCreatingMode" vertical />
<NButton type="primary" @click="onCreateDrawerEvent">
<template #icon>
<TbCheck />
</template>
<template v-if="drawerCreatingMode">Создать</template>
<template v-else>Сохранить</template>
</NButton>
</NFlex>
</template>
</NDrawerContent>
</NDrawer>
</NModal>
</template>
<style scoped>
</style>