Роли, переделывание отчета, изменение на главной странице

This commit is contained in:
brusnitsyn
2026-01-11 23:37:18 +09:00
parent eb019504d7
commit d4f077cdaf
59 changed files with 2099 additions and 366 deletions

View File

@@ -34,7 +34,7 @@ const themeOverrides = {
<!-- <SideMenu />-->
<!-- </NLayoutSider>-->
<NLayout content-class="pl-4">
<NLayout>
<div>
<slot name="header" />
</div>

View File

@@ -3,24 +3,21 @@ import { NFlex, NSpace, NDivider, NButton } from 'naive-ui'
import ReportSelectDate from "../../Components/ReportSelectDate.vue";
import AppUserButton from "./AppUserButton.vue";
import {Link} from "@inertiajs/vue3";
import AppHeaderRole from "./AppHeaderRole.vue";
</script>
<template>
<NFlex justify="space-between" align="center" class="px-4 w-full h-full">
<NSpace align="center">
<NFlex align="center">
<NButton :tag="Link" text href="/">
Метрика
</NButton>
<NDivider vertical />
<ReportSelectDate />
</NSpace>
<NSpace align="center">
<NButton :tag="Link" text href="/">
Мои отчеты??
</NButton>
<NDivider vertical />
<!-- <NDivider vertical />-->
<!-- <ReportSelectDate />-->
</NFlex>
<NFlex align="center">
<AppUserButton />
</NSpace>
</NFlex>
</NFlex>
</template>

View File

@@ -0,0 +1,35 @@
<script setup>
import {computed, onMounted, ref} from "vue";
import {NSelect} from 'naive-ui'
const roles = ref([])
const onFetchUserRoles = async () => {
await axios.get('/api/app/user/roles').then(res => {
roles.value = res.data
})
}
const roleOptions = computed(() => {
if (roles.value.length > 0) return roles.value.map(itm => ({
label: itm.name,
value: itm.role_id
}))
})
const value = ref(null)
onMounted(async () => {
await onFetchUserRoles()
})
</script>
<template>
<div>
<NSelect v-model:value="value" :options="roleOptions" class="w-50!" />
</div>
</template>
<style scoped>
</style>

View File

@@ -1,6 +1,6 @@
<script setup>
import {useAuthStore} from "../../Stores/auth.js";
import {NDropdown, NButton} from 'naive-ui'
import {NDropdown, NButton, NText} from 'naive-ui'
const authStore = useAuthStore()
const userOptions = [
@@ -20,11 +20,14 @@ const themeOverride = {
</script>
<template>
<NDropdown :options="userOptions" placement="bottom-end">
<NButton :theme-overrides="themeOverride">
{{ authStore.user?.name }}
</NButton>
</NDropdown>
<NText>
{{ authStore.user?.name }}
</NText>
<!-- <NDropdown :options="userOptions" placement="bottom-end">-->
<!-- <NButton :theme-overrides="themeOverride">-->
<!-- {{ authStore.user?.name }}-->
<!-- </NButton>-->
<!-- </NDropdown>-->
</template>
<style scoped>

View File

@@ -7,7 +7,7 @@ import {computed} from "vue";
import {format} from "date-fns";
import {ru} from "date-fns/locale";
import {useNow} from "@vueuse/core";
import {TbArticle, TbChartTreemap} from "vue-icons-plus/tb";
import {TbArticle, TbChartTreemap, TbDoorExit} from "vue-icons-plus/tb";
import {useReportStore} from "../Stores/report.js";
const authStore = useAuthStore()
@@ -37,7 +37,7 @@ const currentDate = computed(() => {
<StartButton title="Заполнить сводную"
description="Заполняется регулярно"
href="/dashboard"
href="/report"
:icon="TbArticle"
/>
<StartButton title="Статистика моего отделения"
@@ -45,9 +45,10 @@ const currentDate = computed(() => {
:href="`/statistic?sent_at=${reportStore.timestampCurrentRange}&groupId=1`"
:icon="TbChartTreemap"
/>
<StartButton title="Заполнить сводную"
description="Заполняется регулярно"
<StartButton title="Выйти из системы"
description="Завершение работы с текущей учетной записью"
href="/dashboard"
:icon="TbDoorExit"
/>
</NFlex>
</div>

View File

@@ -0,0 +1,116 @@
<script setup>
import { ref } from 'vue'
import {useVueFlow, VueFlow} from '@vue-flow/core'
import AppLayout from "../../Layouts/AppLayout.vue";
const props = defineProps({
path: {
type: Object,
default: {}
}
})
const elements = ref([
// Ноды (блоки)
{
id: '1',
type: 'input',
label: 'Поступление',
position: { x: 100, y: 50 },
data: {
patient: 'Иванов И.И.',
time: '09:00',
status: 'arrival'
},
class: 'node-arrival'
},
{
id: '2',
label: 'Первичный осмотр',
position: { x: 300, y: 50 },
data: {
doctor: 'Петров П.П.',
diagnosis: 'Предварительный',
duration: '30 мин'
},
class: 'node-examination'
},
{
id: '3',
label: 'Анализы',
position: { x: 500, y: 50 },
data: {
tests: ['Кровь', 'Моча', 'УЗИ'],
lab: 'Лаборатория №1'
},
class: 'node-tests'
},
{
id: '4',
label: 'Лечение',
position: { x: 300, y: 200 },
data: {
procedures: ['Капельница', 'Уколы'],
ward: 'Палата 304'
},
class: 'node-treatment'
},
{
id: '5',
type: 'output',
label: 'Выписка',
position: { x: 100, y: 350 },
data: {
outcome: 'Выздоровление',
date: '2024-01-15'
},
class: 'node-discharge'
},
])
const edges = ref([
{ id: 'e1-2', source: '1', target: '2', label: 'Направлен' },
{ id: 'e2-3', source: '2', target: '3', label: 'На анализы' },
{ id: 'e3-4', source: '3', target: '4', label: 'Результаты' },
{ id: 'e4-5', source: '4', target: '5', label: 'Завершено' }
])
</script>
<template>
<AppLayout>
<div class="h-[calc(100vh-48px)]">
<VueFlow v-model:nodes="elements" v-model:edges="edges" :fit-view-on-init="true">
<template #node-custom="{ data, label }">
<div class="patient-node">
<div class="node-icon">
<span v-if="data.status === 'arrival'">🏥</span>
<span v-else-if="data.doctor">👨</span>
<span v-else-if="data.tests">🧪</span>
<span v-else-if="data.procedures">💉</span>
<span v-else></span>
</div>
<div class="node-info">
<strong>{{ label }}</strong>
<div v-if="data.patient" class="patient-name">
{{ data.patient }}
</div>
<div v-if="data.time" class="node-time">
{{ data.time }}
</div>
</div>
</div>
</template>
</VueFlow>
</div>
</AppLayout>
</template>
<style scoped>
/* Цвета для разных типов нод */
.node-arrival { border-color: #4CAF50; }
.node-examination { border-color: #2196F3; }
.node-tests { border-color: #FF9800; }
.node-treatment { border-color: #9C27B0; }
.node-discharge { border-color: #607D8B; }
</style>

View File

@@ -0,0 +1,42 @@
<script setup>
import { NFlex, NButton } from 'naive-ui'
import ReportHeader from "./ReportHeader.vue";
import ReportFormInput from "./ReportFormInput.vue";
import ReportSection from "./ReportSection.vue";
import {useReportStore} from "../../../Stores/report.js";
import {useAuthStore} from "../../../Stores/auth.js";
const props = defineProps({
mode: {
type: String,
default: 'fillable' // 'fillable', 'readonly'
}
})
const authStore = useAuthStore()
const reportStore = useReportStore()
const onSubmit = () => {
reportStore.sendReportForm({
departmentId: authStore.userDepartment.department_id
})
}
</script>
<template>
<NFlex vertical class="max-w-6xl mx-auto mt-6 mb-4 w-full">
<ReportHeader :mode="mode" />
<ReportFormInput />
<ReportSection label="Планово" />
<NButton secondary size="large" @click="onSubmit">
Сохранить отчет
</NButton>
</NFlex>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,25 @@
<script setup>
import {NCard, NFlex, NFormItem, NForm, NInputNumber} from "naive-ui";
import {useReportStore} from "../../../Stores/report.js";
const reportStore = useReportStore()
</script>
<template>
<NCard>
<NForm>
<NFlex>
<template v-for="metrikaItem in reportStore.reportInfo?.metrikaItems">
<NFormItem :label="metrikaItem.name" :show-feedback="false">
<NInputNumber v-model:value="reportStore.reportForm[`metrika_item_${metrikaItem.metrika_item_id}`]"
:default-value="metrikaItem.default_value" />
</NFormItem>
</template>
</NFlex>
</NForm>
</NCard>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,88 @@
<script setup>
import {NStatistic, NRow, NCol, NCard, NButton, NTag, NDatePicker, NFlex, NSelect, NText, NH2} from "naive-ui";
import {computed, ref} from "vue";
import {format} from "date-fns";
import {useNow} from "@vueuse/core";
import {ru} from "date-fns/locale";
import {useAuthStore} from "../../../Stores/auth.js";
import {storeToRefs} from "pinia";
import {RiAddCircleLine} from 'vue-icons-plus/ri'
import {useReportStore} from "../../../Stores/report.js";
const props = defineProps({
mode: {
type: String,
default: 'fillable' // 'fillable', 'readonly'
},
isShowDepartmentSelect: {
type: Boolean,
default: false
},
})
const departments = [
{
label: 'Все отделения',
value: 0
}
]
const authStore = useAuthStore()
const reportStore = useReportStore()
const {user, availableDepartments} = storeToRefs(authStore)
const {reportInfo} = storeToRefs(reportStore)
const isFillableMode = computed(() => props.mode.toLowerCase() === 'fillable')
const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
const selectDepartment = ref(0)
const currentDate = computed(() => {
const formatted = format(useNow().value, 'PPPPpp', {
locale: ru
})
return formatted.charAt(0).toUpperCase() + formatted.slice(1)
})
</script>
<template>
<NCard>
<NFlex vertical>
<NFlex align="center" justify="space-between">
<NH2 v-if="isFillableMode" class="mb-0!">
{{ currentDate }}
</NH2>
<NDatePicker v-if="isReadonlyMode" />
<NFlex align="center" :wrap="false">
<NTag v-if="isFillableMode" type="info" :bordered="false">
{{ authStore.userDepartment.name_full }}
</NTag>
<NSelect v-if="isReadonlyMode" v-model:value="selectDepartment" :options="departments" />
</NFlex>
</NFlex>
<NFlex justify="space-between" align="center" :wrap="false">
<NRow class="grow">
<NCol :span="4">
<NStatistic label="Коек" :value="reportStore.reportInfo?.department.beds" />
</NCol>
<NCol :span="5">
<NStatistic label="Загруженность" :value="`${reportStore.reportInfo?.department.percentLoadedBeds}%`" />
</NCol>
</NRow>
<NButton type="primary" secondary>
<template #icon>
<RiAddCircleLine />
</template>
Нежелательное событие
</NButton>
</NFlex>
</NFlex>
</NCard>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,90 @@
<script setup>
import {NCard, NFlex, NAlert, NCollapse, NCollapseItem} from 'naive-ui'
import ReportSectionItem from "./ReportSectionItem.vue";
import {computed} from "vue";
import {useReportStore} from "../../../Stores/report.js";
import {storeToRefs} from "pinia";
import ReportSectionHeader from "./ReportSectionHeader.vue";
const props = defineProps({
mode: {
type: String,
default: 'fillable' // 'fillable', 'readonly'
}
})
const reportStore = useReportStore()
const {patientsData} = storeToRefs(reportStore)
const handleItemDragged = (event) => {
console.log('Начато перетаскивание:', event)
}
// Обработка события drop
const handleItemDropped = (event) => {
const { item, fromStatus, toStatus } = event
console.log(event)
// Добавляем в целевую таблицу
if (toStatus && patientsData.value[toStatus]) {
// Проверяем, нет ли уже такого элемента
if (!patientsData.value[toStatus].some(i => i.id === item.id)) {
patientsData.value[toStatus].push(item)
}
}
}
const isFillableMode = computed(() => props.mode.toLowerCase() === 'fillable')
const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
</script>
<template>
<NCard>
<NCollapse>
<NCollapseItem name="1">
<template #header>
<ReportSectionHeader title="Планово" status="plan" />
</template>
<ReportSectionItem status="plan"
@item-dragged="handleItemDragged"
/>
</NCollapseItem>
<NCollapseItem name="2">
<template #header>
<ReportSectionHeader title="Экстренно" status="emergency" />
</template>
<ReportSectionItem status="emergency"
@item-dragged="handleItemDragged"
/>
</NCollapseItem>
<NCollapseItem name="3">
<template #header>
<ReportSectionHeader title="Наблюдение" status="observation" />
</template>
<NFlex :size="12">
<ReportSectionItem status="observation"
@item-dragged="handleItemDragged"
@item-dropped="handleItemDropped"
/>
<NAlert v-if="isFillableMode" type="info" class="w-full">
Перетаскивайте строки из верхних таблиц, что бы добавить в наблюдение
</NAlert>
</NFlex>
</NCollapseItem>
<NCollapseItem name="4">
<template #header>
<ReportSectionHeader title="Умершие" status="deceased" />
</template>
<ReportSectionItem status="deceased"
@item-dragged="handleItemDragged"
@item-dropped="handleItemDropped"
/>
</NCollapseItem>
</NCollapse>
</NCard>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,55 @@
<script setup>
import {computed, onMounted, ref} from "vue";
import {NSkeleton, NText} from 'naive-ui'
const props = defineProps({
title: {
type: String,
default: null
},
status: {
type: String,
default: null
}
})
const isLoading = ref(true)
const countPatient = ref(null)
const fetchPatientCount = async () => {
if (props.status === 'plan' || props.status === 'emergency') {
isLoading.value = true
await axios.post('/api/mis/patients/count', {
status: props.status
}).then((res) => {
countPatient.value = res.data
}).finally(() => {
isLoading.value = false
})
} else {
isLoading.value = false
}
}
const computedHeader = computed(() => {
if (countPatient.value !== null) {
return `${props.title} (${countPatient.value})`
} else {
return props.title
}
})
onMounted(async () => {
await fetchPatientCount()
})
</script>
<template>
<NSkeleton text style="width: 128px; height: 22px" round v-if="isLoading" />
<NText v-else>
{{ computedHeader }}
</NText>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,166 @@
<script setup>
import {NDataTable} from "naive-ui";
import {useReportStore} from "../../../Stores/report.js";
import {computed, h, onMounted, ref, watch} from "vue";
import { VueDraggableNext } from 'vue-draggable-next'
import {storeToRefs} from "pinia";
const props = defineProps({
mode: {
type: String,
default: 'fillable' // 'fillable', 'readonly'
},
keys: {
type: Array,
default: ['num', 'fullname', 'age', 'birth_date', 'ds']
},
status: {
type: String,
default: null // 'plan'
}
})
const isFillableMode = computed(() => props.mode.toLowerCase() === 'fillable')
const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
const emit = defineEmits(['item-dragged', 'item-dropped'])
const reportStore = useReportStore()
const {patientsData} = storeToRefs(reportStore)
// Получаем базовые колонки
const baseColumns = reportStore.getColumnsByKey(props.keys)
const data = ref([])
const isLoading = ref(true)
// Добавляем drag колонку если режим fillable
const columns = computed(() => {
if (!isFillableMode.value) return baseColumns
const dragColumn = {
title: '',
key: 'drag',
width: 40,
render: (row) => h('div', {
style: {
cursor: 'grab',
color: '#666',
textAlign: 'center',
userSelect: 'none'
}
}, '⋮⋮')
}
return [dragColumn, ...baseColumns]
})
const handleDragStart = (e, row) => {
// Устанавливаем данные о перетаскиваемом элементе
e.dataTransfer.setData('application/json', JSON.stringify({
row: row,
fromStatus: props.status
}))
e.dataTransfer.effectAllowed = 'copy'
const rowElement = e.target
// Эмитим событие для родителя
emit('item-dragged', { row, fromStatus: props.status })
// Добавляем класс для визуальной обратной связи
e.target.classList.add('dragging')
}
const handleDragEnd = (e) => {
if (e.target) {
e.target.classList.remove('dragging')
}
}
const handleDragOver = (e) => {
e.preventDefault()
}
const handleDrop = (e) => {
e.preventDefault()
try {
const dragData = JSON.parse(e.dataTransfer.getData('application/json'))
// Эмитим событие для родителя
emit('item-dropped', {
item: dragData.row,
fromStatus: dragData.fromStatus,
toStatus: props.status
})
} catch (error) {
console.error('Drop error:', error)
}
}
const fetchPatients = async () => {
if (props.status === 'plan' || props.status === 'emergency') {
isLoading.value = true
await axios.post('/api/mis/patients', {
status: props.status
}).then((res) => {
patientsData.value[props.status] = res.data
}).finally(() => {
isLoading.value = false
})
} else {
isLoading.value = false
}
}
function rowProps(row) {
return {
draggable: true,
style: 'cursor: grab;',
onDragstart: (e) => {
handleDragStart(e, row)
},
onDragend: (e) => {
handleDragEnd(e)
},
onDragover: (e) => {
handleDragOver(e)
},
onDrop: (e) => {
handleDrop(e)
}
}
}
onMounted(async () => {
await fetchPatients()
})
</script>
<template>
<NDataTable :columns="columns"
:data="patientsData[status]"
size="small"
@drop="handleDrop"
@dragover="handleDragOver"
:loading="isLoading"
virtual-scroll
max-height="200"
min-height="200"
:row-props="rowProps"
class="text-sm!">
</NDataTable>
<!-- <NDataTable :columns="columns"-->
<!-- :data="data"-->
<!-- size="small"-->
<!-- max-height="200"-->
<!-- class="text-sm!">-->
<!-- </NDataTable>-->
</template>
<style scoped>
:deep(.n-data-table-th),
:deep(.n-data-table-td) {
white-space: nowrap !important;
font-size: var(--n-font-size);
}
</style>

View File

@@ -1,19 +1,18 @@
<script setup>
import AppLayout from "../../Layouts/AppLayout.vue";
import {NList, NListItem, NFlex, NInput, NButton} from 'naive-ui'
import {useForm} from "@inertiajs/vue3";
import {computed} from "vue";
import MetrikaForm from "../Metriks/Components/MetrikaForm.vue";
import ReportForm from "./Components/ReportForm.vue";
import {useReportStore} from "../../Stores/report.js";
import {onMounted} from "vue";
const props = defineProps({
metriks: {
type: Array
}
const reportStore = useReportStore()
onMounted(async () => {
await reportStore.getReportInfo()
})
</script>
<template>
<AppLayout>
<MetrikaForm :group-id="1" />
<ReportForm />
</AppLayout>
</template>

View File

@@ -1,58 +1,135 @@
<script setup>
import {NDataTable} from 'naive-ui'
import AppLayout from "../../Layouts/AppLayout.vue";
import {NList, NListItem, NFlex, NText, NH1, NTag} from 'naive-ui'
import {ref} from "vue";
const props = defineProps({
is_view_only: {
type: Boolean,
default: false
},
period: {
data: {
type: Object,
default: {}
},
group: {
type: Object,
default: {}
},
metrics: {
type: Object,
default: {}
},
form: {
type: Object,
default: {}
},
default: []
}
})
const columns = ref([
{
title: 'Отделение',
key: 'department',
width: 240,
titleAlign: 'center'
},
{
title: 'Кол-во коек',
key: 'beds',
width: 60,
titleAlign: 'center',
align: 'center'
},
{
title: 'Состояло',
key: 'beds',
width: 84,
titleAlign: 'center',
align: 'center'
},
{
title: 'Поступило',
key: 'received',
titleAlign: 'center',
children: [
{
title: 'Всего',
key: 'all',
width: 60,
titleAlign: 'center',
align: 'center'
},
{
title: 'План',
key: 'plan',
width: 60,
titleAlign: 'center',
align: 'center'
},
{
title: 'Экстр',
key: 'emergency',
width: 60,
titleAlign: 'center',
align: 'center'
},
{
title: 'Перевод',
key: '',
width: 84,
titleAlign: 'center',
align: 'center'
},
]
},
{
title: 'Выбыло',
key: 'leave',
width: 84,
titleAlign: 'center',
align: 'center'
},
{
title: 'Состоит',
key: 'consist',
width: 84,
titleAlign: 'center',
align: 'center'
},
{
title: '% загруженности',
key: 'percentLoadedBeds',
width: 84,
titleAlign: 'center',
align: 'center'
},
{
title: 'Операции',
key: '',
titleAlign: 'center',
children: [
{
title: 'Э',
key: '',
width: 60,
titleAlign: 'center',
align: 'center'
},
{
title: 'П',
key: '',
width: 60,
titleAlign: 'center',
align: 'center'
},
]
},
])
</script>
<template>
<AppLayout>
<div class="max-w-6xl mx-auto mt-4 mb-4">
<div class="flex items-center justify-between">
<div>
<n-h1 class="!mb-2">{{ group.name }}</n-h1>
<n-text depth="3" v-if="group.description">
{{ group.description }}
</n-text>
</div>
</div>
<NList>
<NListItem v-for="metric in metrics.values">
<NFlex justify="space-between" align="center" class="w-full px-4">
<div>
{{metric.item_name}}
</div>
<div>
{{metric.sum}}
</div>
</NFlex>
</NListItem>
</NList>
</div>
</AppLayout>
<AppLayout>
<NDataTable :columns="columns"
:data="data"
size="small"
:single-line="false"
striped
min-height="calc(100vh - 48px - 70px)"
max-height="calc(100vh - 48px - 70px)"
>
</NDataTable>
</AppLayout>
</template>
<style scoped>
:deep(.n-data-table-th),
:deep(.n-data-table-td) {
//white-space: nowrap !important;
font-size: var(--n-font-size);
}
</style>

View File

@@ -0,0 +1,58 @@
<script setup>
import AppLayout from "../../Layouts/AppLayout.vue";
import {NList, NListItem, NFlex, NText, NH1, NTag} from 'naive-ui'
const props = defineProps({
is_view_only: {
type: Boolean,
default: false
},
period: {
type: Object,
default: {}
},
group: {
type: Object,
default: {}
},
metrics: {
type: Object,
default: {}
},
form: {
type: Object,
default: {}
},
})
</script>
<template>
<AppLayout>
<div class="max-w-6xl mx-auto mt-4 mb-4">
<div class="flex items-center justify-between">
<div>
<n-h1 class="!mb-2">{{ group.name }}</n-h1>
<n-text depth="3" v-if="group.description">
{{ group.description }}
</n-text>
</div>
</div>
<NList>
<NListItem v-for="metric in metrics.values">
<NFlex justify="space-between" align="center" class="w-full px-4">
<div>
{{metric.item_name}}
</div>
<div>
{{metric.sum}}
</div>
</NFlex>
</NListItem>
</NList>
</div>
</AppLayout>
</template>
<style scoped>
</style>

View File

@@ -7,7 +7,7 @@ export const useAuthStore = defineStore('authStore', () => {
const user = usePage().props.user
const token = user?.token
const permissions = user?.permissions
const availableDepartments = ref([])
const availableDepartments = ref(user?.available_departments)
// Инициализация axios с токеном
if (token?.value) {
@@ -21,7 +21,7 @@ export const useAuthStore = defineStore('authStore', () => {
const isNurse = computed(() => user.role === 'nurse')
const isHeadOfDepartment = computed(() => user.role === 'head_of_department')
const isStatistician = computed(() => user.role === 'statistician')
const userDepartment = computed(() => user.department || '')
const userDepartment = computed(() => user.current_department || '')
const clearAuthData = () => {
user.value = null

View File

@@ -1,6 +1,7 @@
import {defineStore} from "pinia";
import {useTimestamp} from "@vueuse/core";
import {computed, ref} from "vue";
import {router} from "@inertiajs/vue3";
export const useReportStore = defineStore('reportStore', () => {
const timestampNow = useTimestamp()
@@ -22,6 +23,82 @@ export const useReportStore = defineStore('reportStore', () => {
const dataOnReport = ref(null)
const reportInfo = ref(null)
const patientColumns = [
{
title: '№',
width: '80',
key: 'num'
},
{
title: 'ФИО',
width: '320',
key: 'fullname'
},
{
title: 'Возраст',
key: 'age'
},
{
title: 'Дата рождения',
key: 'birth_date'
},
{
title: 'Диагноз',
key: 'ds'
}
]
const patientsData = ref({
plan: [],
emergency: [],
observation: [],
deceased: []
})
const reportForm = ref({})
const getColumnsByKey = (keys) => {
const result = []
for (const key of keys) {
const column = patientColumns.find(item => item.key === key)
result.push(column)
}
return result
}
const sendReportForm = (assignForm) => {
const form = {
metrics: reportForm.value,
observationPatients: patientsData.value['observation'],
...assignForm
}
axios.post('/api/report', form)
.then(r => {
window.$message.success('Отчет сохранен')
resetReportForm()
router.visit('/')
})
}
const resetReportForm = () => {
reportForm.value = {}
patientsData.value.observation = []
}
const $reset = () => {
}
const getReportInfo = async () => {
await axios.get('/api/report').then((res) => {
reportInfo.value = res.data
})
}
const getDataOnReportDate = async () => {
await axios.get(`/api/metric-forms/1/report-by-date?sent_at=${timestampCurrentRange.value}`)
.then(res => {
@@ -38,7 +115,15 @@ export const useReportStore = defineStore('reportStore', () => {
timestampCurrent,
timestampCurrentRange,
dataOnReport,
patientColumns,
patientsData,
reportInfo,
reportForm,
getDataOnReportDate
getColumnsByKey,
getDataOnReportDate,
getReportInfo,
sendReportForm,
resetReportForm,
}
})

View File

@@ -1,9 +1,10 @@
import './bootstrap';
import '../css/app.css';
import { createApp, h } from 'vue'
import { createInertiaApp } from '@inertiajs/vue3'
import {createPinia} from "pinia";
import {setupNaiveDiscreteApi} from "./Plugins/NaiveUI.js";
import './bootstrap';
import '../css/app.css';
createInertiaApp({
id: 'onboard',