Реализация смены статуса

Добавлен move метод
Правка в поиске
This commit is contained in:
brusnitsyn
2025-12-07 22:33:19 +09:00
parent 2e1b5a3d0e
commit 945b53c578
10 changed files with 142 additions and 17 deletions

View File

@@ -2,8 +2,10 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Http\Resources\ArchiveHistoryResource;
use App\Models\ArchiveHistory; use App\Models\ArchiveHistory;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
class ArchiveHistoryController extends Controller class ArchiveHistoryController extends Controller
{ {
@@ -18,4 +20,34 @@ class ArchiveHistoryController extends Controller
return response()->json($archiveHistory); return response()->json($archiveHistory);
} }
public function move(Request $request)
{
$data = $request->validate([
'issue_at' => 'nullable|numeric:',
'return_at' => 'nullable|numeric:',
'org_id' => 'required|numeric',
'employee_name' => 'nullable|string',
'employee_post' => 'nullable|string',
'comment' => 'nullable|string',
'has_lost' => 'boolean',
'historyable_id' => 'nullable|numeric',
]);
// Находим связанную модель ??
$historyable = SttMedicalHistory::findOrFail($data['historyable_id']);
// Преобразуем timestamp в дату, если пришли числа
if (isset($data['issue_at']) && is_numeric($data['issue_at'])) {
$data['issue_at'] = Carbon::createFromTimestampMs($data['issue_at'])->format('Y-m-d');
}
if (isset($data['return_at']) && is_numeric($data['return_at'])) {
$data['return_at'] = Carbon::createFromTimestampMs($data['return_at'])->format('Y-m-d');
}
$archiveHistory = ArchiveHistory::create($data);
return response()->json(ArchiveHistoryResource::make($archiveHistory));
}
} }

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Http\Resources\ArchiveHistoryResource; use App\Http\Resources\ArchiveHistoryResource;
use App\Http\Resources\ArchiveInfoResource;
use App\Models\SI\SttMedicalHistory; use App\Models\SI\SttMedicalHistory;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@@ -19,6 +20,10 @@ class MedicalHistoryController extends Controller
$archiveJournal = ArchiveHistoryResource::collection($patient->archiveHistory); $archiveJournal = ArchiveHistoryResource::collection($patient->archiveHistory);
$archiveInfo = $patient->archiveInfo; $archiveInfo = $patient->archiveInfo;
if (!empty($archiveInfo)) {
$archiveInfo = ArchiveInfoResource::make($patient->archiveInfo);
}
$patientInfo = [ $patientInfo = [
'info' => $patient, 'info' => $patient,
'journal' => $archiveJournal, 'journal' => $archiveJournal,

View File

@@ -20,7 +20,8 @@ class SttMedicalHistoryResource extends JsonResource
'fullname' => $this->getFullNameAttribute(), 'fullname' => $this->getFullNameAttribute(),
'daterecipient' => Carbon::parse($this->daterecipient)->format('d.m.Y'), 'daterecipient' => Carbon::parse($this->daterecipient)->format('d.m.Y'),
'dateextract' => Carbon::parse($this->dateextract)->format('d.m.Y'), 'dateextract' => Carbon::parse($this->dateextract)->format('d.m.Y'),
'narhiv' => $this->narhiv, 'card_num' => $this->archiveInfo->num ?? null,
'status' => $this->archiveInfo->status ?? null,
'datearhiv' => Carbon::parse($this->datearhiv)->format('d.m.Y'), 'datearhiv' => Carbon::parse($this->datearhiv)->format('d.m.Y'),
'statgod' => $this->statgod, 'statgod' => $this->statgod,
'enp' => $this->enp, 'enp' => $this->enp,

View File

@@ -6,6 +6,51 @@ use Illuminate\Database\Eloquent\Model;
class ArchiveHistory extends Model class ArchiveHistory extends Model
{ {
protected static function booted()
{
static::created(function ($archiveHistory) {
$archiveHistory->updateArchiveInfoStatus();
});
static::updated(function ($archiveHistory) {
$archiveHistory->updateArchiveInfoStatus();
});
}
public function updateArchiveInfoStatus()
{
// Получаем связанную модель через морф
$historyable = $this->historyable;
if (!$historyable) {
return;
}
// Проверяем, есть ли у модели архивная информация
if (method_exists($historyable, 'archiveInfo') && $historyable->archiveInfo) {
$historyable->archiveInfo->update([
'status_id' => $this->determineStatusId()
]);
}
}
public function determineStatusId()
{
if ($this->has_lost) {
return 4; // Утерян
}
if ($this->issue_at && !$this->return_at) {
return 3; // Выдан
}
if ($this->return_at) {
return 2; // В архиве
}
return 2; // По умолчанию
}
protected $fillable = [ protected $fillable = [
'historyable_type', 'historyable_type',
'historyable_id', 'historyable_id',

View File

@@ -18,4 +18,9 @@ class ArchiveInfo extends Model
{ {
return $this->morphTo(); return $this->morphTo();
} }
public function status()
{
return $this->belongsTo(ArchiveStatus::class);
}
} }

View File

@@ -43,12 +43,19 @@ class SttMedicalHistory extends Model
{ {
return $query->where(function($q) use ($searchText) { return $query->where(function($q) use ($searchText) {
if (is_numeric($searchText)) { if (is_numeric($searchText)) {
$q->where('medcardnum', 'ILIKE', "$searchText%"); $q->where('medcardnum', 'ILIKE', "$searchText");
} else { } else {
// Ищем по всем частям ФИО // Ищем в объединенном ФИО и в отдельных полях
$q->where('family', 'ILIKE', "%$searchText%") $searchPattern = "%{$searchText}%";
->orWhere('name', 'ILIKE', "%$searchText%")
->orWhere('ot', 'ILIKE', "%$searchText%"); $q->where(function($subQ) use ($searchPattern) {
// Поиск в объединенной строке
$subQ->whereRaw("CONCAT(family, ' ', name, ' ', COALESCE(ot, '')) ILIKE ?", [$searchPattern])
// И дополнительно в отдельных полях для точности
->orWhere('family', 'ILIKE', $searchPattern)
->orWhere('name', 'ILIKE', $searchPattern)
->orWhere('ot', 'ILIKE', $searchPattern);
});
} }
}); });
} }

View File

@@ -92,8 +92,8 @@ watch(() => props.patientId, (newId) => {
<NFlex inline justify="space-between" align="center" :wrap="false"> <NFlex inline justify="space-between" align="center" :wrap="false">
<NForm inline :show-feedback="false"> <NForm inline :show-feedback="false">
<NFormItem label="Статус карты"> <NFormItem label="Статус карты">
<NTag type="default" :bordered="false" round> <NTag :type="patient.archiveInfo?.status?.variant ?? 'error'" :bordered="false" round>
Не определен {{ patient.archiveInfo?.status?.text ?? 'Нет в архиве' }}
</NTag> </NTag>
</NFormItem> </NFormItem>
<NFormItem label="№ в архиве"> <NFormItem label="№ в архиве">

View File

@@ -11,6 +11,7 @@ const emits = defineEmits(['closeWithoutSave'])
const loading = ref(false) const loading = ref(false)
const archiveHistory = ref({ const archiveHistory = ref({
historyable_id: props.archiveHistoryId,
issue_at: null, issue_at: null,
org_id: null, org_id: null,
return_at: null, return_at: null,
@@ -23,6 +24,7 @@ const orgs = ref([])
const onResetData = () => { const onResetData = () => {
archiveHistory.value = { archiveHistory.value = {
historyable_id: props.archiveHistoryId,
issue_at: null, issue_at: null,
org_id: null, org_id: null,
return_at: null, return_at: null,
@@ -39,13 +41,13 @@ const onCloseWithoutSave = () => {
const loadArchiveHistoryData = async () => { const loadArchiveHistoryData = async () => {
try { try {
axios.get('/api/orgs').then(res => { await axios.get('/api/orgs').then(res => {
orgs.value = res.data orgs.value = res.data
}) })
if (!props.archiveHistoryId) return if (!props.archiveHistoryId) return
axios.get(`/api/archive/histories/${props.archiveHistoryId}`).then(res => { await axios.get(`/api/archive/histories/${props.archiveHistoryId}`).then(res => {
archiveHistory.value = res.data archiveHistory.value = res.data
}) })
} catch (error) { } catch (error) {
@@ -55,10 +57,22 @@ const loadArchiveHistoryData = async () => {
} }
} }
const submit = () => {
try {
axios.post('/api/archive/histories/move', archiveHistory.value).then(res => {
onCloseWithoutSave()
})
} catch (error) {
console.error(error)
} finally {
loading.value = false
}
}
// Наблюдаем за изменением archiveHistoryId // Наблюдаем за изменением archiveHistoryId
watch(() => props.archiveHistoryId, (newId) => { watch(() => props.archiveHistoryId, async (newId) => {
if (newId) { if (newId) {
loadArchiveHistoryData() await loadArchiveHistoryData()
} else { } else {
onResetData() onResetData()
} }
@@ -101,7 +115,7 @@ watch(() => props.archiveHistoryId, (newId) => {
Закрыть без сохранения Закрыть без сохранения
</NButton> </NButton>
<NDivider vertical /> <NDivider vertical />
<NButton secondary type="primary"> <NButton secondary type="primary" @click="submit">
Сохранить Сохранить
</NButton> </NButton>
</NSpace> </NSpace>

View File

@@ -1,5 +1,5 @@
<script setup> <script setup>
import {NDataTable, NEllipsis} from "naive-ui" import {NDataTable, NEllipsis, NTag} from "naive-ui"
import {computed, h, reactive, ref} from "vue" import {computed, h, reactive, ref} from "vue"
import {useMedicalHistoryFilter} from "../../../Composables/useMedicalHistoryFilter.js"; import {useMedicalHistoryFilter} from "../../../Composables/useMedicalHistoryFilter.js";
import ArchiveHistoryModal from '../ArchiveHistoryModal/Index.vue' import ArchiveHistoryModal from '../ArchiveHistoryModal/Index.vue'
@@ -25,6 +25,19 @@ const props = defineProps({
const { isLoading, handlePageChange, handlePageSizeChange, meta } = useMedicalHistoryFilter(props.filters) const { isLoading, handlePageChange, handlePageSizeChange, meta } = useMedicalHistoryFilter(props.filters)
const archiveStatusColumn = (status) => {
const tagType = status?.variant ?? 'error'
const tagText = status?.text ?? 'Нет в архиве'
console.log(tagType)
return h(
NEllipsis,
null,
{
default: () => h(NTag, {type: tagType, round: true, size: 'small'}, tagText)
})
}
const columns = ref([ const columns = ref([
{ {
title: '№ карты', title: '№ карты',
@@ -58,9 +71,9 @@ const columns = ref([
}, },
{ {
title: '№ архива', title: '№ архива',
key: 'narhiv', key: 'card_num',
width: 120, width: 120,
render: (row) => h(NEllipsis, null, { default: () => row.narhiv || '-' }) render: (row) => h(NEllipsis, null, { default: () => row.card_num || '-' })
}, },
{ {
title: 'Дата архива', title: 'Дата архива',
@@ -72,7 +85,7 @@ const columns = ref([
title: 'Статус', title: 'Статус',
key: 'status', key: 'status',
width: 100, width: 100,
render: (row) => h(NEllipsis, null, { default: () => row.status || '-' }) render: (row) => archiveStatusColumn(row.status)
} }
]) ])
const showArchiveHistoryModal = ref(false) const showArchiveHistoryModal = ref(false)

View File

@@ -16,6 +16,9 @@ Route::prefix('si')->group(function () {
Route::prefix('archive')->group(function () { Route::prefix('archive')->group(function () {
Route::prefix('histories')->group(function () { Route::prefix('histories')->group(function () {
Route::get('{id}', [\App\Http\Controllers\ArchiveHistoryController::class, 'show']); Route::get('{id}', [\App\Http\Controllers\ArchiveHistoryController::class, 'show']);
Route::prefix('move')->group(function () {
Route::post('/', [\App\Http\Controllers\ArchiveHistoryController::class, 'move']);
});
}); });
}); });