* исправление подсчета операций пациентов
* поправил поле выбора даты * добавил индикатор в контроле * окно выбора пользователя для сводной * привязка окна для ввода причины контроля * добавил привязку историй пациентов для просмотра статистики по дням * поправил фиксацию фио ответственного, убрал при диапазоне * отключение ролей адм и зав от реплики
This commit is contained in:
@@ -116,6 +116,12 @@ const modelComputed = computed({
|
||||
reportStore.timestampCurrentRange = [value, value]
|
||||
}
|
||||
|
||||
const queryString = window.location.search
|
||||
const params = new URLSearchParams(queryString)
|
||||
const userId = params.get('userId')
|
||||
|
||||
reportStore.reportInfo.userId = userId
|
||||
|
||||
reportStore.getDataOnReportDate(reportStore.timestampCurrentRange)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -19,8 +19,16 @@ const props = defineProps({
|
||||
icon: {
|
||||
type: [Object, Function],
|
||||
default: null
|
||||
},
|
||||
tag: {
|
||||
type: [Object, Function, String],
|
||||
default: Link
|
||||
},
|
||||
click: {
|
||||
type: [Function, Object],
|
||||
}
|
||||
})
|
||||
const emits = defineEmits(['click'])
|
||||
|
||||
const buttonThemeOverride = {
|
||||
heightLarge: '64px',
|
||||
@@ -33,10 +41,25 @@ const pThemeOverride = {
|
||||
}
|
||||
|
||||
const hasIcon = computed(() => props.icon !== null)
|
||||
|
||||
const isLink = computed(() => props.tag === 'link')
|
||||
|
||||
const onClick = () => {
|
||||
if (isLink.value) return
|
||||
|
||||
emits('click')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NButton :tag="Link" :href="href" :theme-overrides="buttonThemeOverride" size="large" block class="justify-start! text-left!">
|
||||
<NButton :tag="tag"
|
||||
:href="href"
|
||||
:theme-overrides="buttonThemeOverride"
|
||||
@click="onClick"
|
||||
size="large"
|
||||
block
|
||||
class="justify-start! text-left!"
|
||||
>
|
||||
<template v-if="hasIcon" #icon>
|
||||
<component :is="icon" v-if="icon" />
|
||||
</template>
|
||||
|
||||
@@ -18,7 +18,6 @@ const formRole = useForm({
|
||||
role_id: authStore.user.role.role_id
|
||||
})
|
||||
const onChangeRole = (roleId) => {
|
||||
console.log(roleId)
|
||||
formRole.post('/user/role/change', {
|
||||
onSuccess: () => {
|
||||
router.visit(window.location.pathname, {
|
||||
|
||||
@@ -3,12 +3,14 @@ import AppLayout from "../Layouts/AppLayout.vue";
|
||||
import {useAuthStore} from "../Stores/auth.js";
|
||||
import {NH1, NSpace, NP, NFlex} from 'naive-ui'
|
||||
import StartButton from "../Components/StartButton.vue";
|
||||
import {computed} from "vue";
|
||||
import {computed, ref} from "vue";
|
||||
import {format} from "date-fns";
|
||||
import {ru} from "date-fns/locale";
|
||||
import {useNow} from "@vueuse/core";
|
||||
import {TbArticle, TbChartTreemap, TbDoorExit} from "vue-icons-plus/tb";
|
||||
import {useReportStore} from "../Stores/report.js";
|
||||
import SelectUserModal from "./Report/Components/SelectUserModal.vue";
|
||||
import {Link} from "@inertiajs/vue3";
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const reportStore = useReportStore()
|
||||
@@ -20,6 +22,14 @@ const currentDate = computed(() => {
|
||||
|
||||
return formatted.charAt(0).toUpperCase() + formatted.slice(1)
|
||||
})
|
||||
|
||||
const showSelectUserModal = ref(false)
|
||||
const onShowSelectUserModal = () => {
|
||||
if (authStore.isDoctor)
|
||||
showSelectUserModal.value = true
|
||||
}
|
||||
|
||||
const reportButtonType = computed(() => authStore.isDoctor ? 'button' : Link)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -38,6 +48,8 @@ const currentDate = computed(() => {
|
||||
<StartButton title="Заполнить сводную"
|
||||
description="Заполняется регулярно"
|
||||
href="/report"
|
||||
:tag="reportButtonType"
|
||||
@click="onShowSelectUserModal"
|
||||
:icon="TbArticle"
|
||||
/>
|
||||
<StartButton title="Статистика моего отделения"
|
||||
@@ -52,6 +64,7 @@ const currentDate = computed(() => {
|
||||
/>
|
||||
</NFlex>
|
||||
</div>
|
||||
<SelectUserModal v-model:show="showSelectUserModal" />
|
||||
</AppLayout>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ const onSubmit = () => {
|
||||
|
||||
<ReportSection label="Планово" />
|
||||
|
||||
<NButton v-if="reportStore.reportInfo?.report.isActiveSendButton" secondary size="large" @click="onSubmit">
|
||||
<NButton v-if="reportStore.reportInfo?.report?.isActiveSendButton" secondary size="large" @click="onSubmit">
|
||||
Сохранить отчет
|
||||
</NButton>
|
||||
</NFlex>
|
||||
|
||||
@@ -9,7 +9,7 @@ const authStore = useAuthStore()
|
||||
|
||||
<template>
|
||||
<div class="grid grid-cols-[1fr_auto] gap-x-3">
|
||||
<NCard v-if="reportStore.reportInfo?.report.isActiveSendButton">
|
||||
<NCard v-if="reportStore.reportInfo?.report?.isActiveSendButton">
|
||||
<NForm>
|
||||
<template v-if="reportStore.isLoadReportInfo">
|
||||
<NFlex>
|
||||
@@ -35,13 +35,13 @@ const authStore = useAuthStore()
|
||||
style="--n-padding-top: 0; --n-padding-left: 0; --n-padding-bottom: 0; --n-padding-right: 0;"
|
||||
>
|
||||
<div class="w-full h-full flex flex items-center justify-center">
|
||||
<NStatistic label="Умерло" :value="reportStore.reportInfo?.department.deadCount" />
|
||||
<NStatistic label="Умерло" :value="reportStore.reportInfo?.department?.deadCount" />
|
||||
</div>
|
||||
</NCard>
|
||||
<NCard class="min-w-[120px] max-w-[120px] min-h-[100px] max-h-[102px] h-full"
|
||||
style="--n-padding-top: 0; --n-padding-bottom: 0; --n-padding-left: 8px; --n-padding-right: 8px;">
|
||||
<div class="w-full h-full flex flex items-center justify-center">
|
||||
<NStatistic :value="reportStore.reportInfo?.department.surgicalCount[1]">
|
||||
<NStatistic :value="reportStore.reportInfo?.department?.surgicalCount[1]">
|
||||
<template #label>
|
||||
<div class="flex flex-col">
|
||||
<span>Операций</span>
|
||||
@@ -49,7 +49,7 @@ const authStore = useAuthStore()
|
||||
</div>
|
||||
</template>
|
||||
<template #suffix>
|
||||
/ {{ reportStore.reportInfo?.department.surgicalCount[0] }}
|
||||
/ {{ reportStore.reportInfo?.department?.surgicalCount[0] }}
|
||||
</template>
|
||||
</NStatistic>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import {NSkeleton, NStatistic, NRow, NCol, NCard, NButton, NTag, NDatePicker, NFlex, NSelect, NText, NH2} from "naive-ui";
|
||||
import {NSkeleton, NStatistic, NRow, NCol, NSpace, 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";
|
||||
@@ -55,10 +55,15 @@ const currentDate = computed(() => {
|
||||
<NCard>
|
||||
<NFlex vertical>
|
||||
<div class="grid grid-cols-[auto_1fr_auto] items-center">
|
||||
<NTag v-if="isFillableMode" type="info" :bordered="false">
|
||||
{{ authStore.userDepartment.name_full }}
|
||||
</NTag>
|
||||
<DepartmentSelect v-if="isReadonlyMode" />
|
||||
<NSpace align="center">
|
||||
<NTag v-if="isFillableMode" type="info" :bordered="false">
|
||||
{{ authStore.userDepartment.name_full }}
|
||||
</NTag>
|
||||
<DepartmentSelect v-if="isReadonlyMode" />
|
||||
<NTag v-if="reportStore.reportInfo?.userName" type="warning">
|
||||
Ответственный: {{ reportStore.reportInfo?.userName }}
|
||||
</NTag>
|
||||
</NSpace>
|
||||
|
||||
<div class="col-3 w-full">
|
||||
<ReportSelectDate />
|
||||
@@ -71,7 +76,7 @@ const currentDate = computed(() => {
|
||||
<NStatistic label="Коек">
|
||||
<template #default>
|
||||
<NSkeleton v-if="reportStore.isLoadReportInfo" round class="w-[70px]! mt-2 h-[29px]!" />
|
||||
<span v-else>{{ reportStore.reportInfo?.department.beds }}</span>
|
||||
<span v-else>{{ reportStore.reportInfo?.department?.beds }}</span>
|
||||
</template>
|
||||
</NStatistic>
|
||||
</NCol>
|
||||
@@ -79,7 +84,7 @@ const currentDate = computed(() => {
|
||||
<NStatistic label="Загруженность">
|
||||
<template #default>
|
||||
<NSkeleton v-if="reportStore.isLoadReportInfo" round class="w-[70px]! mt-2 h-[29px]!" />
|
||||
<span v-else>{{ reportStore.reportInfo?.department.percentLoadedBeds }}%</span>
|
||||
<span v-else>{{ reportStore.reportInfo?.department?.percentLoadedBeds }}%</span>
|
||||
</template>
|
||||
</NStatistic>
|
||||
</NCol>
|
||||
@@ -87,7 +92,7 @@ const currentDate = computed(() => {
|
||||
<NStatistic label="Поступило">
|
||||
<template #default>
|
||||
<NSkeleton v-if="reportStore.isLoadReportInfo" round class="w-[70px]! mt-2 h-[29px]!" />
|
||||
<span v-else>{{ reportStore.reportInfo?.department.recipientCount }}</span>
|
||||
<span v-else>{{ reportStore.reportInfo?.department?.recipientCount }}</span>
|
||||
</template>
|
||||
</NStatistic>
|
||||
</NCol>
|
||||
@@ -95,7 +100,7 @@ const currentDate = computed(() => {
|
||||
<NStatistic label="Выбыло">
|
||||
<template #default>
|
||||
<NSkeleton v-if="reportStore.isLoadReportInfo" round class="w-[70px]! mt-2 h-[29px]!" />
|
||||
<span v-else>{{ reportStore.reportInfo?.department.extractCount }}</span>
|
||||
<span v-else>{{ reportStore.reportInfo?.department?.extractCount }}</span>
|
||||
</template>
|
||||
</NStatistic>
|
||||
</NCol>
|
||||
@@ -103,7 +108,7 @@ const currentDate = computed(() => {
|
||||
<NStatistic label="Состоит">
|
||||
<template #default>
|
||||
<NSkeleton v-if="reportStore.isLoadReportInfo" round class="w-[70px]! mt-2 h-[29px]!" />
|
||||
<span v-else>{{ reportStore.reportInfo?.department.currentCount }}</span>
|
||||
<span v-else>{{ reportStore.reportInfo?.department?.currentCount }}</span>
|
||||
</template>
|
||||
</NStatistic>
|
||||
</NCol>
|
||||
|
||||
@@ -47,7 +47,7 @@ const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
|
||||
<ReportSectionHeader title="Планово" status="plan" />
|
||||
</template>
|
||||
<ReportSectionItem status="plan"
|
||||
:accent-ids="reportStore.reportInfo?.department.recipientIds"
|
||||
:accent-ids="reportStore.reportInfo?.department?.recipientIds"
|
||||
is-draggable
|
||||
@item-dragged="handleItemDragged"
|
||||
/>
|
||||
@@ -57,7 +57,7 @@ const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
|
||||
<ReportSectionHeader title="Экстренно" status="emergency" />
|
||||
</template>
|
||||
<ReportSectionItem status="emergency"
|
||||
:accent-ids="reportStore.reportInfo?.department.recipientIds"
|
||||
:accent-ids="reportStore.reportInfo?.department?.recipientIds"
|
||||
is-draggable
|
||||
@item-dragged="handleItemDragged"
|
||||
/>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script setup>
|
||||
import {NIcon, NText, NDataTable, NButton, NTabs, NTabPane} from "naive-ui";
|
||||
import {NIcon, NText, NDataTable, NButton, NBadge, NTabs, NTabPane} 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";
|
||||
import {TbGripVertical} from "vue-icons-plus/tb";
|
||||
import {TbGripVertical, TbEye} from "vue-icons-plus/tb";
|
||||
import MoveModalComment from "./MoveModalComment.vue";
|
||||
|
||||
const props = defineProps({
|
||||
@@ -49,6 +49,7 @@ const data = ref([])
|
||||
const isLoading = ref(true)
|
||||
const showMoveModal = ref(false)
|
||||
const latestDropItem = ref(null)
|
||||
const activePatient = ref(null)
|
||||
|
||||
// Добавляем drag колонку если режим fillable
|
||||
const columns = computed(() => {
|
||||
@@ -100,22 +101,40 @@ const columns = computed(() => {
|
||||
}
|
||||
|
||||
const expandColumn = {
|
||||
type: 'expand',
|
||||
renderExpand: (rowData) => {
|
||||
title: '',
|
||||
width: '30',
|
||||
render: (rowData) => {
|
||||
return h(
|
||||
NText,
|
||||
NIcon,
|
||||
{
|
||||
class: 'max-w-full break-words whitespace-normal'
|
||||
onClick: () => {
|
||||
latestDropItem.value = rowData
|
||||
showMoveModal.value = true
|
||||
}
|
||||
},
|
||||
{
|
||||
default: rowData.comment ?? 'Причина наблюдения не указана'
|
||||
default: h(TbEye)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const fillableColumn = {
|
||||
title: '',
|
||||
key: 'fillable',
|
||||
width: '20',
|
||||
render: (row) => h(
|
||||
NBadge,
|
||||
{
|
||||
dot: true,
|
||||
color: (row.comment && row.comment.trim()) ? '#7fe7c4' : '#e88080'
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (props.status === 'observation') {
|
||||
newColumns.push(expandColumn)
|
||||
newColumns.push(fillableColumn)
|
||||
}
|
||||
|
||||
if (props.isDraggable) newColumns.push(dragColumn)
|
||||
|
||||
82
resources/js/Pages/Report/Components/SelectUserModal.vue
Normal file
82
resources/js/Pages/Report/Components/SelectUserModal.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<script setup>
|
||||
import { NSelect, NModal, NForm, NFormItem, NButton } from 'naive-ui'
|
||||
import {useReportStore} from "../../../Stores/report.js";
|
||||
import {computed, onMounted, ref} from "vue";
|
||||
import {router} from "@inertiajs/vue3";
|
||||
const show = defineModel('show')
|
||||
const reportStore = useReportStore()
|
||||
const formRef = ref()
|
||||
|
||||
const users = computed(() => reportStore.departmentUsers.map(itm => ({
|
||||
label: `${itm.FAM_V} ${itm.IM_V} ${itm.OT_V}`,
|
||||
value: itm.LPUDoctorID
|
||||
})))
|
||||
|
||||
const fetchUsers = () => {
|
||||
axios.get('/api/mis/department-users')
|
||||
.then((res) => {
|
||||
reportStore.departmentUsers = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const rules = {
|
||||
userId: {
|
||||
required: true,
|
||||
validator: (rule, value) => {
|
||||
if (Number.isInteger(value)) return true
|
||||
|
||||
return false
|
||||
},
|
||||
trigger: ['change', 'blur'],
|
||||
message: 'Выберите ответственного'
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
reportStore.reportInfo.userId = null
|
||||
fetchUsers()
|
||||
})
|
||||
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
formRef.value?.validate((errors) => {
|
||||
if (!errors) {
|
||||
router.visit(`/report?userId=${reportStore.reportInfo.userId}`)
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const onAfterLeave = () => {
|
||||
reportStore.reportInfo.userId = null
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NModal v-model:show="show"
|
||||
preset="card"
|
||||
class="max-w-[420px]"
|
||||
:mask-closable="false"
|
||||
@before-leave="onAfterLeave"
|
||||
>
|
||||
<NForm id="select-user-form" ref="formRef" :model="reportStore.reportInfo" :rules="rules">
|
||||
<NFormItem label="Выберите ответственного" path="userId">
|
||||
<NSelect :options="users" v-model:value="reportStore.reportInfo.userId" />
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<template #action>
|
||||
<NButton form-id="select-user-form"
|
||||
type="primary"
|
||||
block
|
||||
@click="onSubmit">
|
||||
Перейти к заполнению сводной
|
||||
</NButton>
|
||||
</template>
|
||||
</NModal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -8,10 +8,18 @@ import {useAuthStore} from "../../Stores/auth.js";
|
||||
const reportStore = useReportStore()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
onMounted(async () => {
|
||||
await reportStore.getReportInfo()
|
||||
onMounted(() => {
|
||||
const queryString = window.location.search
|
||||
const params = new URLSearchParams(queryString)
|
||||
const userId = params.get('userId')
|
||||
|
||||
reportStore.reportInfo.userId = userId
|
||||
|
||||
reportStore.getReportInfo()
|
||||
})
|
||||
|
||||
// reportStore.getReportInfo()
|
||||
|
||||
const mode = computed(() => {
|
||||
if (authStore.isHeadOfDepartment)
|
||||
return 'readonly'
|
||||
|
||||
@@ -23,7 +23,9 @@ export const useReportStore = defineStore('reportStore', () => {
|
||||
|
||||
const dataOnReport = ref(null)
|
||||
|
||||
const reportInfo = ref(null)
|
||||
const reportInfo = ref({
|
||||
userId: null
|
||||
})
|
||||
const isLoadReportInfo = ref(false)
|
||||
|
||||
const patientColumns = [
|
||||
@@ -60,6 +62,9 @@ export const useReportStore = defineStore('reportStore', () => {
|
||||
|
||||
const reportForm = ref({})
|
||||
|
||||
// Пользователи которые находятся в том же отделении что и авторизованный пользователь
|
||||
const departmentUsers = ref([])
|
||||
|
||||
// Нежелательные события
|
||||
const unwantedEvents = ref([])
|
||||
|
||||
@@ -79,6 +84,7 @@ export const useReportStore = defineStore('reportStore', () => {
|
||||
observationPatients: patientsData.value['observation'],
|
||||
unwantedEvents: unwantedEvents.value,
|
||||
dates: timestampCurrentRange.value,
|
||||
userId: reportInfo.value.userId,
|
||||
...assignForm
|
||||
}
|
||||
|
||||
@@ -102,13 +108,25 @@ export const useReportStore = defineStore('reportStore', () => {
|
||||
|
||||
const getReportInfo = async () => {
|
||||
isLoadReportInfo.value = true
|
||||
await axios.get('/api/report')
|
||||
const queryParams = {
|
||||
userId: reportInfo.value.userId
|
||||
}
|
||||
await axios.get(`/api/report`, {
|
||||
params: queryParams
|
||||
})
|
||||
.then((res) => {
|
||||
reportInfo.value = res.data
|
||||
reportInfo.value = {
|
||||
...reportInfo.value,
|
||||
...res.data
|
||||
}
|
||||
|
||||
reportForm.value.metrika_item_3 = reportInfo.value.department?.recipientCount
|
||||
reportForm.value.metrika_item_7 = reportInfo.value.department?.extractCount
|
||||
reportForm.value.metrika_item_8 = reportInfo.value.department?.currentCount
|
||||
reportForm.value.metrika_item_8 = reportInfo.value.department?.currentCounts
|
||||
|
||||
reportForm.value.metrika_item_9 = reportInfo.value.department?.deadCount
|
||||
reportForm.value.metrika_item_10 = reportInfo.value.department?.surgicalCount[1]
|
||||
reportForm.value.metrika_item_11 = reportInfo.value.department?.surgicalCount[0]
|
||||
|
||||
unwantedEvents.value = reportInfo.value.report.unwantedEvents
|
||||
|
||||
@@ -125,9 +143,19 @@ export const useReportStore = defineStore('reportStore', () => {
|
||||
const getDataOnReportDate = async (dateRange) => {
|
||||
isLoadReportInfo.value = true
|
||||
timestampCurrentRange.value = dateRange
|
||||
await axios.get(`/api/report?startAt=${timestampCurrentRange.value[0]}&endAt=${timestampCurrentRange.value[1]}`)
|
||||
const queryParams = {
|
||||
userId: reportInfo.value.userId,
|
||||
startAt: timestampCurrentRange.value[0],
|
||||
endAt: timestampCurrentRange.value[1],
|
||||
}
|
||||
await axios.get(`/api/report`, {
|
||||
params: queryParams
|
||||
})
|
||||
.then((res) => {
|
||||
reportInfo.value = res.data
|
||||
reportInfo.value = {
|
||||
...reportInfo.value,
|
||||
...res.data
|
||||
}
|
||||
|
||||
reportForm.value.metrika_item_3 = reportInfo.value.department?.recipientCount
|
||||
reportForm.value.metrika_item_7 = reportInfo.value.department?.extractCount
|
||||
@@ -155,6 +183,7 @@ export const useReportStore = defineStore('reportStore', () => {
|
||||
patientsData,
|
||||
reportInfo,
|
||||
reportForm,
|
||||
departmentUsers,
|
||||
unwantedEvents,
|
||||
|
||||
getColumnsByKey,
|
||||
|
||||
Reference in New Issue
Block a user