Профиль хирургии

This commit is contained in:
brusnitsyn
2026-03-25 17:37:32 +09:00
parent 52a80ccd3b
commit f566ab96df
75 changed files with 3841 additions and 1009 deletions

View File

@@ -3,7 +3,7 @@
</script>
<template>
<div class="max-w-6xl mx-auto mt-6 mb-4 w-full">
<div class="max-w-6xl mx-auto mt-6 mb-4 w-full flex flex-col gap-y-4">
<slot />
</div>
</template>

View File

@@ -18,6 +18,10 @@ const props = defineProps({
type: [String, Number],
default: null
},
noPadding: {
type: Boolean,
default: false
}
})
const hasHeader = computed(() => props.header.trim().length > 0)
@@ -52,7 +56,7 @@ watch(() => [props.minH, props.maxH], ([minH, maxH]) => {
<template>
<NFormItem :show-label="hasHeader" :label="header" :show-feedback="hasFeedback" :feedback="feedback">
<NCard>
<NCard :class="noPadding ? 'no-padding h-full' : ''">
<NScrollbar :style="styles">
<slot />
</NScrollbar>
@@ -61,5 +65,7 @@ watch(() => [props.minH, props.maxH], ([minH, maxH]) => {
</template>
<style scoped>
.no-padding :deep(.n-card__content) {
padding: 0 !important;
}
</style>

View File

@@ -1,10 +1,11 @@
<script setup>
import {NDatePicker, NIcon, } from 'naive-ui'
import {NDatePicker, NIcon, NFlex, NButton, NSkeleton} from 'naive-ui'
import {computed, onMounted, ref, watch} from "vue";
import {router} from "@inertiajs/vue3";
import {TbCalendar} from 'vue-icons-plus/tb'
import {formatRussianDate, formatRussianDateRange} from "../Utils/dateFormatter.js";
import {useReportStore} from "../Stores/report.js";
import {formatDistanceStrict, getTime} from "date-fns";
const props = defineProps({
// Пользователь с ролью админ или зав
@@ -17,21 +18,47 @@ const props = defineProps({
},
isOneDay: {
type: Boolean
},
isShowCurrentDateSwitch: {
type: Boolean,
default: false
}
})
const reportStore = useReportStore()
const isLoading = ref(false)
const isUseDateRange = computed(() => props.isHeadOrAdmin)
const datePicker = ref()
const showCalendar = ref(false)
const calendarType = ref(props.isHeadOrAdmin ? 'daterange' : 'date')
const dateType = computed(() => {
if (isUseDateRange.value) return 'daterange'
return 'date'
})
const isDateRange = computed(() => calendarType.value === 'daterange')
const isDateIsOneDay = computed(() => {
return formatDistanceStrict(modelValue.value[0], modelValue.value[1]) === '0 seconds' || formatDistanceStrict(modelValue.value[0], modelValue.value[1]) === '1 day'
})
const queryDate = ref([null, null])
const modelValue = defineModel('date')
const onChangeDate = () => {
if (isDateIsOneDay.value) {
const startDate = Date.parse(new Date(new Date().getFullYear(), 0, 1).toDateString())
const date = Date.parse(new Date().toDateString())
const arrayDate = [startDate, date]
handleDateUpdate(arrayDate)
} else {
const date = Date.parse(new Date().toDateString())
const arrayDate = [date, date]
handleDateUpdate(arrayDate)
}
showCalendar.value = false
}
const setQueryDate = () => {
reportStore.openedCollapsible = []
router.reload({
@@ -39,6 +66,9 @@ const setQueryDate = () => {
startAt: queryDate.value[0],
endAt: queryDate.value[1]
},
onFinish: () => {
isLoading.value = false
}
})
}
@@ -80,11 +110,12 @@ const formattedValue = computed(() => {
})
const handleDateUpdate = (value) => {
isLoading.value = true
// Устанавливаем новое значение
modelValue.value = value
// Для диапазона: отправляем только если обе даты заполнены
if (isUseDateRange.value) {
if (isDateRange.value) {
if (Array.isArray(value) && value[0] && value[1]) {
// Дебаунс для предотвращения двойной отправки
setTimeout(() => {
@@ -107,24 +138,40 @@ const handleDateUpdate = (value) => {
<template>
<div class="relative inline-flex items-center">
<div v-if="formattedValue" class="font-medium leading-3 cursor-pointer" @click="showCalendar = true">
{{ formattedValue }}
</div>
<template v-if="isLoading">
<NSkeleton width="240" height="20" round />
</template>
<template v-else>
<div v-if="formattedValue" class="font-medium leading-3 cursor-pointer" @click="showCalendar = true">
{{ formattedValue }}
</div>
<NDatePicker v-model:value="modelValue"
v-model:show="showCalendar"
ref="datePicker"
class="opacity-0 absolute! inset-x-0 bottom-full -translate-y-1/2"
placement="top-start"
input-readonly
bind-calendar-months
@update:value="value => handleDateUpdate(value)"
:type="dateType" />
<div class="cursor-pointer p-2 flex items-center justify-center" @click="showCalendar = true">
<NIcon size="20">
<TbCalendar />
</NIcon>
</div>
<NDatePicker v-model:value="modelValue"
v-model:show="showCalendar"
ref="datePicker"
class="opacity-0 absolute! inset-x-0 bottom-full -translate-y-1/2"
placement="top-start"
input-readonly
bind-calendar-months
@update:value="value => handleDateUpdate(value)"
:type="calendarType">
<template #confirm="{onConfirm, disabled, text}">
<NFlex justify="end" align="center" :size="0">
<NButton v-if="isShowCurrentDateSwitch" secondary type="primary" size="tiny" @click="onChangeDate()">
{{ isDateIsOneDay ? 'Текущий год' : 'Сегодня' }}
</NButton>
<NButton type="success" size="tiny" @click="onConfirm" :disabled="disabled">
{{ text }}
</NButton>
</NFlex>
</template>
</NDatePicker>
<div class="cursor-pointer p-2 flex items-center justify-center" @click="showCalendar = true">
<NIcon size="20">
<TbCalendar />
</NIcon>
</div>
</template>
</div>
</template>