You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

551 lines
25 KiB
PHP

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Barryvdh\Snappy\Facades\SnappyPdf;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
class PdfController extends Controller
{
//旧版GetCheckPdf备份
public function GetCheckPdfOld()
{
$OrderNoList = request('OrderNoList');//医嘱号列表(数组)
if (!isset($OrderNoList) or empty($OrderNoList)) return \Yz::JsonReturn("OrderNoList,不能为空");
if (!is_array($OrderNoList)) return \Yz::JsonReturn("OrderNoList,应为数组");
$list = [];
foreach ($OrderNoList as $orderNo) {
$entrustInfo=DB::table('s_list as a')->where(['a.entrust_id'=>$orderNo,'a.list_status'=>1,'a.is_nullify'=>0])->first();
$url="";
if(!!$entrustInfo) $url=env('APP_URL') .$entrustInfo->check_aply_pdf ;
$list[] = [
'OrderNo' => $orderNo,
'PdfUrl' => $url,
];
}
return \Yz::JsonReturn(true, '查询完成', ['list' => $list]);
}
//新版GetCheckPdf检查项目状态分组生成PDF文件
public function GetCheckPdf()
{
$OrderNoList = request('OrderNoList');
if (!isset($OrderNoList) or empty($OrderNoList)) {
return \Yz::JsonReturn('OrderNoList,不能为空');
}
if (!is_array($OrderNoList)) {
return \Yz::JsonReturn('OrderNoList,应为数组');
}
$type = request('Type', 'old');
$dev = request('Dev', '0');
$p_type = config('app.globals.患者类型');
$resultList = [];
$normalIds = []; //正常的医嘱号列表
//建立入参索引映射
$orderIndexMap = array_flip(array_values($OrderNoList));
//遍历每个医嘱号,检查状态
foreach ($OrderNoList as $orderNo) {
//查s_list去掉is_nullify限制先判断记录是否存在和是否已删除
$entrustInfo = DB::table('s_list as a')
->where(['a.entrust_id' => $orderNo])
->first();
//不存在 或 已删除
if (!$entrustInfo || $entrustInfo->is_del == 1) {
$resultList[] = [
'_idx' => $orderIndexMap[$orderNo],
'OrderNo' => [$orderNo],
'Message' => "医嘱id:{$orderNo},在医技预约系统中不存在!",
'PdfUrl' => '',
];
continue;
}
//已作废
if ($entrustInfo->is_nullify == 1) {
$resultList[] = [
'_idx' => $orderIndexMap[$orderNo],
'OrderNo' => [$orderNo],
'Message' => "医嘱id:{$orderNo},已作废!",
'PdfUrl' => '',
];
continue;
}
//查s_check_item判断是否需要预约
$checkItem = DB::table('s_check_item as a')
->leftJoin('s_check_item_device as b', 'a.id', '=', 'b.item_id')
->leftJoin('s_department_resources_device as c', 'b.device_id', '=', 'c.device_id')
->where(['a.item_name' => $entrustInfo->entrust, 'a.status' => 1, 'a.is_del' => 0])
->first();
if (!$checkItem || empty($checkItem->device_id)) {
$resultList[] = [
'_idx' => $orderIndexMap[$orderNo],
'OrderNo' => [$orderNo],
'Message' => "{$entrustInfo->entrust}项目不需要预约",
'PdfUrl' => '',
];
continue;
}
//查预约状态
if ($entrustInfo->list_status != 1) {
$resultList[] = [
'_idx' => $orderIndexMap[$orderNo],
'OrderNo' => [$orderNo],
'Message' => "{$entrustInfo->entrust}项目没有预约",
'PdfUrl' => '',
];
continue;
}
//正常项目
$normalIds[] = $orderNo;
}
//如果有正常项目生成PDF
if (!empty($normalIds)) {
//查询正常项目的完整数据
$list = DB::table('s_list as a')
->select(
'a.*',
'c.period_begin_time',
'c.period_end_time',
'b.department_resources_name',
'b.department_resources_addr'
)
->leftJoin('s_period as c', 'a.reservation_time', '=', 'c.id')
->leftJoin('s_department_resources as b', 'a.reservation_sources', '=', 'b.id')
->whereIn('a.entrust_id', $normalIds)
->where('a.list_status', 1)
->where('a.is_nullify', 0)
->orderByRaw('FIELD(a.entrust_id, ' . implode(',', array_map('intval', $normalIds)) . ')')
->get();
//三层分组
$groups = [];
foreach ($list as $item) {
$typeKey = $item->patient_type;
$patientKey = $item->patient_type == 0
? substr($item->episodeid, -10)
: $item->reg_num;
$roomKey = $type === 'single' || $type === 'old'
? 'item_' . $item->id
: ($item->department_resources_name ?: '未知诊室')
. '|' . ($item->reservation_date ?? '')
. '|' . ($item->period_begin_time ?? '')
. '|' . ($item->period_end_time ?? '');
if (!isset($groups[$typeKey])) {
$groups[$typeKey] = [
'label' => $p_type[$typeKey] ?? '未知',
'patients' => [],
];
}
if (!isset($groups[$typeKey]['patients'][$patientKey])) {
$groups[$typeKey]['patients'][$patientKey] = [
'patient_name' => $item->user_name,
'patient_id' => $patientKey,
'patient_type' => $item->patient_type,
'user_sex' => $item->user_sex,
'user_brithday' => $item->user_brithday,
'warddesc' => $item->warddesc ?? '',
'bedno' => $item->bedno ?? '',
'user_phone' => $item->user_phone,
'rooms' => [],
];
}
if (!isset($groups[$typeKey]['patients'][$patientKey]['rooms'][$roomKey])) {
$groups[$typeKey]['patients'][$patientKey]['rooms'][$roomKey] = [
'room_name' => $roomKey,
'room_addr' => $item->department_resources_addr ?? '',
'items' => [],
];
}
$groups[$typeKey]['patients'][$patientKey]['rooms'][$roomKey]['items'][] = [
'id' => $item->id,
'entrust_id' => $item->entrust_id,
'entrust' => $item->entrust,
'entrust_date' => $item->entrust_date,
'entrust_time' => $item->entrust_time,
'reservation_date' => $item->reservation_date,
'period_begin_time' => $item->period_begin_time,
'period_end_time' => $item->period_end_time,
];
}
//预计算各字段
$generator = new \Picqer\Barcode\BarcodeGeneratorPNG();
foreach ($groups as &$typeGroup) {
foreach ($typeGroup['patients'] as &$patient) {
$patient['user_sex_label'] = '';
if ($patient['user_sex'] == 1) $patient['user_sex_label'] = '男';
if ($patient['user_sex'] == 2) $patient['user_sex_label'] = '女';
$patient['age'] = \Tools::getAgeFromBirthday($patient['user_brithday']);
$patient['patient_type_label'] = $typeGroup['label'];
$patient['barcode'] = base64_encode($generator->getBarcode($patient['patient_id'], $generator::TYPE_CODE_128, 2, 40));
$patient['barcode_text'] = $patient['patient_id'];
foreach ($patient['rooms'] as &$room) {
$room['items_str'] = implode('', array_column($room['items'], 'entrust'));
$firstItem = $room['items'][0];
$room['reservation_date'] = $firstItem['reservation_date'];
$room['period_begin'] = $firstItem['period_begin_time'] ? substr($firstItem['period_begin_time'], 0, 5) : '';
$room['period_end'] = $firstItem['period_end_time'] ? substr($firstItem['period_end_time'], 0, 5) : '';
$room['weekday_label'] = \Tools::GetWeekName($firstItem['reservation_date']);
$minDateTime = $room['items'][0]['entrust_date'] . ' ' . $room['items'][0]['entrust_time'];
$maxDateTime = $minDateTime;
foreach ($room['items'] as $it) {
$dt = $it['entrust_date'] . ' ' . $it['entrust_time'];
if ($dt < $minDateTime) $minDateTime = $dt;
if ($dt > $maxDateTime) $maxDateTime = $dt;
}
$room['entrust_date_time'] = $minDateTime === $maxDateTime
? $minDateTime
: $minDateTime . ' ~ ' . $maxDateTime;
//检查须知:从该诊室所有检查项目读取 check_notice去重过滤
$itemNames = array_column($room['items'], 'entrust');
$notices = DB::table('s_check_item')
->whereIn('item_name', $itemNames)
->where('status', 1)
->where('is_del', 0)
->pluck('check_notice')
->filter()
->unique()
->values()
->toArray();
$room['check_notice'] = implode("\n", $notices);
}
}
}
unset($typeGroup, $patient, $room);
// Dev模式直接输出PDF不生成文件
if ($dev == '1') {
$pdf = SnappyPdf::loadView('pdf.GroupedCheckPdf', ['groups' => $groups])
->setOption('page-size', 'a5')
->setOption('orientation', 'landscape');
return $pdf->inline('CheckPdf.pdf');
}
//为每个room生成独立的PDF文件
$datePath = date('Y/m/d');
$storageDir = 'CheckPdf/' . $datePath;
$fullDir = storage_path('app/public/' . $storageDir);
if (!File::exists($fullDir)) {
File::makeDirectory($fullDir, 0755, true);
}
foreach ($groups as $typeKey => $typeGroup) {
foreach ($typeGroup['patients'] as $patientKey => $patient) {
foreach ($patient['rooms'] as $roomKey => $room) {
//收集该分组的医嘱号
$orderNos = array_column($room['items'], 'entrust_id');
//构建只包含当前room的临时groups结构
$tempGroups = [
$typeKey => [
'label' => $typeGroup['label'],
'patients' => [
$patientKey => [
'patient_name' => $patient['patient_name'],
'patient_id' => $patient['patient_id'],
'patient_type' => $patient['patient_type'],
'user_sex_label' => $patient['user_sex_label'],
'age' => $patient['age'],
'patient_type_label' => $patient['patient_type_label'],
'warddesc' => $patient['warddesc'],
'bedno' => $patient['bedno'],
'user_phone' => $patient['user_phone'],
'barcode' => $patient['barcode'],
'barcode_text' => $patient['barcode_text'],
'rooms' => [
$roomKey => $room,
],
],
],
],
];
//生成文件名MD5医嘱号列表|预约日期|预约时间段)
$entrustIdStr = implode(',', $orderNos);
$nameStr = $entrustIdStr . '|' . $room['reservation_date']
. '|' . ($room['period_begin'] ? $room['period_begin'] . '-' . $room['period_end'] : '');
$filename = md5($nameStr) . '.pdf';
$filePath = $fullDir . '/' . $filename;
//检查文件是否存在,不存在则生成
if (!File::exists($filePath)) {
$pdf = SnappyPdf::loadView('pdf.GroupedCheckPdf', ['groups' => $tempGroups])
->setOption('page-size', 'a5')
->setOption('orientation', 'landscape');
$pdf->save($filePath);
}
$url = env('APP_URL') . Storage::url($storageDir . '/' . $filename);
$resultList[] = [
'_idx' => $orderIndexMap[$orderNos[0]],
'OrderNo' => $orderNos,
'Message' => '',
'PdfUrl' => $url,
];
}
}
}
}
//按入参顺序排序,去掉内部索引
usort($resultList, function ($a, $b) {
return $a['_idx'] - $b['_idx'];
});
$resultList = array_map(function ($item) {
unset($item['_idx']);
return $item;
}, $resultList);
//old模式简化返回格式
if ($type === 'old') {
$resultList = array_map(function ($item) {
return [
'OrderNo' => is_array($item['OrderNo']) ? $item['OrderNo'][0] : $item['OrderNo'],
'PdfUrl' => $item['PdfUrl'] ?? '',
];
}, $resultList);
}
return \Yz::JsonReturn(true, '查询完成', ['list' => $resultList]);
}
//创建检查申请单pdf文件
public function CreateJianChaShenQingDanPdf()
{
$OrderNoList = request('OrderNoList');//医嘱号列表(数组)
if (!isset($OrderNoList) or empty($OrderNoList)) return \Yz::JsonReturn("OrderNoList,不能为空");
if (!is_array($OrderNoList)) return \Yz::JsonReturn("OrderNoList,应为数组");
$config=DB::table('configs')->where(['label'=>'开启申请单pdf'])->first();
if (!$config or $config->value<>1) return \Yz::JsonError("未开启申请单pdf");
$generator = new \Picqer\Barcode\BarcodeGeneratorPNG();
$successCount=0;
foreach ($OrderNoList as $orderNo) {
$entrustInfo=DB::table('s_list as a')->where(['a.entrust_id'=>$orderNo,'a.list_status'=>1,'a.is_nullify'=>0])
->select('a.*','c.period_begin_time','c.period_end_time')
->leftJoin('s_period as c','a.reservation_time','=','c.id')
->first();
if(!$entrustInfo) continue;
$barcodeContent = $entrustInfo->patient_type == 0 ? substr($entrustInfo->episodeid, -10) : $entrustInfo->reg_num;
$tiaoma = base64_encode($generator->getBarcode($barcodeContent, $generator::TYPE_CODE_128, 2, 40));
$source=null;
if(!empty($entrustInfo->reservation_sources)){
$source=DB::table('s_department_resources')->where(['id'=>$entrustInfo->reservation_sources])->first();
}
$entrustInfo->department_resources=$source;
$entrustInfo->user_sex_label='';
if($entrustInfo->user_sex==1){
$entrustInfo->user_sex_label='男';
}
if($entrustInfo->user_sex==2){
$entrustInfo->user_sex_label='女';
}
$entrustInfo->age=\Tools::getAgeFromBirthday($entrustInfo->user_brithday);
//患者类型
$p_type=config('app.globals.患者类型');
$entrustInfo->patient_type_label=$p_type[$entrustInfo->patient_type] ?? '';
//星期
$entrustInfo->weekday_label=\Tools::GetWeekName($entrustInfo->reservation_date);
// 准备数据
$data = [
'printInfo' =>$entrustInfo,
'barcode' => $tiaoma,
];
$filePath = storage_path('app/public/CheckPdf/' . date('Ymd') . '/' . $orderNo . '.pdf');
// 检查文件是否存在,存在则删除
if (File::exists($filePath)) {
File::delete($filePath);
}
// 生成并保存新文件
$pdf = SnappyPdf::loadView('pdf.JianChaShenQingDan', $data)
->setOption('page-size', 'a5')
// 设置方向portrait 纵向 / landscape 横向)
->setOption('orientation', 'landscape');
$pdf->save($filePath);
$fileUrl = Storage::url('CheckPdf/' . date('Ymd') . '/' . $orderNo . '.pdf');
DB::table('s_list')->where('entrust_id', $orderNo)->update(['check_aply_pdf' => $fileUrl]);
$successCount++;
}
return \Yz::JsonReturn(true, '生成检查申请单pdf成功', ['success_count' => $successCount]);
}
//按诊室分组生成检查项目清单PDF流式返回
public function GenerateGroupedCheckPdf()
{
$OrderNoList = request('OrderNoList');
if (!isset($OrderNoList) or empty($OrderNoList)) {
return \Yz::JsonReturn('OrderNoList,不能为空');
}
if (!is_array($OrderNoList)) {
return \Yz::JsonReturn('OrderNoList,应为数组');
}
//查询数据,关联时段和诊室资源
$list = DB::table('s_list as a')
->select(
'a.*',
'c.period_begin_time',
'c.period_end_time',
'b.department_resources_name',
'b.department_resources_addr'
)
->leftJoin('s_period as c', 'a.reservation_time', '=', 'c.id')
->leftJoin('s_department_resources as b', 'a.reservation_sources', '=', 'b.id')
->whereIn('a.entrust_id', $OrderNoList)
->where('a.list_status', 1)
->where('a.is_nullify', 0)
->orderBy('a.id')
->get();
if ($list->isEmpty()) {
return \Yz::JsonReturn(false, '未找到符合条件的医嘱数据');
}
$type = request('Type', 'group');
$p_type = config('app.globals.患者类型');
//三层分组patient_type → 患者标识 → 诊室
$groups = [];
foreach ($list as $item) {
//第1层患者类型
$typeKey = $item->patient_type;
//第2层患者标识住院用episodeid后10位非住院用reg_num
$patientKey = $item->patient_type == 0
? substr($item->episodeid, -10)
: $item->reg_num;
//第3层诊室single模式每个item独立一页用item.id区分
$roomKey = $type === 'single'
? 'item_' . $item->id
: ($item->department_resources_name ?: '未知诊室')
. '|' . ($item->reservation_date ?? '')
. '|' . ($item->period_begin_time ?? '')
. '|' . ($item->period_end_time ?? '');
if (!isset($groups[$typeKey])) {
$groups[$typeKey] = [
'label' => $p_type[$typeKey] ?? '未知',
'patients' => [],
];
}
if (!isset($groups[$typeKey]['patients'][$patientKey])) {
$groups[$typeKey]['patients'][$patientKey] = [
'patient_name' => $item->user_name,
'patient_id' => $patientKey,
'patient_type' => $item->patient_type,
'user_sex' => $item->user_sex,
'user_brithday' => $item->user_brithday,
'warddesc' => $item->warddesc ?? '',
'bedno' => $item->bedno ?? '',
'user_phone' => $item->user_phone,
'rooms' => [],
];
}
if (!isset($groups[$typeKey]['patients'][$patientKey]['rooms'][$roomKey])) {
$groups[$typeKey]['patients'][$patientKey]['rooms'][$roomKey] = [
'room_name' => $roomKey,
'room_addr' => $item->department_resources_addr ?? '',
'items' => [],
];
}
$groups[$typeKey]['patients'][$patientKey]['rooms'][$roomKey]['items'][] = [
'id' => $item->id,
'entrust' => $item->entrust,
'entrust_date' => $item->entrust_date,
'entrust_time' => $item->entrust_time,
'reservation_date' => $item->reservation_date,
'period_begin_time' => $item->period_begin_time,
'period_end_time' => $item->period_end_time,
];
}
//预计算各字段
$generator = new \Picqer\Barcode\BarcodeGeneratorPNG();
foreach ($groups as &$typeGroup) {
foreach ($typeGroup['patients'] as &$patient) {
//患者基本信息
$patient['user_sex_label'] = '';
if ($patient['user_sex'] == 1) $patient['user_sex_label'] = '男';
if ($patient['user_sex'] == 2) $patient['user_sex_label'] = '女';
$patient['age'] = \Tools::getAgeFromBirthday($patient['user_brithday']);
$patient['patient_type_label'] = $typeGroup['label'];
//条形码
$patient['barcode'] = base64_encode($generator->getBarcode($patient['patient_id'], $generator::TYPE_CODE_128, 2, 40));
$patient['barcode_text'] = $patient['patient_id'];
foreach ($patient['rooms'] as &$room) {
//项目名称拼接
$room['items_str'] = implode('', array_column($room['items'], 'entrust'));
//预约时间
$firstItem = $room['items'][0];
$room['reservation_date'] = $firstItem['reservation_date'];
$room['period_begin'] = $firstItem['period_begin_time'] ? substr($firstItem['period_begin_time'], 0, 5) : '';
$room['period_end'] = $firstItem['period_end_time'] ? substr($firstItem['period_end_time'], 0, 5) : '';
$room['weekday_label'] = \Tools::GetWeekName($firstItem['reservation_date']);
//申请时间范围
$minDateTime = $room['items'][0]['entrust_date'] . ' ' . $room['items'][0]['entrust_time'];
$maxDateTime = $minDateTime;
foreach ($room['items'] as $it) {
$dt = $it['entrust_date'] . ' ' . $it['entrust_time'];
if ($dt < $minDateTime) $minDateTime = $dt;
if ($dt > $maxDateTime) $maxDateTime = $dt;
}
$room['entrust_date_time'] = $minDateTime === $maxDateTime
? $minDateTime
: $minDateTime . ' ~ ' . $maxDateTime;
//检查须知:从该诊室所有检查项目读取 check_notice去重过滤
$itemNames = array_column($room['items'], 'entrust');
$notices = DB::table('s_check_item')
->whereIn('item_name', $itemNames)
->where('status', 1)
->where('is_del', 0)
->pluck('check_notice')
->filter()
->unique()
->values()
->toArray();
$room['check_notice'] = implode("\n", $notices);
}
}
}
unset($typeGroup, $patient, $room);
$pdf = SnappyPdf::loadView('pdf.GroupedCheckPdf', ['groups' => $groups])
->setOption('page-size', 'a4')
->setOption('orientation', 'portrait');
return $pdf->inline('GenerateGroupedCheckPdf.pdf');
}
}