modified: .gitignore
This commit is contained in:
191
resources/js/Pages/Report/Components/ManualPatientModal.vue
Normal file
191
resources/js/Pages/Report/Components/ManualPatientModal.vue
Normal file
@@ -0,0 +1,191 @@
|
||||
<script setup>
|
||||
import {computed, reactive, ref, watch} from "vue";
|
||||
import {NButton, NDatePicker, NForm, NFormItem, NInput, NModal, NSelect} from "naive-ui";
|
||||
import {useReportStore} from "../../../Stores/report.js";
|
||||
import {useDebounceFn} from "@vueuse/core";
|
||||
|
||||
const props = defineProps({
|
||||
patientKind: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const show = defineModel('show', {type: Boolean, default: false})
|
||||
const reportStore = useReportStore()
|
||||
const formRef = ref(null)
|
||||
const submitting = ref(false)
|
||||
const mkbLoading = ref(false)
|
||||
const mkbOptions = ref([])
|
||||
const getDefaultAdmittedAt = () => reportStore.reportInfo?.dates?.endAt ?? Date.now()
|
||||
|
||||
const form = reactive({
|
||||
full_name: '',
|
||||
birth_date: null,
|
||||
admitted_at: getDefaultAdmittedAt(),
|
||||
diagnosis_code: '',
|
||||
diagnosis_name: '',
|
||||
})
|
||||
|
||||
const rules = {
|
||||
full_name: {
|
||||
required: true,
|
||||
message: 'Укажите ФИО',
|
||||
trigger: ['blur', 'input'],
|
||||
},
|
||||
birth_date: {
|
||||
required: true,
|
||||
type: 'number',
|
||||
message: 'Укажите дату рождения',
|
||||
trigger: ['change', 'blur'],
|
||||
validator: (_rule, value) => {
|
||||
if (!value) return false
|
||||
return value <= Date.now()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const title = computed(() => props.patientKind === 'plan'
|
||||
? 'Добавить планового пациента спецконтингента'
|
||||
: 'Добавить экстренного пациента спецконтингента')
|
||||
|
||||
const resetForm = () => {
|
||||
form.full_name = ''
|
||||
form.birth_date = null
|
||||
form.admitted_at = getDefaultAdmittedAt()
|
||||
form.diagnosis_code = ''
|
||||
form.diagnosis_name = ''
|
||||
mkbOptions.value = []
|
||||
}
|
||||
|
||||
const normalizeSpaces = (value) => value.replace(/\s+/g, ' ').trim()
|
||||
const pad = (value) => String(value).padStart(2, '0')
|
||||
const formatLocalDate = (timestamp) => {
|
||||
const date = new Date(timestamp)
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`
|
||||
}
|
||||
const formatLocalDateTime = (timestamp) => {
|
||||
const date = new Date(timestamp)
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
|
||||
}
|
||||
|
||||
const isSubmitDisabled = computed(() => submitting.value)
|
||||
|
||||
const handleClose = () => {
|
||||
resetForm()
|
||||
show.value = false
|
||||
}
|
||||
|
||||
watch(() => show.value, (value) => {
|
||||
if (value) {
|
||||
form.admitted_at = getDefaultAdmittedAt()
|
||||
}
|
||||
})
|
||||
|
||||
const loadMkbOptions = useDebounceFn(async (query) => {
|
||||
if (!query || query.trim().length < 2) {
|
||||
mkbOptions.value = []
|
||||
return
|
||||
}
|
||||
|
||||
mkbLoading.value = true
|
||||
try {
|
||||
const items = await reportStore.searchMkb(query.trim())
|
||||
mkbOptions.value = (items ?? []).map((item) => ({
|
||||
label: item.label,
|
||||
value: item.code,
|
||||
name: item.name,
|
||||
}))
|
||||
} finally {
|
||||
mkbLoading.value = false
|
||||
}
|
||||
}, 300)
|
||||
|
||||
const handleMkbSearch = async (query) => {
|
||||
await loadMkbOptions(query)
|
||||
}
|
||||
|
||||
const handleMkbChange = (value, option) => {
|
||||
if (value === null || value === undefined || value === '') {
|
||||
form.diagnosis_code = ''
|
||||
form.diagnosis_name = ''
|
||||
return
|
||||
}
|
||||
|
||||
const selected = (!Array.isArray(option) && option)
|
||||
? option
|
||||
: mkbOptions.value.find((item) => item.value === value)
|
||||
|
||||
form.diagnosis_code = selected?.value ?? value ?? ''
|
||||
form.diagnosis_name = selected?.name ?? ''
|
||||
}
|
||||
|
||||
const submit = async () => {
|
||||
if (submitting.value) return
|
||||
|
||||
try {
|
||||
await formRef.value?.validate()
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
submitting.value = true
|
||||
|
||||
try {
|
||||
await reportStore.createManualPatient({
|
||||
departmentId: reportStore.reportInfo.department.department_id,
|
||||
full_name: normalizeSpaces(form.full_name),
|
||||
birth_date: formatLocalDate(form.birth_date),
|
||||
patient_kind: props.patientKind,
|
||||
admitted_at: form.admitted_at ? formatLocalDateTime(form.admitted_at) : null,
|
||||
diagnosis_code: form.diagnosis_code ? normalizeSpaces(form.diagnosis_code).toUpperCase() : null,
|
||||
diagnosis_name: form.diagnosis_name ? normalizeSpaces(form.diagnosis_name) : null,
|
||||
})
|
||||
|
||||
resetForm()
|
||||
show.value = false
|
||||
window.$message.success('Пациент добавлен')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NModal v-model:show="show" preset="card" :title="title" class="max-w-xl" @after-leave="resetForm">
|
||||
<NForm ref="formRef" :model="form" :rules="rules" label-placement="top">
|
||||
<NFormItem label="ФИО" path="full_name">
|
||||
<NInput v-model:value="form.full_name" />
|
||||
</NFormItem>
|
||||
<NFormItem label="Дата рождения" path="birth_date">
|
||||
<NDatePicker v-model:value="form.birth_date" type="date" class="w-full" />
|
||||
</NFormItem>
|
||||
<NFormItem label="Дата и время поступления">
|
||||
<NDatePicker v-model:value="form.admitted_at" type="datetime" class="w-full" />
|
||||
</NFormItem>
|
||||
<NFormItem label="Диагноз (МКБ)">
|
||||
<NSelect
|
||||
v-model:value="form.diagnosis_code"
|
||||
class="w-full"
|
||||
filterable
|
||||
clearable
|
||||
remote
|
||||
:options="mkbOptions"
|
||||
:loading="mkbLoading"
|
||||
placeholder="Начните ввод кода или названия диагноза"
|
||||
@search="handleMkbSearch"
|
||||
@update:value="handleMkbChange"
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex justify-end gap-2">
|
||||
<NButton @click="handleClose">Отмена</NButton>
|
||||
<NButton type="primary" :loading="submitting" :disabled="isSubmitDisabled" @click="submit">
|
||||
Сохранить
|
||||
</NButton>
|
||||
</div>
|
||||
</template>
|
||||
</NModal>
|
||||
</template>
|
||||
Reference in New Issue
Block a user