modified: .gitignore
This commit is contained in:
@@ -1,12 +1,31 @@
|
||||
<script setup>
|
||||
import {NIcon, NText, NDataTable, NButton, NBadge, NTabs, NTabPane, NPopover, NEllipsis, NTooltip} from "naive-ui";
|
||||
import {
|
||||
NIcon,
|
||||
NText,
|
||||
NDataTable,
|
||||
NButton,
|
||||
NBadge,
|
||||
NTabs,
|
||||
NTabPane,
|
||||
NPopover,
|
||||
NEllipsis,
|
||||
NTooltip,
|
||||
NFlex,
|
||||
NInput,
|
||||
NPagination,
|
||||
NSpin,
|
||||
} from "naive-ui";
|
||||
import {useReportStore} from "../../../Stores/report.js";
|
||||
import {computed, h, onMounted, ref, watch} from "vue";
|
||||
import { VueDraggableNext } from 'vue-draggable-next'
|
||||
import {computed, h, ref, watch} from "vue";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {TbGripVertical, TbEye, TbExternalLink} from "vue-icons-plus/tb";
|
||||
import {TbEye, TbExternalLink, TbPencil} from "vue-icons-plus/tb";
|
||||
import MoveModalComment from "./MoveModalComment.vue";
|
||||
import OperationInfoModal from "./OperationInfoModal.vue";
|
||||
import ManualPatientOutcomeModal from "./ManualPatientOutcomeModal.vue";
|
||||
import ManualPatientLinkModal from "./ManualPatientLinkModal.vue";
|
||||
import ManualPatientEditModal from "./ManualPatientEditModal.vue";
|
||||
import ManualPatientOperationsModal from "./ManualPatientOperationsModal.vue";
|
||||
import {useDebounceFn} from "@vueuse/core";
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
@@ -19,7 +38,7 @@ const props = defineProps({
|
||||
},
|
||||
keys: {
|
||||
type: Array,
|
||||
default: ['num', 'fullname', 'age', 'birth_date']
|
||||
default: ['num', 'fullname', 'age', 'birth_date', 'admitted_at']
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
@@ -41,34 +60,54 @@ const props = defineProps({
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
enabled: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
})
|
||||
|
||||
const isFillableMode = computed(() => props.mode.toLowerCase() === 'fillable')
|
||||
const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
|
||||
const baseStatus = computed(() => props.status.replace(/^(mis|special)-/, ''))
|
||||
const isSpecialStatus = computed(() => props.status.startsWith('special-'))
|
||||
|
||||
const tableRef = ref()
|
||||
|
||||
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)
|
||||
const {patientsData, statusStates} = storeToRefs(reportStore)
|
||||
const showMoveModal = ref(false)
|
||||
const showOperationInfoModal = ref(false)
|
||||
const showManualOutcomeModal = ref(false)
|
||||
const showManualLinkModal = ref(false)
|
||||
const showManualEditModal = ref(false)
|
||||
const showManualOperationsModal = ref(false)
|
||||
const currentHistory = ref(null)
|
||||
const latestDropItem = ref(null)
|
||||
const activePatient = ref(null)
|
||||
|
||||
const hasDisabledEdit = computed(() => {
|
||||
return reportStore.reportInfo.report.isActiveSendButton === false
|
||||
return !Boolean(reportStore.reportInfo?.report?.isActiveSendButton)
|
||||
})
|
||||
const canEditSpecial = computed(() => isSpecialStatus.value && !hasDisabledEdit.value)
|
||||
const statusState = computed(() => statusStates.value[props.status] ?? {
|
||||
page: 1,
|
||||
perPage: 20,
|
||||
total: 0,
|
||||
search: '',
|
||||
loading: false,
|
||||
loaded: false,
|
||||
})
|
||||
const searchValue = ref('')
|
||||
const isObservationStatus = computed(() => baseStatus.value === 'observation')
|
||||
const showPagination = computed(() => !isObservationStatus.value)
|
||||
|
||||
// Добавляем drag колонку если режим fillable
|
||||
const columns = computed(() => {
|
||||
// if (!isFillableMode.value) return baseColumns
|
||||
const resolvedBaseColumns = reportStore.getColumnsByKey(props.keys)
|
||||
.filter(Boolean)
|
||||
.map((column) => ({ ...column }))
|
||||
|
||||
const newColumns = []
|
||||
|
||||
@@ -76,28 +115,86 @@ const columns = computed(() => {
|
||||
title: '',
|
||||
key: 'goToMis',
|
||||
width: 40,
|
||||
render: (row) => h(
|
||||
NTooltip,
|
||||
{},
|
||||
{
|
||||
trigger: () => h('div',
|
||||
{
|
||||
style: {
|
||||
cursor: 'hand',
|
||||
textAlign: 'center',
|
||||
userSelect: 'none'
|
||||
},
|
||||
onClick: () => {
|
||||
window.open(`https://stationar.amurzdrav.ru/prod/statist/edit/card/${row.id}`, '_blank')
|
||||
render: (row) => {
|
||||
const actions = []
|
||||
|
||||
if (canEditSpecial.value && row?.department_patient_id) {
|
||||
actions.push(
|
||||
h(
|
||||
NTooltip,
|
||||
{},
|
||||
{
|
||||
trigger: () => h(
|
||||
'div',
|
||||
{
|
||||
style: {
|
||||
cursor: 'pointer',
|
||||
textAlign: 'center',
|
||||
userSelect: 'none',
|
||||
color: '#6b7280',
|
||||
display: 'inline-flex',
|
||||
},
|
||||
onClick: () => {
|
||||
activePatient.value = row
|
||||
showManualEditModal.value = true
|
||||
},
|
||||
},
|
||||
[h(NIcon, { depth: 3, size: 16 }, h(TbPencil))]
|
||||
),
|
||||
default: () => 'Редактировать',
|
||||
}
|
||||
},
|
||||
[
|
||||
h(NIcon, { depth: 2 }, h(TbExternalLink))
|
||||
]
|
||||
),
|
||||
default: () => 'Перейти в карту'
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
if (row.medical_history_id) {
|
||||
actions.push(
|
||||
h(
|
||||
NTooltip,
|
||||
{},
|
||||
{
|
||||
trigger: () => h(
|
||||
'div',
|
||||
{
|
||||
style: {
|
||||
cursor: 'pointer',
|
||||
textAlign: 'center',
|
||||
userSelect: 'none',
|
||||
display: 'inline-flex',
|
||||
},
|
||||
onClick: () => {
|
||||
window.open(`https://stationar.amurzdrav.ru/prod/statist/edit/card/${row.medical_history_id}`, '_blank')
|
||||
}
|
||||
},
|
||||
[h(NIcon, { depth: 2 }, h(TbExternalLink))]
|
||||
),
|
||||
default: () => 'Перейти в карту'
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (!actions.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (actions.length === 1) {
|
||||
return actions[0]
|
||||
}
|
||||
|
||||
return h(
|
||||
'div',
|
||||
{
|
||||
style: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
gap: '6px',
|
||||
},
|
||||
},
|
||||
actions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const removeColumn = {
|
||||
@@ -108,17 +205,14 @@ const columns = computed(() => {
|
||||
{
|
||||
text: true,
|
||||
disabled: hasDisabledEdit.value,
|
||||
onClick: () => {
|
||||
axios.post('/api/report/observation/remove', {
|
||||
id: row.id
|
||||
}).then(async () => {
|
||||
const indexRemove = patientsData.value['observation'].findIndex(itm => itm.id === row.id)
|
||||
if (indexRemove !== -1) {
|
||||
patientsData.value['observation'].splice(indexRemove, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
onClick: () => {
|
||||
axios.post('/api/report/observation/remove', {
|
||||
id: row.id
|
||||
}).then(async () => {
|
||||
reportStore.removeObservationPatientLocally(row.id)
|
||||
})
|
||||
}
|
||||
},
|
||||
[
|
||||
'Снять с наблюдения'
|
||||
]
|
||||
@@ -157,13 +251,13 @@ const columns = computed(() => {
|
||||
)
|
||||
}
|
||||
|
||||
if (props.status === 'observation') {
|
||||
if (baseStatus.value === 'observation') {
|
||||
newColumns.push(expandColumn)
|
||||
newColumns.push(fillableColumn)
|
||||
}
|
||||
|
||||
newColumns.push(dragColumn)
|
||||
newColumns.push(...baseColumns)
|
||||
newColumns.push(...resolvedBaseColumns)
|
||||
newColumns.push({
|
||||
title: 'Диагноз',
|
||||
key: 'ds',
|
||||
@@ -196,11 +290,30 @@ const columns = computed(() => {
|
||||
})
|
||||
if (props.isRemovable) newColumns.push(removeColumn)
|
||||
|
||||
if (props.status === 'emergency' || props.status === 'plan') {
|
||||
if (baseStatus.value === 'emergency' || baseStatus.value === 'plan') {
|
||||
const operationColumn = {
|
||||
title: 'Операции',
|
||||
key: 'operations',
|
||||
render: (row) => row.operations?.length ?
|
||||
render: (row) => canEditSpecial.value && row?.department_patient_id
|
||||
? h(
|
||||
'div',
|
||||
{
|
||||
class: 'underline decoration-dashed cursor-pointer',
|
||||
style: 'padding: 8px;',
|
||||
onClick: () => {
|
||||
activePatient.value = row
|
||||
showManualOperationsModal.value = true
|
||||
},
|
||||
},
|
||||
row.operations?.length
|
||||
? h(NEllipsis, {tooltip: false}, row.operations.map(itm => `${itm.code}; `).join(''))
|
||||
: 'Добавить'
|
||||
)
|
||||
: isSpecialStatus.value
|
||||
? (row.operations?.length
|
||||
? h('div', {style: 'padding: 8px;'}, h(NEllipsis, {tooltip: false}, row.operations.map(itm => `${itm.code}; `).join('')))
|
||||
: h('div', {style: 'padding: 8px;'}, '-'))
|
||||
: row.operations?.length ?
|
||||
h(
|
||||
NPopover,
|
||||
{
|
||||
@@ -214,7 +327,7 @@ const columns = computed(() => {
|
||||
class: 'underline decoration-dashed cursor-pointer',
|
||||
style: 'padding: 8px;',
|
||||
onClick: () => {
|
||||
currentHistory.value = row.id
|
||||
currentHistory.value = row.medical_history_id
|
||||
showOperationInfoModal.value = true
|
||||
},
|
||||
},
|
||||
@@ -233,7 +346,7 @@ const columns = computed(() => {
|
||||
newColumns.push(operationColumn)
|
||||
}
|
||||
|
||||
if (props.status === 'outcome') {
|
||||
if (baseStatus.value === 'outcome') {
|
||||
const typeColumn = {
|
||||
title: 'Причина',
|
||||
key: 'outcome_type',
|
||||
@@ -325,21 +438,6 @@ const handleDrop = (e) => {
|
||||
}
|
||||
}
|
||||
|
||||
const fetchPatients = async () => {
|
||||
isLoading.value = true
|
||||
const data = {
|
||||
status: props.status,
|
||||
startAt: reportStore.timestampCurrentRange[0],
|
||||
endAt: reportStore.timestampCurrentRange[1],
|
||||
departmentId: reportStore.reportInfo.department.department_id
|
||||
}
|
||||
await axios.post('/api/mis/patients', data).then((res) => {
|
||||
patientsData.value[props.status] = reportStore.addRowNumbers(res.data)
|
||||
}).finally(() => {
|
||||
isLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function rowProps(row) {
|
||||
const style = []
|
||||
const classes = []
|
||||
@@ -374,29 +472,70 @@ function rowProps(row) {
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await fetchPatients()
|
||||
})
|
||||
const applySearch = useDebounceFn(async () => {
|
||||
await reportStore.setStatusSearch(props.status, searchValue.value)
|
||||
}, 350)
|
||||
|
||||
const handlePageChange = async (page) => {
|
||||
await reportStore.setStatusPage(props.status, page)
|
||||
}
|
||||
|
||||
watch(() => props.enabled, async (enabled) => {
|
||||
if (enabled) {
|
||||
await reportStore.ensureStatusLoaded(props.status)
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
watch(() => reportStore.reportInfo?.dates, async () => {
|
||||
searchValue.value = ''
|
||||
if (props.enabled) {
|
||||
await reportStore.loadPatientsByStatus(props.status, { resetPage: true })
|
||||
}
|
||||
}, { deep: true })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<NDataTable :columns="columns"
|
||||
ref="tableRef"
|
||||
:data="patientsData[status]"
|
||||
size="small"
|
||||
@drop="handleDrop"
|
||||
@dragover="handleDragOver"
|
||||
:loading="isLoading"
|
||||
max-height="200"
|
||||
min-height="200"
|
||||
:row-props="rowProps"
|
||||
:row-key="(row, index) => row.id"
|
||||
class="text-sm!">
|
||||
</NDataTable>
|
||||
<NFlex vertical :size="8">
|
||||
<NInput
|
||||
v-model:value="searchValue"
|
||||
clearable
|
||||
size="small"
|
||||
placeholder="Поиск по ФИО или диагнозу"
|
||||
@update:value="applySearch"
|
||||
/>
|
||||
|
||||
<NSpin :show="statusState.loading">
|
||||
<NDataTable :columns="columns"
|
||||
ref="tableRef"
|
||||
:data="patientsData[status]"
|
||||
size="small"
|
||||
@drop="handleDrop"
|
||||
@dragover="handleDragOver"
|
||||
max-height="200"
|
||||
min-height="200"
|
||||
:row-props="rowProps"
|
||||
:row-key="(row, index) => row.id"
|
||||
class="text-sm!">
|
||||
</NDataTable>
|
||||
</NSpin>
|
||||
|
||||
<NPagination
|
||||
v-if="showPagination"
|
||||
:page="statusState.page"
|
||||
:page-size="statusState.perPage"
|
||||
:item-count="statusState.total"
|
||||
:page-slot="7"
|
||||
@update:page="handlePageChange"
|
||||
/>
|
||||
</NFlex>
|
||||
|
||||
<MoveModalComment v-model:show="showMoveModal" :patient-id="latestDropItem?.id" />
|
||||
<OperationInfoModal v-model:show="showOperationInfoModal" :history-id="currentHistory" />
|
||||
<ManualPatientOutcomeModal v-model:show="showManualOutcomeModal" :patient="activePatient" />
|
||||
<ManualPatientLinkModal v-model:show="showManualLinkModal" :patient="activePatient" />
|
||||
<ManualPatientEditModal v-model:show="showManualEditModal" :patient="activePatient" :source-status="status" />
|
||||
<ManualPatientOperationsModal v-model:show="showManualOperationsModal" :patient="activePatient" :source-status="status" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user