Добавил проверку источника при добавлении пациента и вывод отчетов выбранной мед. сестры

This commit is contained in:
brusnitsyn
2026-06-03 13:56:05 +09:00
parent e758769035
commit 720ca1b39a
8 changed files with 121 additions and 28 deletions

View File

@@ -26,7 +26,13 @@ class NurseController extends Controller
{ {
public function getPatient($id, Request $request) public function getPatient($id, Request $request)
{ {
return Cache::remember("nurse_patient:{$id}", 120, function () use ($id, $request) { $patientSource = $request->query('patient_source', 'manual');
if ($patientSource === 'manual') {
return Cache::remember("nurse_patient:manual:{$id}", 120, function () use ($id, $request) {
return UnifiedMedicalHistory::where('id', $id)->first();
});
}
return Cache::remember("nurse_patient:mis:{$id}", 120, function () use ($id, $request) {
return MisMKSB::where('MedicalHistoryID', $id)->select(MisMKSB::workColumns())->first(); return MisMKSB::where('MedicalHistoryID', $id)->select(MisMKSB::workColumns())->first();
}); });
} }
@@ -202,6 +208,11 @@ class NurseController extends Controller
$reportNurseId = $request->input('report_nurse_id'); $reportNurseId = $request->input('report_nurse_id');
$this->syncNurseSnapshot($originalId, $data, $migrationData, $departmentId, $reportNurseId); $this->syncNurseSnapshot($originalId, $data, $migrationData, $departmentId, $reportNurseId);
if (Cache::has("nurse_patient:manual:{$id}"))
Cache::forget("nurse_patient:manual:{$id}");
if (Cache::has("nurse_patient:mis:{$id}"))
Cache::forget("nurse_patient:mis:{$id}");
return response()->json([ return response()->json([
'data' => $historyCorrection, 'data' => $historyCorrection,
], 201); ], 201);

View File

@@ -35,6 +35,7 @@ class NurseReportController extends Controller
$departmentId = $request->query('departmentId') ? (int) $request->query('departmentId') : null; $departmentId = $request->query('departmentId') ? (int) $request->query('departmentId') : null;
$department = Department::where('department_id', $departmentId)->firstOrFail(); $department = Department::where('department_id', $departmentId)->firstOrFail();
$dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user); $dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user);
$isRangeOneDay = $this->dateRangeService->isRangeOneDay($dateRange->startDate, $dateRange->endDate);
// Проверяем, есть ли отчет за этот период // Проверяем, есть ли отчет за этот период
$isPastPeriod = $this->dateRangeService->isPastPeriod($dateRange); $isPastPeriod = $this->dateRangeService->isPastPeriod($dateRange);
@@ -43,9 +44,42 @@ class NurseReportController extends Controller
->where('period_end', '<=', $dateRange->endSql()) ->where('period_end', '<=', $dateRange->endSql())
->exists(); ->exists();
$hasReport = $existsReport && $isPastPeriod; $isCurrentPeriod = !$isPastPeriod;
$data = $this->unifiedMedicalHistoryService->getGroupedHistories($dateRange, $department->rf_mis_department_id); $reportsNurse = ReportNurse::where('rf_department_id', $departmentId)
->where('period_start', '>=', $dateRange->startSql())
->where('period_end', '<=', $dateRange->endSql())
->where('rf_lpudoctor_id', $selectedUserId)
->orderBy('period_end', 'desc')
->with(['doctor'])
->get();
$hasNurseReport = $reportsNurse->count() > 0;
$reportNurseIds = $reportsNurse->pluck('id')->toArray();
// Получаем пациентов (источник зависит от периода)
if ($isCurrentPeriod) {
// Для текущего периода - пациенты из МИС
$patients = $this->unifiedMedicalHistoryService->getGroupedHistories(
$dateRange,
$department->rf_mis_department_id,
);
$latestReport = $reportsNurse->first();
} else {
// Для прошедшего периода - данные из отчета
$patients = $hasNurseReport
? $this->nurseMedicalHistoryService->getGroupedHistories(
$dateRange,
$department->rf_mis_department_id,
$reportNurseIds
)
: [];
$latestReport = $reportsNurse->first();
}
//$data = $this->unifiedMedicalHistoryService->getGroupedHistories($dateRange, $department->rf_mis_department_id);
$currentReport = ReportNurse::where('rf_department_id', $departmentId) $currentReport = ReportNurse::where('rf_department_id', $departmentId)
->where('period_start', '>=', $dateRange->startSql()) ->where('period_start', '>=', $dateRange->startSql())
@@ -56,7 +90,8 @@ class NurseReportController extends Controller
$isRangeOneDay = $this->dateRangeService->isRangeOneDay($dateRange->startDate, $dateRange->endDate); $isRangeOneDay = $this->dateRangeService->isRangeOneDay($dateRange->startDate, $dateRange->endDate);
return Inertia::render('Nurse/Report/Index', [ return Inertia::render('Nurse/Report/Index', [
'patients' => $data, 'patients' => $patients,
'latestReport' => $latestReport ?? null,
'reportNurseId' => $currentReport?->id, 'reportNurseId' => $currentReport?->id,
'canSaveReport' => $isRangeOneDay && $user->currentRoleCan('nurse.report.create'), 'canSaveReport' => $isRangeOneDay && $user->currentRoleCan('nurse.report.create'),
'canEditPastReport' => $user->currentRoleCan('nurse.report.edit.past'), 'canEditPastReport' => $user->currentRoleCan('nurse.report.edit.past'),

View File

@@ -39,4 +39,9 @@ class ReportNurse extends Model
{ {
return $this->belongsTo(ReportStatus::class); return $this->belongsTo(ReportStatus::class);
} }
public function doctor()
{
return $this->belongsTo(MisLpuDoctor::class, 'rf_lpudoctor_id', 'LPUDoctorID');
}
} }

View File

@@ -50,6 +50,12 @@ class NurseReportService
'rf_user_id' => $user->id, 'rf_user_id' => $user->id,
]; ];
$existsReport = ReportNurse::where('period_start', $data['period_start'])
->where('period_end', $data['period_end'])
->exists();
if ($existsReport) unset($data['rf_lpudoctor_id']);
$report = ReportNurse::updateOrCreate( $report = ReportNurse::updateOrCreate(
[ [
'report_date' => $data['report_date'], 'report_date' => $data['report_date'],

View File

@@ -14,7 +14,7 @@ const props = defineProps({
const emits = defineEmits(['clickEdit', 'clickDelete']) const emits = defineEmits(['clickEdit', 'clickDelete'])
const onClickEdit = () => { const onClickEdit = () => {
emits('clickEdit', props.row.id) emits('clickEdit', props.row)
} }
const onClickDelete = () => { const onClickDelete = () => {
emits('clickDelete', props.row.id) emits('clickDelete', props.row.id)

View File

@@ -168,7 +168,7 @@ const search = (search) => {
const onChangeSearch = (historyId) => { const onChangeSearch = (historyId) => {
loadingChangeSelect.value = true loadingChangeSelect.value = true
axios.get(`/api/nurse/patients/${historyId}`).then(res => { axios.get(`/api/nurse/patients/${historyId}?patient_source=mis`).then(res => {
form.value.medical_card_number = res.data.medical_card_number form.value.medical_card_number = res.data.medical_card_number
form.value.full_name = res.data.full_name form.value.full_name = res.data.full_name
form.value.urgency_id = res.data.urgency_id form.value.urgency_id = res.data.urgency_id

View File

@@ -27,6 +27,10 @@ const props = defineProps({
reportNurseId: { reportNurseId: {
type: Number, type: Number,
default: null default: null
},
patientSource: {
type: String,
default: 'manual'
} }
}) })
@@ -126,7 +130,7 @@ const submit = async () => {
const fetchPatient = async (historyId) => { const fetchPatient = async (historyId) => {
loading.value = true loading.value = true
await axios.get(`/api/nurse/patients/${historyId}`) await axios.get(`/api/nurse/patients/${historyId}?patient_source=${props.patientSource}`)
.then(res => { .then(res => {
form.value.patient_source = res.data.source_type form.value.patient_source = res.data.source_type
form.value.patient_id = historyId form.value.patient_id = historyId

View File

@@ -1,6 +1,6 @@
<script setup> <script setup>
import AppLayout from "../../../Layouts/AppLayout.vue"; import AppLayout from "../../../Layouts/AppLayout.vue";
import {NFlex, NTag, NDataTable, NButton, NTabs, NTabPane} from 'naive-ui' import {NFlex, NTag, NDataTable, NButton, NTabs, NTabPane, NSpace} from 'naive-ui'
import AppContainer from "../../../Components/AppContainer.vue"; import AppContainer from "../../../Components/AppContainer.vue";
import AppPanel from "../../../Components/AppPanel.vue"; import AppPanel from "../../../Components/AppPanel.vue";
import ShiftPickerQuery from "../../../Components/ShiftPickerQuery.vue"; import ShiftPickerQuery from "../../../Components/ShiftPickerQuery.vue";
@@ -43,7 +43,11 @@ const props = defineProps({
dates: { dates: {
type: Array, type: Array,
default: [] default: []
} },
latestReport: {
type: Object,
default: () => ({ })
},
}) })
const canEdit = computed(() => props.canSaveReport || props.canEditPastReport) const canEdit = computed(() => props.canSaveReport || props.canEditPastReport)
@@ -51,6 +55,7 @@ const canEdit = computed(() => props.canSaveReport || props.canEditPastReport)
const showAddMedicalHistoryModal = shallowRef(false) const showAddMedicalHistoryModal = shallowRef(false)
const showEditMedicalHistoryModal = shallowRef(false) const showEditMedicalHistoryModal = shallowRef(false)
const editHistoryId = ref(null) const editHistoryId = ref(null)
const patientSource = ref(null)
const authStore = useAuthStore() const authStore = useAuthStore()
const userDepartment = authStore.userDepartment const userDepartment = authStore.userDepartment
const loading = ref(false) const loading = ref(false)
@@ -64,20 +69,30 @@ const patientsByGroup = computed(() => {
recipient: [], recipient: [],
discharged: [], discharged: [],
transferred: [], transferred: [],
}; reanimations: [],
observables: []
for (const p of props.patients.data) {
// Группировка по срочности
if (p.patient_urgency === 'urgent') groups.urgent.push(p);
else if (p.patient_urgency === 'planned') groups.planned.push(p);
// Группировка по статусу (дублирование нужно, если один пациент может быть в двух таблицах)
if (groups.hasOwnProperty(p.patient_status)) {
groups[p.patient_status].push(p);
}
} }
return groups; const patients = props.patients?.data ?? []
for (const raw of patients) {
const p = raw
const flags = p.period_flags ?? {}
const isCurrentAtEnd = flags.current_at_end ?? ['in_department', 'recipient'].includes(p.patient_status)
// Группировка по срочности за период: пациент должен состоять на конец периода.
if (isCurrentAtEnd && (flags.urgent ?? p.patient_urgency === 'urgent')) groups.urgent.push(p)
else if (isCurrentAtEnd && (flags.planned ?? p.patient_urgency === 'planned')) groups.planned.push(p)
// Событийная группировка за период. Один пациент может быть в нескольких группах.
if (flags.recipient ?? p.patient_status === 'recipient') groups.recipient.push(p)
if (flags.current_at_end ?? p.patient_status === 'in_department') groups.in_department.push(p)
if (flags.discharged ?? p.patient_status === 'discharged') groups.discharged.push(p)
if (flags.deceased ?? p.patient_status === 'deceased') groups.deceased.push(p)
if (flags.transferred ?? p.patient_status === 'transferred') groups.transferred.push(p)
}
return groups
}) })
const columns = [ const columns = [
@@ -115,16 +130,17 @@ const columns = [
row: row, row: row,
canEdit: canEdit.value, canEdit: canEdit.value,
onClickDelete: (historyId) => onClickDeleteButton(historyId), onClickDelete: (historyId) => onClickDeleteButton(historyId),
onClickEdit: (historyId) => onClickEditButton(historyId), onClickEdit: (row) => onClickEditButton(row),
} }
) )
} }
} }
] ]
const onClickEditButton = (historyId) => { const onClickEditButton = (row) => {
showEditMedicalHistoryModal.value = true showEditMedicalHistoryModal.value = true
editHistoryId.value = historyId editHistoryId.value = row.id
patientSource.value = row.source
} }
const onClickDeleteButton = async (historyId) => { const onClickDeleteButton = async (historyId) => {
@@ -158,6 +174,17 @@ const submit = () => {
}) })
} }
const reportCreator = computed(() => {
if (props.latestReport === null) return ''
if (props.latestReport.doctor.LPUDoctorID === 0) return 'Отчет создан системой'
else return `Отчет создан: ${props.latestReport.doctor.FAM_V} ${props.latestReport.doctor.IM_V} ${props.latestReport.doctor.OT_V}`
})
const reportCreatorType = computed(() => {
if (props.latestReport === null) return 'warning'
if (props.latestReport.doctor.LPUDoctorID === 0) return 'error'
else return 'warning'
})
const formattedLabel = (word, count) => { const formattedLabel = (word, count) => {
return `${word} (${count})` return `${word} (${count})`
} }
@@ -168,9 +195,14 @@ const formattedLabel = (word, count) => {
<AppContainer> <AppContainer>
<AppPanel> <AppPanel>
<NFlex justify="space-between" align="center"> <NFlex justify="space-between" align="center">
<NTag type="info" :bordered="false"> <NSpace>
{{ department?.name_full ?? userDepartment.name_full }} <NTag type="info" :bordered="false">
</NTag> {{ department?.name_full ?? userDepartment.name_full }}
</NTag>
<NTag v-if="props.latestReport" :type="reportCreatorType" :bordered="false">
{{ reportCreator }}
</NTag>
</NSpace>
<DatePickerQuery :date="dates" :is-head-or-admin="true" class="text-lg!" hint /> <DatePickerQuery :date="dates" :is-head-or-admin="true" class="text-lg!" hint />
</NFlex> </NFlex>
</AppPanel> </AppPanel>
@@ -238,7 +270,7 @@ const formattedLabel = (word, count) => {
</NButton> </NButton>
</AppContainer> </AppContainer>
<AddMedicalHistoryModal v-model:show="showAddMedicalHistoryModal" /> <AddMedicalHistoryModal v-model:show="showAddMedicalHistoryModal" />
<EditMedicalHistoryModal v-model:show="showEditMedicalHistoryModal" :history-id="editHistoryId" :report-nurse-id="props.reportNurseId" /> <EditMedicalHistoryModal v-model:show="showEditMedicalHistoryModal" :history-id="editHistoryId" :patient-source="patientSource" :report-nurse-id="props.reportNurseId" />
</AppLayout> </AppLayout>
</template> </template>