Files
onboard/resources/js/Pages/Report/Components/ReportSectionItem.vue
2026-01-20 09:26:47 +09:00

171 lines
4.4 KiB
Vue
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.

<script setup>
import {NIcon, NDataTable} 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";
const props = defineProps({
mode: {
type: String,
default: 'fillable' // 'fillable', 'readonly'
},
keys: {
type: Array,
default: ['num', 'fullname', 'age', 'birth_date', 'mkb.ds']
},
status: {
type: String,
default: null // 'plan'
}
})
const isFillableMode = computed(() => props.mode.toLowerCase() === 'fillable')
const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
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)
// Добавляем drag колонку если режим fillable
const columns = computed(() => {
if (!isFillableMode.value) return baseColumns
const dragColumn = {
title: '',
key: 'drag',
width: 40,
render: (row) => h(
'div',
{
style: {
cursor: 'grab',
textAlign: 'center',
userSelect: 'none'
}
},
[
h(NIcon, {
depth: '2',
component: TbGripVertical
}, [])
]
)
}
return [dragColumn, ...baseColumns]
})
const handleDragStart = (e, row) => {
// Устанавливаем данные о перетаскиваемом элементе
e.dataTransfer.setData('application/json', JSON.stringify({
row: row,
fromStatus: props.status
}))
e.dataTransfer.effectAllowed = 'copy'
const rowElement = e.target
// Эмитим событие для родителя
emit('item-dragged', { row, fromStatus: props.status })
// Добавляем класс для визуальной обратной связи
e.target.classList.add('dragging')
}
const handleDragEnd = (e) => {
if (e.target) {
e.target.classList.remove('dragging')
}
}
const handleDragOver = (e) => {
e.preventDefault()
}
const handleDrop = (e) => {
e.preventDefault()
try {
const dragData = JSON.parse(e.dataTransfer.getData('application/json'))
// Эмитим событие для родителя
emit('item-dropped', {
item: dragData.row,
fromStatus: dragData.fromStatus,
toStatus: props.status
})
} catch (error) {
console.error('Drop error:', error)
}
}
const fetchPatients = async () => {
isLoading.value = true
await axios.post('/api/mis/patients', {
status: props.status
}).then((res) => {
patientsData.value[props.status] = res.data
}).finally(() => {
isLoading.value = false
})
}
function rowProps(row) {
return {
draggable: true,
style: 'cursor: grab;',
onDragstart: (e) => {
handleDragStart(e, row)
},
onDragend: (e) => {
handleDragEnd(e)
},
onDragover: (e) => {
handleDragOver(e)
},
onDrop: (e) => {
handleDrop(e)
}
}
}
onMounted(async () => {
await fetchPatients()
})
</script>
<template>
<NDataTable :columns="columns"
:data="patientsData[status]"
size="small"
@drop="handleDrop"
@dragover="handleDragOver"
:loading="isLoading"
max-height="200"
min-height="200"
:row-props="rowProps"
class="text-sm!">
</NDataTable>
<!-- <NDataTable :columns="columns"-->
<!-- :data="data"-->
<!-- size="small"-->
<!-- max-height="200"-->
<!-- class="text-sm!">-->
<!-- </NDataTable>-->
</template>
<style scoped>
:deep(.n-data-table-th),
:deep(.n-data-table-td) {
white-space: nowrap !important;
font-size: var(--n-font-size);
}
</style>