Files
onboard/resources/js/Stores/report.js
brusnitsyn 719eb1403f * добавил исход спец контингенту
* оптимизация обновления при редактировании спец контингента
* добавил поддержку заключительных диагнозов
* изменил определение законченной операции
* добавил поддержку исхода операции
* добавил определение отмены для операции через назначение
* работа над диапазонами календарей, подсчет статистики
* добавил статусы отчетов и подкорректировал привязку спец контингента к отчету
* добавил новые сервисы для будущего кеширования
* частичное разделение логики подсчета пациентов
2026-04-22 20:35:39 +09:00

446 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { defineStore } from "pinia";
import { useTimestamp } from "@vueuse/core";
import { computed, ref } from "vue";
import { router } from "@inertiajs/vue3";
const patientStatuses = [
'mis-plan',
'mis-emergency',
'mis-observation',
'mis-reanimation',
'mis-outcome-discharged',
'mis-outcome-deceased',
'mis-outcome-transferred',
'special-plan',
'special-emergency',
'special-observation',
'special-outcome-discharged',
'special-outcome-deceased',
'special-outcome-transferred',
]
const createEmptyPatients = () => Object.fromEntries(patientStatuses.map((status) => [status, []]))
const createStatusCounts = () => {
const extended = {
'mis-outcome': 0,
'special-outcome': 0,
}
return {
...Object.fromEntries(patientStatuses.map((status) => [status, 0])),
...extended,
}
}
const createStatusStates = () => Object.fromEntries(patientStatuses.map((status) => [status, {
page: 1,
perPage: status.includes('observation') ? 1000 : 20,
total: 0,
search: '',
loading: false,
loaded: false,
}]))
export const useReportStore = defineStore('reportStore', () => {
const timestampNow = useTimestamp()
const reportFormRef = ref(null)
const _timestampCurrent = ref(null)
const timestampCurrent = computed({
get: () => _timestampCurrent.value === null ? timestampNow.value : _timestampCurrent.value,
set: (value) => {
_timestampCurrent.value = value
}
})
const timestampCurrentRange = ref([null, null])
const dataOnReport = ref(null)
const openedCollapsible = ref([])
const reportInfo = ref({ userId: null })
const isLoadReportInfo = ref(false)
const isDragActive = ref(false)
const patientsData = ref(createEmptyPatients())
const statusCounts = ref(createStatusCounts())
const statusStates = ref(createStatusStates())
const countsLoading = ref(false)
const reportForm = ref({})
const departmentUsers = ref([])
const unwantedEvents = ref([])
const patientColumns = [
{ title: '№', width: '80', key: 'num' },
{ title: 'ФИО', width: '320', key: 'fullname' },
{ title: 'Возраст', key: 'age' },
{ title: 'Д/р', key: 'birth_date' },
{ title: 'Д/п', key: 'admitted_at' },
{ title: 'Диагноз', key: 'mkb.ds' }
]
const addRowNumbers = (data, page = 1, perPage = 15) => {
if (!Array.isArray(data)) return data
const startFrom = ((page - 1) * perPage) + 1
return data.map((item, index) => ({
...item,
num: startFrom + index
}))
}
const applyMetricsFromDepartment = (department) => {
reportForm.value.metrika_item_3 = department?.recipientCount ?? 0
reportForm.value.metrika_item_7 = department?.extractCount ?? 0
reportForm.value.metrika_item_8 = department?.currentCount ?? 0
reportForm.value.metrika_item_9 = department?.deadCount ?? 0
reportForm.value.metrika_item_10 = department?.surgicalCount?.[0] ?? 0
reportForm.value.metrika_item_11 = department?.surgicalCount?.[1] ?? 0
reportForm.value.metrika_item_17 = department?.countStaff ?? 0
}
const initializeFromPage = (pageProps) => {
reportInfo.value = {
...reportInfo.value,
...pageProps,
}
unwantedEvents.value = [...(pageProps.report?.unwantedEvents ?? [])]
patientsData.value = createEmptyPatients()
statusCounts.value = createStatusCounts()
statusStates.value = createStatusStates()
openedCollapsible.value = []
if (pageProps.report?.isHeadOrAdmin) {
timestampCurrentRange.value = [pageProps.dates.startAt, pageProps.dates.endAt]
} else {
timestampCurrentRange.value = [pageProps.dates.endAt, pageProps.dates.endAt]
}
applyMetricsFromDepartment(pageProps.department)
}
const getColumnsByKey = (keys) => keys.map((key) => patientColumns.find(item => item.key === key))
const getStatusState = (status) => statusStates.value[status]
const getPatientsCount = (status) => {
if (Object.prototype.hasOwnProperty.call(statusCounts.value, status)) {
return statusCounts.value[status]
}
return patientsData.value[status]?.length ?? 0
}
const getObservationPatientsForSubmit = () => ([
...(patientsData.value['mis-observation'] ?? []),
...(patientsData.value['special-observation'] ?? []),
])
const findPatientById = (patientId) => {
for (const status of patientStatuses) {
const patient = patientsData.value[status]?.find((item) => item.id === patientId)
if (patient) {
return patient
}
}
return null
}
const removeObservationPatientLocally = (patientId) => {
for (const status of ['mis-observation', 'special-observation']) {
const index = patientsData.value[status]?.findIndex((item) => item.id === patientId) ?? -1
if (index !== -1) {
patientsData.value[status].splice(index, 1)
const state = getStatusState(status)
if (state && state.total > 0) state.total -= 1
return
}
}
}
const loadPatientsByStatus = async (status, { resetPage = false } = {}) => {
const state = getStatusState(status)
if (!state) return
if (state.loading) return
if (resetPage) {
state.page = 1
}
state.loading = true
try {
const response = await axios.post('/api/mis/patients', {
status,
departmentId: reportInfo.value?.department?.department_id,
startAt: reportInfo.value?.dates?.startAt,
endAt: reportInfo.value?.dates?.endAt,
page: state.page,
perPage: state.perPage,
search: state.search || undefined,
})
patientsData.value[status] = addRowNumbers(
response.data?.data ?? [],
state.page,
state.perPage
)
state.total = response.data?.meta?.total ?? patientsData.value[status].length
statusCounts.value[status] = state.total
state.loaded = true
} finally {
state.loading = false
}
}
const loadStatusCount = async (status) => {
if (!Object.prototype.hasOwnProperty.call(statusCounts.value, status)) return
const response = await axios.post('/api/mis/patients/count', {
status,
departmentId: reportInfo.value?.department?.department_id,
startAt: reportInfo.value?.dates?.startAt,
endAt: reportInfo.value?.dates?.endAt,
})
statusCounts.value[status] = Number(response.data ?? 0)
}
const loadAllStatusCounts = async (force = false) => {
countsLoading.value = true
try {
const response = await axios.post('/api/mis/patients/counts', {
departmentId: reportInfo.value?.department?.department_id,
startAt: reportInfo.value?.dates?.startAt,
endAt: reportInfo.value?.dates?.endAt,
force,
})
const counts = response.data?.counts ?? {}
statusCounts.value = {
...createStatusCounts(),
...counts,
}
} finally {
countsLoading.value = false
}
}
const ensureStatusLoaded = async (status) => {
const state = getStatusState(status)
if (!state || state.loaded) return
await loadPatientsByStatus(status)
}
const setStatusSearch = async (status, search) => {
const state = getStatusState(status)
if (!state) return
state.search = search
await loadPatientsByStatus(status, { resetPage: true })
}
const setStatusPage = async (status, page) => {
const state = getStatusState(status)
if (!state) return
state.page = page
await loadPatientsByStatus(status)
}
const reloadReportPage = () => new Promise((resolve) => {
isLoadReportInfo.value = true
router.reload({
preserveScroll: true,
onSuccess: (page) => {
initializeFromPage(page.props)
},
onFinish: () => {
isLoadReportInfo.value = false
resolve()
},
})
})
const getSpecialStatusByPatient = (patient) => {
if (!patient) return null
if (patient.is_current) {
return patient.patient_kind ? `special-${patient.patient_kind}` : null
}
if (!patient.outcome_type) return null
return `special-outcome-${patient.outcome_type}`
}
const getDataOnReportDate = async () => {
await reloadReportPage()
}
const sendReportForm = (assignForm = null) => {
const form = {
metrics: reportForm.value,
observationPatients: getObservationPatientsForSubmit(),
unwantedEvents: unwantedEvents.value,
dates: [
timestampCurrentRange.value[0],
timestampCurrentRange.value[1]
],
userId: reportInfo.value.report.userId,
departmentId: reportInfo.value.department.department_id,
reportId: reportInfo.value.report.report_id,
status: reportInfo.value?.report?.status ?? 'draft',
...assignForm
}
router.post('/report', form, {
onSuccess: () => {
window.$message.success(form.status === 'submitted' ? 'Отчет опубликован' : 'Черновик сохранен')
}
})
}
const createManualPatient = async (payload) => {
const response = await axios.post('/api/report/manual-patients', payload)
const reportId = response.data?.report_id
if (reportId) {
reportInfo.value = {
...reportInfo.value,
report: {
...(reportInfo.value?.report ?? {}),
report_id: reportId,
}
}
}
const status = `special-${payload.patient_kind}`
await Promise.all([
loadPatientsByStatus(status, { resetPage: true }),
loadAllStatusCounts(true),
])
}
const setManualPatientOutcome = async (departmentPatientId, payload) => {
const response = await axios.post(`/api/report/manual-patients/${departmentPatientId}/outcome`, payload)
const targetStatus = getSpecialStatusByPatient(response.data)
await Promise.all([
...(targetStatus ? [loadPatientsByStatus(targetStatus, { resetPage: true })] : []),
loadAllStatusCounts(true),
])
}
const updateManualPatient = async (departmentPatientId, payload, options = {}) => {
await axios.patch(`/api/report/manual-patients/${departmentPatientId}`, {
...payload,
startAt: reportInfo.value?.dates?.startAt,
endAt: reportInfo.value?.dates?.endAt,
})
const reloadStatuses = Array.from(new Set((options.reloadStatuses ?? []).filter(Boolean)))
await Promise.all([
...reloadStatuses.map((status) => loadPatientsByStatus(status, { resetPage: true })),
loadAllStatusCounts(true),
])
}
const searchMisPatients = async (departmentId, query) => {
const response = await axios.get('/api/mis/patients/search', {
params: { departmentId, query }
})
return response.data
}
const searchMkb = async (query) => {
const response = await axios.get('/api/mis/mkb/search', {
params: { query }
})
return response.data
}
const searchMedicalServices = async (query) => {
const response = await axios.get('/api/mis/services/search', {
params: { query }
})
return response.data
}
const linkManualPatient = async (departmentPatientId, medicalHistoryId) => {
await axios.post(`/api/report/manual-patients/${departmentPatientId}/link`, {
medical_history_id: medicalHistoryId
})
await reloadReportPage()
}
const getManualPatientOperations = async (departmentPatientId) => {
const response = await axios.get(`/api/report/manual-patients/${departmentPatientId}/operations`)
return response.data ?? []
}
const createManualPatientOperation = async (departmentPatientId, payload) => {
const response = await axios.post(`/api/report/manual-patients/${departmentPatientId}/operations`, payload)
return response.data
}
const updateManualPatientOperation = async (departmentPatientId, operationId, payload) => {
const response = await axios.patch(`/api/report/manual-patients/${departmentPatientId}/operations/${operationId}`, payload)
return response.data
}
const deleteManualPatientOperation = async (departmentPatientId, operationId) => {
await axios.delete(`/api/report/manual-patients/${departmentPatientId}/operations/${operationId}`)
}
return {
reportFormRef,
timestampNow,
timestampCurrent,
timestampCurrentRange,
dataOnReport,
isLoadReportInfo,
patientColumns,
patientsData,
statusCounts,
statusStates,
countsLoading,
reportInfo,
reportForm,
departmentUsers,
unwantedEvents,
openedCollapsible,
isDragActive,
initializeFromPage,
getColumnsByKey,
getPatientsCount,
getStatusState,
getObservationPatientsForSubmit,
findPatientById,
removeObservationPatientLocally,
loadPatientsByStatus,
loadStatusCount,
loadAllStatusCounts,
ensureStatusLoaded,
setStatusSearch,
setStatusPage,
reloadReportPage,
getDataOnReportDate,
createManualPatient,
setManualPatientOutcome,
updateManualPatient,
searchMisPatients,
searchMkb,
searchMedicalServices,
linkManualPatient,
getManualPatientOperations,
createManualPatientOperation,
updateManualPatientOperation,
deleteManualPatientOperation,
sendReportForm,
addRowNumbers,
}
})