Много чего
This commit is contained in:
@@ -6,6 +6,7 @@ use App\Http\Resources\ArchiveHistoryResource;
|
|||||||
use App\Http\Resources\ArchiveInfoResource;
|
use App\Http\Resources\ArchiveInfoResource;
|
||||||
use App\Models\ArchiveHistory;
|
use App\Models\ArchiveHistory;
|
||||||
use App\Models\ArchiveInfo;
|
use App\Models\ArchiveInfo;
|
||||||
|
use App\Models\SI\SttMedicalHistory;
|
||||||
use App\Rules\DateTimeOrStringOrNumber;
|
use App\Rules\DateTimeOrStringOrNumber;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
@@ -21,7 +22,10 @@ class ArchiveHistoryController extends Controller
|
|||||||
{
|
{
|
||||||
$archiveHistory = ArchiveHistory::find($id);
|
$archiveHistory = ArchiveHistory::find($id);
|
||||||
|
|
||||||
return response()->json($archiveHistory);
|
return response()->json([
|
||||||
|
...$archiveHistory->toArray(),
|
||||||
|
'type' => $archiveHistory->historyType()
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function moveStore(Request $request)
|
public function moveStore(Request $request)
|
||||||
@@ -34,36 +38,46 @@ class ArchiveHistoryController extends Controller
|
|||||||
'employee_post' => 'nullable|string',
|
'employee_post' => 'nullable|string',
|
||||||
'comment' => 'nullable|string',
|
'comment' => 'nullable|string',
|
||||||
'has_lost' => 'boolean',
|
'has_lost' => 'boolean',
|
||||||
'historyable_id' => 'nullable|numeric',
|
'archive_info_id' => 'required|numeric',
|
||||||
'historyable_type' => 'required|string',
|
'type' => 'required|string',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Преобразуем timestamp в дату, если пришли числа
|
// Преобразуем timestamp в дату, если пришли числа
|
||||||
if (isset($data['issue_at']) && is_numeric($data['issue_at'])) {
|
if (isset($data['issue_at']) && is_numeric($data['issue_at'])) {
|
||||||
$data['issue_at'] = Carbon::createFromTimestampMs($data['issue_at'])->format('Y-m-d');
|
$data['issue_at'] = Carbon::createFromTimestampMs($data['issue_at'])
|
||||||
|
->setTimezone(config('app.timezone'))
|
||||||
|
->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($data['return_at']) && is_numeric($data['return_at'])) {
|
if (isset($data['return_at']) && is_numeric($data['return_at'])) {
|
||||||
$data['return_at'] = Carbon::createFromTimestampMs($data['return_at'])->format('Y-m-d');
|
$data['return_at'] = Carbon::createFromTimestampMs($data['return_at'])
|
||||||
|
->setTimezone(config('app.timezone'))
|
||||||
|
->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
$archiveHistory = ArchiveHistory::create($data);
|
$archiveInfo = ArchiveInfo::whereId($data['archive_info_id'])->first();
|
||||||
|
if ($data['type'] === 'mis') {
|
||||||
// Если переданы данные для полиморфной связи
|
$archiveHistory = $archiveInfo->misHistory->archiveHistory()->create([
|
||||||
if ($request->filled('historyable_id') && $request->filled('historyable_type')) {
|
'issue_at' => $data['issue_at'],
|
||||||
// Найти связанную модель
|
'return_at' => $data['return_at'],
|
||||||
$historyableClass = $request->input('historyable_type');
|
'org_id' => $data['org_id'],
|
||||||
|
'employee_name' => $data['employee_name'],
|
||||||
// Проверяем, существует ли класс модели
|
'employee_post' => $data['employee_post'],
|
||||||
if (class_exists($historyableClass)) {
|
'comment' => $data['comment'],
|
||||||
$historyableModel = $historyableClass::find($request->input('historyable_id'));
|
'has_lost' => $data['has_lost'],
|
||||||
|
'mis_history_id' => $archiveInfo->mis_history_id
|
||||||
if ($historyableModel) {
|
]);
|
||||||
// Связываем модели
|
} else {
|
||||||
$archiveHistory->historyable()->associate($historyableModel);
|
$archiveHistory = $archiveInfo->foxproHistory->archiveHistory()->create([
|
||||||
$archiveHistory->save();
|
'issue_at' => $data['issue_at'],
|
||||||
}
|
'return_at' => $data['return_at'],
|
||||||
}
|
'org_id' => $data['org_id'],
|
||||||
|
'employee_name' => $data['employee_name'],
|
||||||
|
'employee_post' => $data['employee_post'],
|
||||||
|
'comment' => $data['comment'],
|
||||||
|
'has_lost' => $data['has_lost'],
|
||||||
|
'foxpro_history_id' => $archiveInfo->foxpro_history_id,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(ArchiveHistoryResource::make($archiveHistory));
|
return response()->json(ArchiveHistoryResource::make($archiveHistory));
|
||||||
@@ -79,17 +93,20 @@ class ArchiveHistoryController extends Controller
|
|||||||
'employee_post' => 'nullable|string',
|
'employee_post' => 'nullable|string',
|
||||||
'comment' => 'nullable|string',
|
'comment' => 'nullable|string',
|
||||||
'has_lost' => 'boolean',
|
'has_lost' => 'boolean',
|
||||||
'historyable_id' => 'nullable|numeric',
|
'type' => 'required|string',
|
||||||
'historyable_type' => 'required|string',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Преобразуем timestamp в дату, если пришли числа
|
// Преобразуем timestamp в дату, если пришли числа
|
||||||
if (isset($data['issue_at']) && is_numeric($data['issue_at'])) {
|
if (isset($data['issue_at']) && is_numeric($data['issue_at'])) {
|
||||||
$data['issue_at'] = Carbon::createFromTimestampMs($data['issue_at'])->format('Y-m-d');
|
$data['issue_at'] = Carbon::createFromTimestampMs($data['issue_at'])
|
||||||
|
->setTimezone(config('app.timezone'))
|
||||||
|
->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($data['return_at']) && is_numeric($data['return_at'])) {
|
if (isset($data['return_at']) && is_numeric($data['return_at'])) {
|
||||||
$data['return_at'] = Carbon::createFromTimestampMs($data['return_at'])->format('Y-m-d');
|
$data['return_at'] = Carbon::createFromTimestampMs($data['return_at'])
|
||||||
|
->setTimezone(config('app.timezone'))
|
||||||
|
->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
$archiveHistory = ArchiveHistory::find($id);
|
$archiveHistory = ArchiveHistory::find($id);
|
||||||
@@ -105,7 +122,8 @@ class ArchiveHistoryController extends Controller
|
|||||||
'id' => 'required|numeric',
|
'id' => 'required|numeric',
|
||||||
'num' => 'nullable|string',
|
'num' => 'nullable|string',
|
||||||
'post_in' => ['nullable', new DateTimeOrStringOrNumber],
|
'post_in' => ['nullable', new DateTimeOrStringOrNumber],
|
||||||
'historyable_type' => 'required|string',
|
'status' => 'nullable',
|
||||||
|
'type' => 'nullable'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Преобразуем timestamp в дату, если пришли числа
|
// Преобразуем timestamp в дату, если пришли числа
|
||||||
@@ -113,25 +131,16 @@ class ArchiveHistoryController extends Controller
|
|||||||
$data['post_in'] = Carbon::createFromTimestampMs($data['post_in'])->format('Y-m-d');
|
$data['post_in'] = Carbon::createFromTimestampMs($data['post_in'])->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($patientId && $request->filled('historyable_type')) {
|
$archiveInfo = ArchiveInfo::whereId($patientId)->first();
|
||||||
// Найти связанную модель
|
|
||||||
$historyableClass = $request->input('historyable_type');
|
|
||||||
|
|
||||||
// Проверяем, существует ли класс модели
|
$archiveInfo->updateOrCreate(
|
||||||
if (class_exists($historyableClass)) {
|
['id' => $patientId],
|
||||||
$historyableModel = $historyableClass::find($patientId);
|
[
|
||||||
|
'archive_num' => $data['num'],
|
||||||
|
'post_in' => $data['post_in'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
if ($historyableModel) {
|
return response()->json()->setStatusCode(200);
|
||||||
// Связываем модели
|
|
||||||
$historyableModel->archiveInfo()->updateOrCreate([
|
|
||||||
'historyable_type' => $historyableClass,
|
|
||||||
'historyable_id' => $patientId,
|
|
||||||
], $data);
|
|
||||||
return response()->json(ArchiveInfoResource::make($historyableModel->archiveInfo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response()->json()->setStatusCode(500);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,58 +25,15 @@ class IndexController extends Controller
|
|||||||
$searchText = $request->get('search', null);
|
$searchText = $request->get('search', null);
|
||||||
$dateExtractFrom = $request->get('date_extract_from', null);
|
$dateExtractFrom = $request->get('date_extract_from', null);
|
||||||
$dateExtractTo = $request->get('date_extract_to', null);
|
$dateExtractTo = $request->get('date_extract_to', null);
|
||||||
$database = $request->get('database', 'separate'); // si, mis
|
|
||||||
$status = $request->get('status', null);
|
$status = $request->get('status', null);
|
||||||
|
|
||||||
$data = [];
|
$data = $this->repository->unifiedSearch(
|
||||||
$databaseStats = $this->repository->getDatabaseStats();
|
$searchText,
|
||||||
|
$dateExtractFrom,
|
||||||
switch ($database) {
|
$dateExtractTo,
|
||||||
case 'si':
|
$status,
|
||||||
$paginator = $this->repository->searchInPostgres(
|
$pageSize
|
||||||
$searchText,
|
);
|
||||||
$dateExtractFrom,
|
|
||||||
$dateExtractTo,
|
|
||||||
$pageSize
|
|
||||||
);
|
|
||||||
$data['si'] = SiSttMedicalHistoryResource::collection($paginator);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'mis':
|
|
||||||
$paginator = $this->repository->searchInMssql(
|
|
||||||
$searchText,
|
|
||||||
$dateExtractFrom,
|
|
||||||
$dateExtractTo,
|
|
||||||
$pageSize
|
|
||||||
);
|
|
||||||
$data['mis'] = MisSttMedicalHistoryResource::collection($paginator);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'smart':
|
|
||||||
$paginator = $this->repository->smartSearch(
|
|
||||||
$searchText,
|
|
||||||
$dateExtractFrom,
|
|
||||||
$dateExtractTo,
|
|
||||||
$pageSize
|
|
||||||
);
|
|
||||||
$data['smart'] = SiSttMedicalHistoryResource::collection($paginator);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'separate':
|
|
||||||
$separateResults = $this->repository->separateSearch(
|
|
||||||
$searchText,
|
|
||||||
$dateExtractFrom,
|
|
||||||
$dateExtractTo,
|
|
||||||
$status,
|
|
||||||
$pageSize
|
|
||||||
);
|
|
||||||
$data = [
|
|
||||||
'si' => SiSttMedicalHistoryResource::collection($separateResults['si']),
|
|
||||||
'mis' => MisSttMedicalHistoryResource::collection($separateResults['mis']),
|
|
||||||
'stats' => $separateResults['stats'],
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$statuses = ArchiveStatus::all()->map(function ($status) {
|
$statuses = ArchiveStatus::all()->map(function ($status) {
|
||||||
return [
|
return [
|
||||||
@@ -91,35 +48,13 @@ class IndexController extends Controller
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
return Inertia::render('Home/Index', [
|
return Inertia::render('Home/Index', [
|
||||||
'cards' => $data,
|
'cards' => MisSttMedicalHistoryResource::collection($data),
|
||||||
'statuses' => $statuses,
|
'statuses' => $statuses,
|
||||||
'databaseStats' => $databaseStats,
|
|
||||||
'filters' => array_merge($request->only([
|
'filters' => array_merge($request->only([
|
||||||
'search', 'date_extract_from', 'date_extract_to',
|
'search', 'date_extract_from', 'date_extract_to',
|
||||||
'page_size', 'page', 'view_type', 'database', 'status'
|
'page_size', 'page', 'status'
|
||||||
]))
|
]))
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// $cardsQuery = SttMedicalHistory::query();
|
|
||||||
//
|
|
||||||
// if (!empty($searchText)) {
|
|
||||||
// $cardsQuery = $cardsQuery->search($searchText);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (!empty($dateExtractFrom)) {
|
|
||||||
// $cardsQuery = $cardsQuery->whereDate('dateextract', '>=', $dateExtractFrom);
|
|
||||||
// if (!empty($dateExtractTo)) {
|
|
||||||
// $cardsQuery = $cardsQuery->whereDate('dateextract', '<=', $dateExtractTo);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// $cards = SttMedicalHistoryResource::collection($cardsQuery->paginate($pageSize));
|
|
||||||
//
|
|
||||||
// return Inertia::render('Home/Index', [
|
|
||||||
// 'cards' => $cards,
|
|
||||||
// 'filters' => $request->only([
|
|
||||||
// 'search', 'date_extract_from', 'date_extract_to', 'page_size', 'page', 'view_type'
|
|
||||||
// ]),
|
|
||||||
// ]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
|
|||||||
use App\Http\Resources\ArchiveHistoryResource;
|
use App\Http\Resources\ArchiveHistoryResource;
|
||||||
use App\Http\Resources\ArchiveInfoResource;
|
use App\Http\Resources\ArchiveInfoResource;
|
||||||
use App\Http\Resources\PatientInfoResource;
|
use App\Http\Resources\PatientInfoResource;
|
||||||
|
use App\Models\ArchiveInfo;
|
||||||
use App\Models\SI\SttMedicalHistory as SiSttMedicalHistory;
|
use App\Models\SI\SttMedicalHistory as SiSttMedicalHistory;
|
||||||
use App\Models\Mis\SttMedicalHistory as MisSttMedicalHistory;
|
use App\Models\Mis\SttMedicalHistory as MisSttMedicalHistory;
|
||||||
use App\Repositories\MedicalHistoryRepository;
|
use App\Repositories\MedicalHistoryRepository;
|
||||||
@@ -14,24 +15,25 @@ class MedicalHistoryController extends Controller
|
|||||||
{
|
{
|
||||||
public function patient($id, Request $request)
|
public function patient($id, Request $request)
|
||||||
{
|
{
|
||||||
$viewType = $request->get('view_type', 'si');
|
$viewType = $request->get('view_type', 'mis');
|
||||||
$patientId = $request->get('patient_id');
|
$patientId = $request->get('patient_id');
|
||||||
|
|
||||||
$patientInfo = null;
|
$archiveInfo = ArchiveInfo::whereId($id)->first()->load('status');
|
||||||
if ($viewType == 'si') $patient = SiSttMedicalHistory::where('id', $id)->first();
|
if ($viewType == 'foxpro') $patient = $archiveInfo->foxproHistory;
|
||||||
else $patient = MisSttMedicalHistory::where('MedicalHistoryID', $id)->first();
|
else $patient = $archiveInfo->misHistory;
|
||||||
$archiveJournal = $patient->archiveHistory ? ArchiveHistoryResource::collection($patient->archiveHistory) : null;
|
|
||||||
|
|
||||||
if (!empty($patient->archiveInfo)) {
|
$archiveJournal = $patient->archiveHistory ? ArchiveHistoryResource::collection($patient->archiveHistory) : null;
|
||||||
$archiveInfo = ArchiveInfoResource::make($patient->archiveInfo)->toArray(request());
|
// dd($archiveInfo);
|
||||||
|
if (!empty($archiveInfo)) {
|
||||||
|
$archiveInfo = ArchiveInfoResource::make($archiveInfo)->toArray(request());
|
||||||
} else {
|
} else {
|
||||||
$archiveInfo = null;
|
$archiveInfo = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$patientInfo = [
|
$patientInfo = [
|
||||||
'historyable_type' => $viewType == 'si' ? SiSttMedicalHistory::class : MisSttMedicalHistory::class,
|
'historyable_type' => $viewType == 'foxpro' ? SiSttMedicalHistory::class : MisSttMedicalHistory::class,
|
||||||
'info' => [
|
'info' => [
|
||||||
'historyable_type' => $viewType == 'si' ? SiSttMedicalHistory::class : MisSttMedicalHistory::class,
|
'historyable_type' => $viewType == 'foxpro' ? SiSttMedicalHistory::class : MisSttMedicalHistory::class,
|
||||||
...PatientInfoResource::make($patient)->toArray(request()),
|
...PatientInfoResource::make($patient)->toArray(request()),
|
||||||
'can_be_issued' => $patient->canBeIssued()
|
'can_be_issued' => $patient->canBeIssued()
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class ArchiveHistoryResource extends JsonResource
|
|||||||
'return_at' => $this->return_at ? Carbon::parse($this->return_at)->format('d.m.Y') : null,
|
'return_at' => $this->return_at ? Carbon::parse($this->return_at)->format('d.m.Y') : null,
|
||||||
'comment' => $this->comment,
|
'comment' => $this->comment,
|
||||||
'org_id' => $this->org_id,
|
'org_id' => $this->org_id,
|
||||||
'org' => $this->org->name,
|
'org' => $this->org?->name,
|
||||||
'employee_name' => $this->employee_name,
|
'employee_name' => $this->employee_name,
|
||||||
'employee_post' => $this->employee_post,
|
'employee_post' => $this->employee_post,
|
||||||
'has_lost' => $this->has_lost,
|
'has_lost' => $this->has_lost,
|
||||||
|
|||||||
@@ -16,11 +16,12 @@ class ArchiveInfoResource extends JsonResource
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'num' => $this->num,
|
'num' => $this->archive_num,
|
||||||
'post_in' => $this->post_in,
|
'post_in' => $this->post_in,
|
||||||
'status' => $this->status,
|
'status' => $this->status,
|
||||||
'historyable_id' => $this->historyable_id,
|
'foxpro_num' => $this->foxpro_num,
|
||||||
'historyable_type' => $this->historyable_type,
|
'mis_num' => $this->mis_num,
|
||||||
|
'type' => $this->historyType()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Http\Resources\Mis;
|
namespace App\Http\Resources\Mis;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
use Illuminate\Support\Carbon;
|
|
||||||
|
|
||||||
class SttMedicalHistoryResource extends JsonResource
|
class SttMedicalHistoryResource extends JsonResource
|
||||||
{
|
{
|
||||||
@@ -15,17 +15,114 @@ class SttMedicalHistoryResource extends JsonResource
|
|||||||
*/
|
*/
|
||||||
public function toArray(Request $request): array
|
public function toArray(Request $request): array
|
||||||
{
|
{
|
||||||
|
// Определяем источник данных
|
||||||
|
$isFromArchive = $this->resource['in_archive'] ?? false;
|
||||||
|
$isTemporary = $this->resource['is_temporary'] ?? false;
|
||||||
|
$historyType = $this->resource['history_type'] ?? 'mis';
|
||||||
|
|
||||||
|
// Формируем ФИО
|
||||||
|
$family = $this->resource['family'] ?? '';
|
||||||
|
$name = $this->resource['name'] ?? '';
|
||||||
|
$ot = $this->resource['ot'] ?? '';
|
||||||
|
|
||||||
|
// Для временных записей (не в архиве) используем данные из MIS
|
||||||
|
if ($isTemporary) {
|
||||||
|
// Данные из stt_medicalhistory (не в архиве)
|
||||||
|
$fullName = trim("{$family} {$name} {$ot}");
|
||||||
|
$birthDate = $this->resource['birth_date'] ?? null;
|
||||||
|
$dateExtract = $this->resource['date_extract'] ?? null;
|
||||||
|
$dateRecipient = null; // Для MIS записей не в архиве может не быть
|
||||||
|
$cardNumber = $this->resource['card_number'] ?? null;
|
||||||
|
$archiveNum = null;
|
||||||
|
$postIn = null;
|
||||||
|
$status = $this->resource['status_text'] ?? 'Не в архиве';
|
||||||
|
} else {
|
||||||
|
// Данные из archive_infos (в архиве)
|
||||||
|
$fullName = trim("{$family} {$name} {$ot}");
|
||||||
|
$birthDate = $this->resource['birth_date'] ?? null;
|
||||||
|
|
||||||
|
// Для архивных записей date_extract может быть из MIS или FoxPro
|
||||||
|
$dateExtract = $this->resource['date_extract'] ?? null;
|
||||||
|
|
||||||
|
// Для MIS записей в архиве
|
||||||
|
if ($historyType === 'mis') {
|
||||||
|
$dateRecipient = $this->resource['date_recipient'] ?? null;
|
||||||
|
} else {
|
||||||
|
// Для FoxPro записей в архиве
|
||||||
|
$dateRecipient = $this->resource['mpostdate'] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cardNumber = $this->resource['card_number'] ?? null;
|
||||||
|
$archiveNum = $this->resource['archive_num'] ?? null;
|
||||||
|
$postIn = $this->resource['post_in'] ?? null;
|
||||||
|
$status = $this->resource['status_text'] ?? 'Неизвестно';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Форматирование дат
|
||||||
|
$formattedBirthDate = $birthDate ? Carbon::parse($birthDate)->format('d.m.Y') : null;
|
||||||
|
$formattedDateRecipient = $dateRecipient ? Carbon::parse($dateRecipient)->format('d.m.Y') : null;
|
||||||
|
$formattedDateExtract = $dateExtract ? Carbon::parse($dateExtract)->format('d.m.Y') : null;
|
||||||
|
$formattedPostIn = $postIn ? Carbon::parse($postIn)->format('d.m.Y') : null;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'id' => $this->MedicalHistoryID,
|
'id' => $this->resource['id'],
|
||||||
'fullname' => $this->getFullNameAttribute(),
|
'history_type' => $historyType,
|
||||||
'daterecipient' => Carbon::parse($this->DateRecipient)->format('d.m.Y'),
|
'in_archive' => $isFromArchive,
|
||||||
'dateextract' => Carbon::parse($this->DateExtract)->format('d.m.Y'),
|
'is_temporary' => $isTemporary,
|
||||||
'card_num' => $this->archiveInfo->num ?? null,
|
'source' => $this->resource['source'] ?? 'archive',
|
||||||
'status' => $this->archiveInfo->status ?? null,
|
|
||||||
'datearhiv' => $this->whenLoaded('archiveInfo') ? Carbon::parse($this->archiveInfo->post_in)->format('d.m.Y') : null,
|
// Основные данные
|
||||||
'medcardnum' => $this->MedCardNum,
|
'fullname' => $fullName,
|
||||||
'dr' => Carbon::parse($this->BD)->format('d.m.Y'),
|
'family' => $family,
|
||||||
'can_be_issue' => $this->canBeIssued()
|
'name' => $name,
|
||||||
|
'ot' => $ot,
|
||||||
|
'dr' => $formattedBirthDate,
|
||||||
|
'daterecipient' => $formattedDateRecipient,
|
||||||
|
'dateextract' => $formattedDateExtract,
|
||||||
|
|
||||||
|
// Номера карт
|
||||||
|
'medcardnum' => $cardNumber, // MIS номер или FoxPro номер
|
||||||
|
'mis_card_number' => $this->resource['mis_card_number'] ?? null, // Оригинальный MIS номер
|
||||||
|
'foxpro_card_number' => $this->resource['foxpro_card_number'] ?? null, // Оригинальный FoxPro номер
|
||||||
|
'card_num' => $archiveNum, // Архивный номер
|
||||||
|
'datearhiv' => $formattedPostIn,
|
||||||
|
|
||||||
|
// Статус и возможности
|
||||||
|
'status' => $status,
|
||||||
|
'status_id' => $this->resource['status_id'] ?? 0,
|
||||||
|
'can_be_issued' => $this->resource['can_be_issued'] ?? false,
|
||||||
|
'can_add_to_archive' => $this->resource['can_add_to_archive'] ?? false,
|
||||||
|
|
||||||
|
// Дополнительные идентификаторы
|
||||||
|
'mis_history_id' => $this->resource['mis_history_id'] ?? null,
|
||||||
|
'foxpro_history_id' => $this->resource['foxpro_history_id'] ?? null,
|
||||||
|
|
||||||
|
// Дополнительные данные
|
||||||
|
'snils' => $this->resource['snils'] ?? null,
|
||||||
|
'enp' => $this->resource['enp'] ?? null,
|
||||||
|
// 'created_at' => $this->resource->created_at ? Carbon::parse($this->resource->created_at)->format('d.m.Y H:i') : null,
|
||||||
|
// 'updated_at' => $this->resource->updated_at ? Carbon::parse($this->resource->updated_at)->format('d.m.Y H:i') : null,
|
||||||
|
|
||||||
|
// Стили для фронта
|
||||||
|
'row_class' => $this->resource['row_class'] ?? '',
|
||||||
|
'status_color' => $this->getStatusColor($this->resource['status_id'] ?? 0, $isFromArchive),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получение цвета статуса для фронта
|
||||||
|
*/
|
||||||
|
private function getStatusColor(int $statusId, bool $inArchive): string
|
||||||
|
{
|
||||||
|
if (!$inArchive) {
|
||||||
|
return 'warning'; // Желтый для не в архиве
|
||||||
|
}
|
||||||
|
|
||||||
|
return match($statusId) {
|
||||||
|
1 => 'success', // Зеленый для в архиве
|
||||||
|
2 => 'info', // Синий для выдано
|
||||||
|
3, 4 => 'danger', // Красный для утрачено/списано
|
||||||
|
default => 'secondary',
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ class PatientInfoResource extends JsonResource
|
|||||||
public function toArray(Request $request): array
|
public function toArray(Request $request): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => $this->id ?? $this->MedicalHistoryID,
|
'id' => $this->keykarta ?? $this->MedicalHistoryID,
|
||||||
'medcardnum' => $this->medcardnum ?? $this->MedCardNum,
|
'medcardnum' => $this->nkarta ?? $this->MedCardNum,
|
||||||
'family' => $this->family ?? $this->FAMILY,
|
'family' => $this->fam ?? $this->FAMILY,
|
||||||
'name' => $this->name ?? $this->Name,
|
'name' => $this->im ?? $this->Name,
|
||||||
'ot' => $this->ot ?? $this->OT,
|
'ot' => $this->ot ?? $this->OT,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\Mis\SttMedicalHistory as MisMedicalHistory;
|
||||||
|
use App\Models\SI\SttMedicalHistory as SiMedicalHistory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class ArchiveHistory extends Model
|
class ArchiveHistory extends Model
|
||||||
@@ -54,8 +56,9 @@ class ArchiveHistory extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'historyable_type',
|
'keyarhiv',
|
||||||
'historyable_id',
|
'foxpro_history_id',
|
||||||
|
'mis_history_id',
|
||||||
'issue_at',
|
'issue_at',
|
||||||
'return_at',
|
'return_at',
|
||||||
'comment',
|
'comment',
|
||||||
@@ -65,9 +68,19 @@ class ArchiveHistory extends Model
|
|||||||
'has_lost',
|
'has_lost',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function historyable()
|
public function foxproHistory()
|
||||||
{
|
{
|
||||||
return $this->morphTo();
|
return $this->belongsTo(SiMedicalHistory::class, 'keykarta', 'foxpro_history_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function misHistory()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(MisMedicalHistory::class, 'MedicalHistoryID', 'mis_history_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function historyType()
|
||||||
|
{
|
||||||
|
return $this->mis_history_id !== null ? 'mis' : 'foxpro';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function org(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
public function org(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\Mis\SttMedicalHistory as MisMedicalHistory;
|
||||||
|
use App\Models\SI\SttMedicalHistory as SiMedicalHistory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class ArchiveInfo extends Model
|
class ArchiveInfo extends Model
|
||||||
@@ -16,17 +18,30 @@ class ArchiveInfo extends Model
|
|||||||
|
|
||||||
protected $connection = 'pgsql';
|
protected $connection = 'pgsql';
|
||||||
protected $table = 'archive_infos';
|
protected $table = 'archive_infos';
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'historyable_type',
|
'foxpro_history_id',
|
||||||
'historyable_id',
|
'mis_history_id',
|
||||||
'num',
|
'foxpro_num',
|
||||||
|
'mis_num',
|
||||||
|
'archive_num',
|
||||||
'post_in',
|
'post_in',
|
||||||
'status_id'
|
'status_id'
|
||||||
];
|
];
|
||||||
|
|
||||||
public function historyable()
|
public function foxproHistory()
|
||||||
{
|
{
|
||||||
return $this->morphTo();
|
return $this->belongsTo(SiMedicalHistory::class, 'foxpro_history_id', 'keykarta');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function misHistory()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(MisMedicalHistory::class, 'mis_history_id', 'MedicalHistoryID');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function historyType()
|
||||||
|
{
|
||||||
|
return $this->mis_history_id !== null ? 'mis' : 'foxpro';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function status()
|
public function status()
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ class SttMedicalHistory extends Model
|
|||||||
{
|
{
|
||||||
protected $primaryKey = 'MedicalHistoryID';
|
protected $primaryKey = 'MedicalHistoryID';
|
||||||
protected $table = 'stt_medicalhistory';
|
protected $table = 'stt_medicalhistory';
|
||||||
|
protected $keyType = 'string';
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'MedicalHistoryID' => 'string',
|
||||||
|
];
|
||||||
|
|
||||||
public function getFullNameAttribute()
|
public function getFullNameAttribute()
|
||||||
{
|
{
|
||||||
@@ -19,12 +24,12 @@ class SttMedicalHistory extends Model
|
|||||||
|
|
||||||
public function archiveHistory()
|
public function archiveHistory()
|
||||||
{
|
{
|
||||||
return $this->morphMany(ArchiveHistory::class, 'historyable');
|
return $this->hasMany(ArchiveHistory::class, 'mis_history_id', 'MedicalHistoryID');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function archiveInfo()
|
public function archiveInfo()
|
||||||
{
|
{
|
||||||
return $this->morphOne(ArchiveInfo::class, 'historyable');
|
return $this->hasOne(ArchiveInfo::class, 'mis_history_id', 'MedicalHistoryID');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,7 +46,6 @@ class SttMedicalHistory extends Model
|
|||||||
|
|
||||||
$hasNotBadStatus = $this->archiveInfo()
|
$hasNotBadStatus = $this->archiveInfo()
|
||||||
->whereNotNull('status_id')
|
->whereNotNull('status_id')
|
||||||
->whereNot('status_id', 1)
|
|
||||||
->whereNot('status_id', 3)
|
->whereNot('status_id', 3)
|
||||||
->whereNot('status_id', 4)
|
->whereNot('status_id', 4)
|
||||||
->exists();
|
->exists();
|
||||||
|
|||||||
@@ -8,36 +8,43 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
|
|
||||||
class SttMedicalHistory extends Model
|
class SttMedicalHistory extends Model
|
||||||
{
|
{
|
||||||
protected $table = 'si_stt_patients';
|
protected $table = 'foxpro_original_patient';
|
||||||
|
protected $primaryKey = 'keykarta';
|
||||||
protected $connection = 'pgsql';
|
protected $connection = 'pgsql';
|
||||||
|
protected $keyType = 'string';
|
||||||
|
public $incrementing = false;
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'keykarta' => 'string',
|
||||||
|
];
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'family', // Фамилия
|
'fam', // Фамилия
|
||||||
'name', // Имя
|
'im', // Имя
|
||||||
'ot', // Отчество
|
'ot', // Отчество
|
||||||
'daterecipient', // Д. пост. (mpostdate)
|
'mpostdate', // Д. пост. (mpostdate)
|
||||||
'dateextract', // Д. вып. (menddate)
|
'menddate', // Д. вып. (menddate)
|
||||||
'narhiv', // № в архиве
|
'narhiv', // № в архиве
|
||||||
'datearhiv', // Д. архив
|
'datearhiv', // Д. архив
|
||||||
'statgod', // Год нахождения в стационаре
|
'snils', // Год нахождения в стационаре
|
||||||
'enp', // ЕНП
|
'enp', // ЕНП
|
||||||
'medcardnum', // № карты
|
'nkarta', // № карты
|
||||||
'dr', // ДР
|
'dr', // ДР
|
||||||
];
|
];
|
||||||
|
|
||||||
public function getFullNameAttribute()
|
public function getFullNameAttribute()
|
||||||
{
|
{
|
||||||
return "$this->family $this->name $this->ot";
|
return "$this->fam $this->im $this->ot";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function archiveHistory()
|
public function archiveHistory()
|
||||||
{
|
{
|
||||||
return $this->morphMany(ArchiveHistory::class, 'historyable');
|
return $this->hasMany(ArchiveHistory::class, 'foxpro_history_id', 'keykarta');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function archiveInfo()
|
public function archiveInfo()
|
||||||
{
|
{
|
||||||
return $this->morphOne(ArchiveInfo::class, 'historyable');
|
return $this->hasOne(ArchiveInfo::class, 'foxpro_history_id', 'keykarta');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
146
app/Services/ArchiveSearchService.php
Normal file
146
app/Services/ArchiveSearchService.php
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Models\ArchiveInfo;
|
||||||
|
use App\Models\Mis\SttMedicalHistory as MisMedicalHistory;
|
||||||
|
use App\Models\SI\SttMedicalHistory as SiMedicalHistory;
|
||||||
|
|
||||||
|
class ArchiveSearchService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Поиск карты по номеру
|
||||||
|
*/
|
||||||
|
public function searchByNumber(string $searchText): ?ArchiveInfo
|
||||||
|
{
|
||||||
|
if (!is_numeric($searchText)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Проверяем, есть ли запись в archive_infos
|
||||||
|
$archiveInfo = $this->searchInArchiveInfos($searchText);
|
||||||
|
if ($archiveInfo) {
|
||||||
|
return $archiveInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Если нет в archive_infos, ищем в MIS
|
||||||
|
$misHistory = $this->searchInMis($searchText);
|
||||||
|
if ($misHistory) {
|
||||||
|
// Создаем запись в archive_infos для MIS карты
|
||||||
|
return $this->createArchiveInfoForMis($misHistory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Если нет в MIS, ищем в FoxPro
|
||||||
|
$foxproHistory = $this->searchInFoxPro($searchText);
|
||||||
|
if ($foxproHistory) {
|
||||||
|
// Создаем запись в archive_infos для FoxPro карты
|
||||||
|
return $this->createArchiveInfoForFoxPro($foxproHistory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поиск по ФИО или другим критериям
|
||||||
|
*/
|
||||||
|
public function searchByName(string $searchText): array
|
||||||
|
{
|
||||||
|
// Поиск в MIS
|
||||||
|
$misResults = MisMedicalHistory::query()
|
||||||
|
->where(function($query) use ($searchText) {
|
||||||
|
$query->whereRaw("CONCAT(\"FAMILY\", ' ', \"Name\", ' ', COALESCE(\"OT\", '')) ILIKE ?", ["$searchText%"])
|
||||||
|
->orWhere('FAMILY', 'ILIKE', "$searchText%")
|
||||||
|
->orWhere('Name', 'ILIKE', "$searchText%")
|
||||||
|
->orWhere('OT', 'ILIKE', "$searchText%");
|
||||||
|
})
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return $misResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поиск в archive_infos
|
||||||
|
*/
|
||||||
|
private function searchInArchiveInfos(string $cardNumber): ?ArchiveInfo
|
||||||
|
{
|
||||||
|
return ArchiveInfo::query()
|
||||||
|
->where('mis_num', $cardNumber)
|
||||||
|
->orWhere('foxpro_num', $cardNumber)
|
||||||
|
->with(['misHistory', 'foxproHistory'])
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поиск в MIS
|
||||||
|
*/
|
||||||
|
private function searchInMis(string $cardNumber): ?MisMedicalHistory
|
||||||
|
{
|
||||||
|
return MisMedicalHistory::where('MedCardNum', $cardNumber)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поиск в FoxPro
|
||||||
|
*/
|
||||||
|
private function searchInFoxPro(string $cardNumber): ?SiMedicalHistory
|
||||||
|
{
|
||||||
|
return SiMedicalHistory::where('nkarta', $cardNumber)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Создание записи в archive_infos для MIS карты
|
||||||
|
*/
|
||||||
|
private function createArchiveInfoForMis(MisMedicalHistory $misHistory): ArchiveInfo
|
||||||
|
{
|
||||||
|
// Проверяем, нет ли уже записи
|
||||||
|
$existingArchiveInfo = ArchiveInfo::where('mis_history_id', $misHistory->MedicalHistoryID)->first();
|
||||||
|
if ($existingArchiveInfo) {
|
||||||
|
return $existingArchiveInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ищем связанную запись в FoxPro
|
||||||
|
$foxproHistory = SiMedicalHistory::where('snils', $misHistory->SS)
|
||||||
|
->where('menddate', $misHistory->DateExtract)
|
||||||
|
->where('dr', '!=', $misHistory->BD)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
// Создаем запись
|
||||||
|
return ArchiveInfo::create([
|
||||||
|
'mis_history_id' => $misHistory->MedicalHistoryID,
|
||||||
|
'mis_num' => $misHistory->MedCardNum,
|
||||||
|
'foxpro_history_id' => $foxproHistory?->keykarta,
|
||||||
|
'foxpro_num' => $foxproHistory?->nkarta,
|
||||||
|
'archive_num' => $foxproHistory?->narhiv,
|
||||||
|
'post_in' => $foxproHistory?->datearhiv,
|
||||||
|
'status_id' => 2, // Статус по умолчанию
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Создание записи в archive_infos для FoxPro карты
|
||||||
|
*/
|
||||||
|
private function createArchiveInfoForFoxPro(SiMedicalHistory $foxproHistory): ArchiveInfo
|
||||||
|
{
|
||||||
|
// Проверяем, нет ли уже записи
|
||||||
|
$existingArchiveInfo = ArchiveInfo::where('foxpro_history_id', $foxproHistory->keykarta)->first();
|
||||||
|
if ($existingArchiveInfo) {
|
||||||
|
return $existingArchiveInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ищем связанную запись в MIS
|
||||||
|
$misHistory = MisMedicalHistory::where('SS', $foxproHistory->snils)
|
||||||
|
->where('DateExtract', $foxproHistory->menddate)
|
||||||
|
->where('BD', '!=', $foxproHistory->dr)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
// Создаем запись
|
||||||
|
return ArchiveInfo::create([
|
||||||
|
'foxpro_history_id' => $foxproHistory->keykarta,
|
||||||
|
'foxpro_num' => $foxproHistory->nkarta,
|
||||||
|
'archive_num' => $foxproHistory->narhiv,
|
||||||
|
'post_in' => $foxproHistory->datearhiv,
|
||||||
|
'mis_history_id' => $misHistory?->MedicalHistoryID,
|
||||||
|
'mis_num' => $misHistory?->MedCardNum,
|
||||||
|
'status_id' => 2, // Статус по умолчанию
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
"laravel/tinker": "^2.10.1"
|
"laravel/tinker": "^2.10.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"barryvdh/laravel-debugbar": "^3.16",
|
||||||
"fakerphp/faker": "^1.23",
|
"fakerphp/faker": "^1.23",
|
||||||
"laravel/pail": "^1.2.2",
|
"laravel/pail": "^1.2.2",
|
||||||
"laravel/pint": "^1.24",
|
"laravel/pint": "^1.24",
|
||||||
|
|||||||
161
composer.lock
generated
161
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "4ecf76c8e987c4f4186a17e150248317",
|
"content-hash": "d35c2af4354943a6ab7e9b9ca3c4fed0",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
@@ -6136,6 +6136,91 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "barryvdh/laravel-debugbar",
|
||||||
|
"version": "v3.16.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/barryvdh/laravel-debugbar.git",
|
||||||
|
"reference": "730dbf8bf41f5691e026dd771e64dd54ad1b10b3"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/730dbf8bf41f5691e026dd771e64dd54ad1b10b3",
|
||||||
|
"reference": "730dbf8bf41f5691e026dd771e64dd54ad1b10b3",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/routing": "^10|^11|^12",
|
||||||
|
"illuminate/session": "^10|^11|^12",
|
||||||
|
"illuminate/support": "^10|^11|^12",
|
||||||
|
"php": "^8.1",
|
||||||
|
"php-debugbar/php-debugbar": "^2.2.4",
|
||||||
|
"symfony/finder": "^6|^7"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^1.3.3",
|
||||||
|
"orchestra/testbench-dusk": "^7|^8|^9|^10",
|
||||||
|
"phpunit/phpunit": "^9.5.10|^10|^11",
|
||||||
|
"squizlabs/php_codesniffer": "^3.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"aliases": {
|
||||||
|
"Debugbar": "Barryvdh\\Debugbar\\Facades\\Debugbar"
|
||||||
|
},
|
||||||
|
"providers": [
|
||||||
|
"Barryvdh\\Debugbar\\ServiceProvider"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.16-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/helpers.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Barryvdh\\Debugbar\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP Debugbar integration for Laravel",
|
||||||
|
"keywords": [
|
||||||
|
"debug",
|
||||||
|
"debugbar",
|
||||||
|
"dev",
|
||||||
|
"laravel",
|
||||||
|
"profiler",
|
||||||
|
"webprofiler"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/barryvdh/laravel-debugbar/issues",
|
||||||
|
"source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.16.2"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://fruitcake.nl",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/barryvdh",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-12-03T14:52:46+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "brianium/paratest",
|
"name": "brianium/paratest",
|
||||||
"version": "v7.14.2",
|
"version": "v7.14.2",
|
||||||
@@ -7614,6 +7699,80 @@
|
|||||||
},
|
},
|
||||||
"time": "2022-02-21T01:04:05+00:00"
|
"time": "2022-02-21T01:04:05+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "php-debugbar/php-debugbar",
|
||||||
|
"version": "v2.2.5",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-debugbar/php-debugbar.git",
|
||||||
|
"reference": "c5dce08e98dd101c771e55949fd89124b216271d"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/c5dce08e98dd101c771e55949fd89124b216271d",
|
||||||
|
"reference": "c5dce08e98dd101c771e55949fd89124b216271d",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^8.1",
|
||||||
|
"psr/log": "^1|^2|^3",
|
||||||
|
"symfony/var-dumper": "^5.4|^6.4|^7.3|^8.0"
|
||||||
|
},
|
||||||
|
"replace": {
|
||||||
|
"maximebf/debugbar": "self.version"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"dbrekelmans/bdi": "^1",
|
||||||
|
"phpunit/phpunit": "^10",
|
||||||
|
"symfony/browser-kit": "^6.0|7.0",
|
||||||
|
"symfony/panther": "^1|^2.1",
|
||||||
|
"twig/twig": "^3.11.2"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"kriswallsmith/assetic": "The best way to manage assets",
|
||||||
|
"monolog/monolog": "Log using Monolog",
|
||||||
|
"predis/predis": "Redis storage"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "2.2-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"DebugBar\\": "src/DebugBar/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Maxime Bouroumeau-Fuseau",
|
||||||
|
"email": "maxime.bouroumeau@gmail.com",
|
||||||
|
"homepage": "http://maximebf.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Debug bar in the browser for php application",
|
||||||
|
"homepage": "https://github.com/php-debugbar/php-debugbar",
|
||||||
|
"keywords": [
|
||||||
|
"debug",
|
||||||
|
"debug bar",
|
||||||
|
"debugbar",
|
||||||
|
"dev"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/php-debugbar/php-debugbar/issues",
|
||||||
|
"source": "https://github.com/php-debugbar/php-debugbar/tree/v2.2.5"
|
||||||
|
},
|
||||||
|
"time": "2025-12-21T08:50:08+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/reflection-common",
|
"name": "phpdocumentor/reflection-common",
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'timezone' => 'UTC',
|
'timezone' => 'Asia/Yakutsk',
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ return new class extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create('archive_histories', function (Blueprint $table) {
|
Schema::create('archive_histories', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->morphs('historyable');
|
$table->string('keyarhiv')->nullable();
|
||||||
|
$table->string('foxpro_history_id')->nullable();
|
||||||
|
$table->bigInteger('mis_history_id')->nullable();
|
||||||
$table->timestamp('issue_at');
|
$table->timestamp('issue_at');
|
||||||
$table->timestamp('return_at')->nullable();
|
$table->timestamp('return_at')->nullable();
|
||||||
$table->text('comment')->nullable();
|
$table->text('comment')->nullable();
|
||||||
|
|||||||
@@ -13,8 +13,11 @@ return new class extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create('archive_infos', function (Blueprint $table) {
|
Schema::create('archive_infos', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->morphs('historyable');
|
$table->string('foxpro_history_id')->nullable();
|
||||||
$table->string('num');
|
$table->bigInteger('mis_history_id')->nullable();
|
||||||
|
$table->string('foxpro_num')->nullable();
|
||||||
|
$table->string('mis_num')->nullable();
|
||||||
|
$table->string('archive_num');
|
||||||
$table->date('post_in');
|
$table->date('post_in');
|
||||||
$table->foreignIdFor(\App\Models\ArchiveStatus::class, 'status_id')->default(1);
|
$table->foreignIdFor(\App\Models\ArchiveStatus::class, 'status_id')->default(1);
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|||||||
21
database/seeders/OrgSeeder.php
Normal file
21
database/seeders/OrgSeeder.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\Org;
|
||||||
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class OrgSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
Org::create([
|
||||||
|
'code' => '0',
|
||||||
|
'name' => 'Неизвестно'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,51 +16,15 @@ export const useMedicalHistoryFilter = (initialFilters = {}) => {
|
|||||||
page_size: initialFilters?.page_size || 50,
|
page_size: initialFilters?.page_size || 50,
|
||||||
sort_by: initialFilters?.sort_by || 'dateextract',
|
sort_by: initialFilters?.sort_by || 'dateextract',
|
||||||
sort_order: initialFilters?.sort_order || 'desc',
|
sort_order: initialFilters?.sort_order || 'desc',
|
||||||
view_type: initialFilters?.view_type || 'si',
|
|
||||||
status: initialFilters?.status || null,
|
status: initialFilters?.status || null,
|
||||||
database: initialFilters?.database || 'separate', // НОВЫЙ ПАРАМЕТР: postgresql, mssql, smart, separate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Метаданные для разных типов данных
|
// Метаданные для разных типов данных
|
||||||
const meta = computed(() => {
|
const meta = computed(() => {
|
||||||
const cards = page.props.cards
|
return page.props.cards.meta
|
||||||
|
|
||||||
// Для раздельного поиска
|
|
||||||
if (filtersRef.value.database === 'separate') {
|
|
||||||
return {
|
|
||||||
si: cards.si.meta || {},
|
|
||||||
mis: cards.mis.meta || {},
|
|
||||||
stats: cards.stats || {},
|
|
||||||
}
|
|
||||||
} else if (filtersRef.value.database === 'mis') {
|
|
||||||
return {
|
|
||||||
mis: cards.mis?.meta
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
si: cards.si?.meta
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const databaseStats = computed(() => page.props.databaseStats || {})
|
|
||||||
|
|
||||||
// Статистика по базам
|
|
||||||
const databaseInfo = computed(() => ({
|
|
||||||
postgresql: {
|
|
||||||
count: databaseStats.value.postgresql?.total || 0,
|
|
||||||
label: 'PostgreSQL',
|
|
||||||
color: 'blue',
|
|
||||||
description: 'Основной архив'
|
|
||||||
},
|
|
||||||
mssql: {
|
|
||||||
count: databaseStats.value.mssql?.total || 0,
|
|
||||||
label: 'MSSQL',
|
|
||||||
color: 'purple',
|
|
||||||
description: 'Исторический архив'
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
|
|
||||||
// Форматирование даты для URL
|
// Форматирование даты для URL
|
||||||
const formatDateForUrl = (date) => {
|
const formatDateForUrl = (date) => {
|
||||||
@@ -81,8 +45,6 @@ export const useMedicalHistoryFilter = (initialFilters = {}) => {
|
|||||||
page_size: filtersRef.value.page_size,
|
page_size: filtersRef.value.page_size,
|
||||||
sort_by: filtersRef.value.sort_by,
|
sort_by: filtersRef.value.sort_by,
|
||||||
sort_order: filtersRef.value.sort_order,
|
sort_order: filtersRef.value.sort_order,
|
||||||
view_type: filtersRef.value.view_type,
|
|
||||||
database: filtersRef.value.database,
|
|
||||||
status: filtersRef.value.status
|
status: filtersRef.value.status
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,10 +90,6 @@ export const useMedicalHistoryFilter = (initialFilters = {}) => {
|
|||||||
debouncedSearch(value)
|
debouncedSearch(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDatabaseChange = (database) => {
|
|
||||||
applyFilters({ database, page: 1 }, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Конвертация строки даты в timestamp для NaiveUI
|
// Конвертация строки даты в timestamp для NaiveUI
|
||||||
const convertToTimestamp = (dateString) => {
|
const convertToTimestamp = (dateString) => {
|
||||||
if (!dateString) return null
|
if (!dateString) return null
|
||||||
@@ -186,10 +144,6 @@ export const useMedicalHistoryFilter = (initialFilters = {}) => {
|
|||||||
applyFilters({ page_size: size, page: 1 })
|
applyFilters({ page_size: size, page: 1 })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleViewTypeChange = (view_type) => {
|
|
||||||
applyFilters({ view_type, page: 1 })
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSortChange = (sorter) => {
|
const handleSortChange = (sorter) => {
|
||||||
applyFilters({
|
applyFilters({
|
||||||
sort_by: sorter.columnKey,
|
sort_by: sorter.columnKey,
|
||||||
@@ -213,8 +167,6 @@ export const useMedicalHistoryFilter = (initialFilters = {}) => {
|
|||||||
page_size: 15,
|
page_size: 15,
|
||||||
sort_by: 'dateextract',
|
sort_by: 'dateextract',
|
||||||
sort_order: 'desc',
|
sort_order: 'desc',
|
||||||
view_type: 'archive',
|
|
||||||
database: 'postgresql',
|
|
||||||
}
|
}
|
||||||
dateRange.value = [null, null]
|
dateRange.value = [null, null]
|
||||||
applyFilters({}, true)
|
applyFilters({}, true)
|
||||||
@@ -270,22 +222,6 @@ export const useMedicalHistoryFilter = (initialFilters = {}) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Фильтр по базе данных
|
|
||||||
if (filtersRef.value.database) {
|
|
||||||
const dbLabel = {
|
|
||||||
postgresql: 'PostgreSQL',
|
|
||||||
mssql: 'MSSQL',
|
|
||||||
smart: 'Умный поиск',
|
|
||||||
separate: 'Раздельно'
|
|
||||||
}[filtersRef.value.database] || filtersRef.value.database
|
|
||||||
|
|
||||||
active.push({
|
|
||||||
key: 'database',
|
|
||||||
label: `База: ${dbLabel}`,
|
|
||||||
icon: 'database'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return active
|
return active
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -341,12 +277,8 @@ export const useMedicalHistoryFilter = (initialFilters = {}) => {
|
|||||||
activeFilters,
|
activeFilters,
|
||||||
dateRange,
|
dateRange,
|
||||||
searchValue,
|
searchValue,
|
||||||
databaseInfo,
|
|
||||||
databaseStats,
|
|
||||||
|
|
||||||
// Обработчики
|
// Обработчики
|
||||||
handleDatabaseChange,
|
|
||||||
handleViewTypeChange,
|
|
||||||
handleSearch,
|
handleSearch,
|
||||||
handleDateRangeChange,
|
handleDateRangeChange,
|
||||||
handlePageChange,
|
handlePageChange,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { NLayout, NH1, NLayoutSider, NFlex, NButton, NConfigProvider, ruRU, dateRuRU } from "naive-ui";
|
import {NLayout, NH1, NLayoutSider, NFlex, NButton, NConfigProvider, ruRU, dateRuRU, darkTheme} from "naive-ui";
|
||||||
import SideMenu from "./Components/SideMenu.vue";
|
import SideMenu from "./Components/SideMenu.vue";
|
||||||
import { generate } from '@arco-design/color'
|
import { generate } from '@arco-design/color'
|
||||||
|
|
||||||
@@ -7,17 +7,27 @@ const colors = generate('#EC6608', {
|
|||||||
list: true,
|
list: true,
|
||||||
})
|
})
|
||||||
const themeOverrides = {
|
const themeOverrides = {
|
||||||
common: {
|
// common: {
|
||||||
primaryColor: colors[5],
|
// primaryColor: colors[5],
|
||||||
primaryColorHover: colors[4],
|
// primaryColorHover: colors[4],
|
||||||
primaryColorSuppl: colors[4],
|
// primaryColorSuppl: colors[4],
|
||||||
primaryColorPressed: colors[6],
|
// primaryColorPressed: colors[6],
|
||||||
|
// },
|
||||||
|
Modal: {
|
||||||
|
peers: {
|
||||||
|
Dialog: {
|
||||||
|
borderRadius: '8px'
|
||||||
|
},
|
||||||
|
Card: {
|
||||||
|
borderRadius: '8px'
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NConfigProvider :theme-overrides="themeOverrides" :locale="ruRU" :date-locale="dateRuRU">
|
<NConfigProvider :theme="darkTheme" :theme-overrides="themeOverrides" :locale="ruRU" :date-locale="dateRuRU">
|
||||||
<NLayout class="h-screen">
|
<NLayout class="h-screen">
|
||||||
<NLayout position="absolute" content-class="p-6 relative" :native-scrollbar="false">
|
<NLayout position="absolute" content-class="p-6 relative" :native-scrollbar="false">
|
||||||
<!-- <NLayoutSider-->
|
<!-- <NLayoutSider-->
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {useNotification} from "../../../Composables/useNotification.js";
|
|||||||
|
|
||||||
const open = defineModel('open')
|
const open = defineModel('open')
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
patientId: {
|
patientInfo: {
|
||||||
type: Number,
|
type: Number,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -18,10 +18,10 @@ const loading = ref(true)
|
|||||||
const patient = ref({})
|
const patient = ref({})
|
||||||
const showArchiveHistoryModal = ref(false)
|
const showArchiveHistoryModal = ref(false)
|
||||||
const selectedArchiveHistoryId = ref(null)
|
const selectedArchiveHistoryId = ref(null)
|
||||||
const selectedArchiveHistoryType = ref(null)
|
const selectedArchiveHistoryType = ref(props.patientInfo.type)
|
||||||
const isCreateNewArchiveHistoryModal = ref(false)
|
const isCreateNewArchiveHistoryModal = ref(false)
|
||||||
const archiveInfo = ref({
|
const archiveInfo = ref({
|
||||||
id: props.patientId,
|
id: props.patientInfo.id,
|
||||||
num: null,
|
num: null,
|
||||||
post_in: null,
|
post_in: null,
|
||||||
status: null
|
status: null
|
||||||
@@ -30,7 +30,7 @@ const emits = defineEmits(['historyUpdated', 'closeWithoutSave'])
|
|||||||
|
|
||||||
const onResetData = () => {
|
const onResetData = () => {
|
||||||
archiveInfo.value = {
|
archiveInfo.value = {
|
||||||
id: props.patientId,
|
id: props.patientInfo.id,
|
||||||
num: null,
|
num: null,
|
||||||
post_in: null,
|
post_in: null,
|
||||||
status: null
|
status: null
|
||||||
@@ -47,16 +47,16 @@ const patientData = ref({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const loadPatientData = async () => {
|
const loadPatientData = async () => {
|
||||||
if (!props.patientId) return
|
if (!props.patientInfo.id) return
|
||||||
|
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
await axios.get(`/api/si/patients/${props.patientId}?view_type=${filtersRef.value.view_type}`).then(res => {
|
await axios.get(`/api/si/patients/${props.patientInfo.id}?view_type=${props.patientInfo.type}`).then(res => {
|
||||||
patient.value = res.data
|
patient.value = res.data
|
||||||
patientData.value = res.data.info
|
patientData.value = res.data.info
|
||||||
archiveInfo.value = res.data.archiveInfo ?? {
|
archiveInfo.value = res.data.archiveInfo ?? {
|
||||||
historyable_type: res.data.historyable_type,
|
// historyable_type: res.data.historyable_type,
|
||||||
id: props.patientId,
|
id: props.patientInfo.id,
|
||||||
num: null,
|
num: null,
|
||||||
post_in: null,
|
post_in: null,
|
||||||
status: null,
|
status: null,
|
||||||
@@ -73,12 +73,12 @@ const loadPatientData = async () => {
|
|||||||
const onShowArchiveHistoryModal = (id) => {
|
const onShowArchiveHistoryModal = (id) => {
|
||||||
if (id === null) {
|
if (id === null) {
|
||||||
isCreateNewArchiveHistoryModal.value = true
|
isCreateNewArchiveHistoryModal.value = true
|
||||||
selectedArchiveHistoryId.value = props.patientId
|
selectedArchiveHistoryId.value = props.patientInfo.id
|
||||||
} else {
|
} else {
|
||||||
isCreateNewArchiveHistoryModal.value = false
|
isCreateNewArchiveHistoryModal.value = false
|
||||||
selectedArchiveHistoryId.value = id
|
selectedArchiveHistoryId.value = id
|
||||||
}
|
}
|
||||||
selectedArchiveHistoryType.value = archiveInfo.value.historyable_type
|
selectedArchiveHistoryType.value = props.patientInfo.type
|
||||||
showArchiveHistoryModal.value = true
|
showArchiveHistoryModal.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ const onUpdateHistory = async ({data}) => {
|
|||||||
}
|
}
|
||||||
emits('historyUpdated', {
|
emits('historyUpdated', {
|
||||||
data: updatedData,
|
data: updatedData,
|
||||||
patientId: props.patientId
|
patientId: props.patientInfo.id
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,14 +130,14 @@ const hasCreateNew = computed(() => archiveInfo.value === null)
|
|||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
await axios.post(`/api/archive/histories/info/${props.patientId}`, archiveInfo.value).then(res => {
|
await axios.post(`/api/archive/histories/info/${props.patientInfo.id}`, archiveInfo.value).then(res => {
|
||||||
// onCloseWithoutSave()
|
// onCloseWithoutSave()
|
||||||
const updatedData = {
|
const updatedData = {
|
||||||
status: archiveInfo.value.status,
|
status: archiveInfo.value.status,
|
||||||
}
|
}
|
||||||
emits('historyUpdated', {
|
emits('historyUpdated', {
|
||||||
data: updatedData,
|
data: updatedData,
|
||||||
patientId: props.patientId
|
patientId: props.patientInfo.id
|
||||||
})
|
})
|
||||||
open.value = false
|
open.value = false
|
||||||
})
|
})
|
||||||
@@ -151,7 +151,7 @@ const onSubmit = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Наблюдаем за изменением patientId
|
// Наблюдаем за изменением patientId
|
||||||
watch(() => props.patientId, async (newId) => {
|
watch(() => props.patientInfo, async (newId) => {
|
||||||
if (newId) {
|
if (newId) {
|
||||||
await loadPatientData()
|
await loadPatientData()
|
||||||
}
|
}
|
||||||
@@ -177,6 +177,11 @@ watch(() => props.patientId, async (newId) => {
|
|||||||
<NFormItem label="Дата поступления карты в архив">
|
<NFormItem label="Дата поступления карты в архив">
|
||||||
<NDatePicker v-model:value="archiveInfo.post_in" format="dd.MM.yyyy" />
|
<NDatePicker v-model:value="archiveInfo.post_in" format="dd.MM.yyyy" />
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
|
<NFormItem label="№ карты в МИС / СофтИнфо">
|
||||||
|
<NTag :bordered="false" round class="w-full justify-center">
|
||||||
|
{{ archiveInfo.mis_num }} / {{ archiveInfo.foxpro_num }}
|
||||||
|
</NTag>
|
||||||
|
</NFormItem>
|
||||||
</NForm>
|
</NForm>
|
||||||
</NFlex>
|
</NFlex>
|
||||||
<NButton @click="onShowArchiveHistoryModal(null)" :disabled="!patientData.can_be_issued">
|
<NButton @click="onShowArchiveHistoryModal(null)" :disabled="!patientData.can_be_issued">
|
||||||
@@ -202,7 +207,7 @@ watch(() => props.patientId, async (newId) => {
|
|||||||
<NSpin :show="true" />
|
<NSpin :show="true" />
|
||||||
</div>
|
</div>
|
||||||
</NModal>
|
</NModal>
|
||||||
<ArchiveHistoryMoveModal @history-updated="onUpdateHistory" @close-without-save="selectedArchiveHistoryId = null" :is-create-new="isCreateNewArchiveHistoryModal" v-model:open="showArchiveHistoryModal" :active-history-type="selectedArchiveHistoryType" :archive-history-id="selectedArchiveHistoryId" />
|
<ArchiveHistoryMoveModal @history-updated="onUpdateHistory" @close-without-save="selectedArchiveHistoryId = null" :is-create-new="isCreateNewArchiveHistoryModal" v-model:open="showArchiveHistoryModal" :type="selectedArchiveHistoryType" :archive-history-id="selectedArchiveHistoryId" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ import {ref, watch} from "vue";
|
|||||||
import {router} from "@inertiajs/vue3";
|
import {router} from "@inertiajs/vue3";
|
||||||
const open = defineModel('open')
|
const open = defineModel('open')
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
type: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
archiveHistoryId: {
|
archiveHistoryId: {
|
||||||
type: Number
|
type: Number
|
||||||
},
|
},
|
||||||
activeHistoryType: {
|
|
||||||
type: String
|
|
||||||
},
|
|
||||||
isCreateNew: {
|
isCreateNew: {
|
||||||
type: Boolean
|
type: Boolean
|
||||||
}
|
}
|
||||||
@@ -31,8 +31,7 @@ const emits = defineEmits(['closeWithoutSave', 'historyUpdated'])
|
|||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const archiveHistory = ref({
|
const archiveHistory = ref({
|
||||||
historyable_id: props.archiveHistoryId,
|
type: props.type,
|
||||||
historyable_type: props.activeHistoryType,
|
|
||||||
issue_at: null,
|
issue_at: null,
|
||||||
org_id: null,
|
org_id: null,
|
||||||
return_at: null,
|
return_at: null,
|
||||||
@@ -45,8 +44,8 @@ const orgs = ref([])
|
|||||||
|
|
||||||
const onResetData = () => {
|
const onResetData = () => {
|
||||||
archiveHistory.value = {
|
archiveHistory.value = {
|
||||||
historyable_id: props.archiveHistoryId,
|
archive_info_id: props.archiveHistoryId,
|
||||||
historyable_type: props.activeHistoryType,
|
type: props.type,
|
||||||
issue_at: null,
|
issue_at: null,
|
||||||
org_id: null,
|
org_id: null,
|
||||||
return_at: null,
|
return_at: null,
|
||||||
@@ -114,7 +113,7 @@ watch(() => props.archiveHistoryId, async (newId) => {
|
|||||||
<template>
|
<template>
|
||||||
<NModal v-model:show="open" preset="card" class="max-w-2xl relative" closable @close="onCloseWithoutSave">
|
<NModal v-model:show="open" preset="card" class="max-w-2xl relative" closable @close="onCloseWithoutSave">
|
||||||
<template #header>
|
<template #header>
|
||||||
{{ archiveHistoryId === null ? 'Добавить' : 'Редактировать' }} запись выдачи
|
{{ isCreateNew ? 'Добавить' : 'Редактировать' }} запись выдачи
|
||||||
</template>
|
</template>
|
||||||
<NForm>
|
<NForm>
|
||||||
<NFormItem label="Дата выдачи">
|
<NFormItem label="Дата выдачи">
|
||||||
|
|||||||
@@ -90,56 +90,37 @@ const columns = ref([
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
const showArchiveHistoryModal = ref(false)
|
const showArchiveHistoryModal = ref(false)
|
||||||
const selectedPatientId = ref(null)
|
const selectedPatientInfo = ref({})
|
||||||
const rowProps = (row) => ({
|
const rowProps = (row) => ({
|
||||||
onDblclick: () => {
|
onDblclick: () => {
|
||||||
selectedPatientId.value = row.id
|
selectedPatientInfo.value = {id: row.id, type: row.history_type}
|
||||||
showArchiveHistoryModal.value = true
|
showArchiveHistoryModal.value = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const pagination = computed(() => {
|
const pagination = computed(() => {
|
||||||
if (filtersRef.value.view_type === 'si') {
|
return {
|
||||||
return {
|
page: meta.value.current_page || 1,
|
||||||
page: meta.value.si.current_page || 1,
|
pageCount: meta.value.last_page || 1,
|
||||||
pageCount: meta.value.si.last_page || 1,
|
pageSize: meta.value.per_page || 15,
|
||||||
pageSize: meta.value.si.per_page || 15,
|
itemCount: meta.value.total || 0,
|
||||||
itemCount: meta.value.si.total || 0,
|
pageSizes: [15, 50, 100],
|
||||||
pageSizes: [15, 50, 100],
|
showSizePicker: true,
|
||||||
showSizePicker: true,
|
prefix({ itemCount }) {
|
||||||
prefix({ itemCount }) {
|
return `Всего карт ${itemCount}`
|
||||||
return `Всего карт ${itemCount}.`
|
},
|
||||||
},
|
onUpdatePage: (page) => {
|
||||||
onUpdatePage: (page) => {
|
handlePageChange(page)
|
||||||
handlePageChange(page)
|
},
|
||||||
},
|
onUpdatePageSize: handlePageSizeChange
|
||||||
onUpdatePageSize: handlePageSizeChange
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
page: meta.value.mis.current_page || 1,
|
|
||||||
pageCount: meta.value.mis.last_page || 1,
|
|
||||||
pageSize: meta.value.mis.per_page || 15,
|
|
||||||
itemCount: meta.value.mis.total || 0,
|
|
||||||
pageSizes: [15, 50, 100],
|
|
||||||
showSizePicker: true,
|
|
||||||
prefix({ itemCount }) {
|
|
||||||
return `Всего карт ${itemCount}.`
|
|
||||||
},
|
|
||||||
onUpdatePage: (page) => {
|
|
||||||
handlePageChange(page)
|
|
||||||
},
|
|
||||||
onUpdatePageSize: handlePageSizeChange
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const onCloseWithoutSave = () => {
|
const onCloseWithoutSave = () => {
|
||||||
selectedPatientId.value = null
|
selectedPatientInfo.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
const onUpdateHistory = ({data, patientId}) => {
|
const onUpdateHistory = ({data, patientId}) => {
|
||||||
console.log(data)
|
|
||||||
if (dataTable.value.length > 0) {
|
if (dataTable.value.length > 0) {
|
||||||
let needUpdateItem = dataTable.value.findIndex(itm => itm.id === patientId)
|
let needUpdateItem = dataTable.value.findIndex(itm => itm.id === patientId)
|
||||||
dataTable.value[needUpdateItem] = {
|
dataTable.value[needUpdateItem] = {
|
||||||
@@ -156,7 +137,7 @@ watch(() => props.data, (newData) => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NDataTable remote striped :loading="isLoading" :row-props="rowProps" :columns="columns" :pagination="pagination" :max-height="maxHeight" size="small" :min-height="minHeight" :data="dataTable" />
|
<NDataTable remote striped :loading="isLoading" :row-props="rowProps" :columns="columns" :pagination="pagination" :max-height="maxHeight" size="small" :min-height="minHeight" :data="dataTable" />
|
||||||
<ArchiveHistoryModal v-model:open="showArchiveHistoryModal" :patient-id="selectedPatientId" @history-updated="onUpdateHistory" @close-without-save="onCloseWithoutSave" />
|
<ArchiveHistoryModal v-model:open="showArchiveHistoryModal" :patient-info="selectedPatientInfo" @history-updated="onUpdateHistory" @close-without-save="onCloseWithoutSave" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -2,10 +2,8 @@
|
|||||||
import AppLayout from "../../Layouts/AppLayout.vue"
|
import AppLayout from "../../Layouts/AppLayout.vue"
|
||||||
import TableCards from './DataTable/Index.vue'
|
import TableCards from './DataTable/Index.vue'
|
||||||
import { NInput, NFlex, NDivider, NDatePicker, NSpace, NFormItem, NRadioButton, NH1, NTabs, NTabPane, NSelect } from 'naive-ui'
|
import { NInput, NFlex, NDivider, NDatePicker, NSpace, NFormItem, NRadioButton, NH1, NTabs, NTabPane, NSelect } from 'naive-ui'
|
||||||
import {useMedicalHistory} from "../../Composables/useMedicalHistory.js";
|
|
||||||
import {useDebounceFn} from "@vueuse/core";
|
|
||||||
import {useMedicalHistoryFilter} from "../../Composables/useMedicalHistoryFilter.js";
|
import {useMedicalHistoryFilter} from "../../Composables/useMedicalHistoryFilter.js";
|
||||||
import {computed, ref} from "vue";
|
import {ref} from "vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
cards: {
|
cards: {
|
||||||
@@ -63,14 +61,7 @@ const handleBeforeLeave = (tabName) => {
|
|||||||
</NFlex>
|
</NFlex>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</template>
|
</template>
|
||||||
<NTabs :value="filtersRef.view_type" type="segment" animated @before-leave="handleBeforeLeave">
|
<TableCards :filters="filters" :data="cards.data" :meta="cards.meta" min-height="calc(100vh - 212px)" max-height="calc(100vh - 320px)" />
|
||||||
<NTabPane name="si" :tab="`СофтИнфо (${cards.si?.meta.total})`">
|
|
||||||
<TableCards :filters="filters" :data="cards.si?.data" :meta="cards.si?.meta" min-height="calc(100vh - 286px)" max-height="calc(100vh - 320px)" />
|
|
||||||
</NTabPane>
|
|
||||||
<NTabPane name="mis" :tab="`МИС (${cards.mis?.meta.total})`">
|
|
||||||
<TableCards :filters="filters" :data="cards.mis?.data" :meta="cards.mis?.meta" min-height="calc(100vh - 286px)" max-height="calc(100vh - 320px)" />
|
|
||||||
</NTabPane>
|
|
||||||
</NTabs>
|
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user