鹿和sa0ChunLuyu 7 days ago
parent d4fefd628f
commit ff156c8eec

@ -236,8 +236,12 @@ public function GetCheckPdf()
// Dev模式直接输出PDF不生成文件 // Dev模式直接输出PDF不生成文件
if ($dev == '1') { if ($dev == '1') {
$pdf = SnappyPdf::loadView('pdf.GroupedCheckPdf', ['groups' => $groups]) $pdf = SnappyPdf::loadView('pdf.GroupedCheckPdf', ['groups' => $groups])
->setOption('page-size', 'a5') ->setOption('page-width', '210mm')
->setOption('orientation', 'landscape'); ->setOption('page-height', '297mm')
->setOption('margin-top', '5mm')
->setOption('margin-bottom', '5mm')
->setOption('margin-left', '5mm')
->setOption('margin-right', '5mm');
return $pdf->inline('CheckPdf.pdf'); return $pdf->inline('CheckPdf.pdf');
} }
@ -288,10 +292,15 @@ public function GetCheckPdf()
$filePath = $fullDir . '/' . $filename; $filePath = $fullDir . '/' . $filename;
//检查文件是否存在,不存在则生成 //检查文件是否存在,不存在则生成
//检查文件是否存在,不存在则生成(打印路径变更时需手动清理旧文件)
if (!File::exists($filePath)) { if (!File::exists($filePath)) {
$pdf = SnappyPdf::loadView('pdf.GroupedCheckPdf', ['groups' => $tempGroups]) $pdf = SnappyPdf::loadView('pdf.GroupedCheckPdf', ['groups' => $tempGroups])
->setOption('page-size', 'a5') ->setOption('page-width', '210mm')
->setOption('orientation', 'landscape'); ->setOption('page-height', '297mm')
->setOption('margin-top', '5mm')
->setOption('margin-bottom', '5mm')
->setOption('margin-left', '5mm')
->setOption('margin-right', '5mm');
$pdf->save($filePath); $pdf->save($filePath);
} }
@ -543,8 +552,12 @@ public function GenerateGroupedCheckPdf()
unset($typeGroup, $patient, $room); unset($typeGroup, $patient, $room);
$pdf = SnappyPdf::loadView('pdf.GroupedCheckPdf', ['groups' => $groups]) $pdf = SnappyPdf::loadView('pdf.GroupedCheckPdf', ['groups' => $groups])
->setOption('page-size', 'a4') ->setOption('page-width', '210mm')
->setOption('orientation', 'portrait'); ->setOption('page-height', '297mm')
->setOption('margin-top', '5mm')
->setOption('margin-bottom', '5mm')
->setOption('margin-left', '5mm')
->setOption('margin-right', '5mm');
return $pdf->inline('GenerateGroupedCheckPdf.pdf'); return $pdf->inline('GenerateGroupedCheckPdf.pdf');
} }

@ -213,7 +213,26 @@ public function SignIn(){
'note' => '通知PacS', 'note' => '通知PacS',
'data' => json_encode($pacs_res,JSON_UNESCAPED_UNICODE) 'data' => json_encode($pacs_res,JSON_UNESCAPED_UNICODE)
]); ]);
return \Yz::JsonReturn(true,'报道成功',['orderNo'=>$orderNo,'pacs_info'=>$pacs_res]);
if (!!$pacs_res['status']) {
return \Yz::JsonReturn(true, '报道成功', ['orderNo' => $orderNo, 'pacs_info' => $pacs_res]);
} else {
$data = [
'list_status' => 1,
'check_num' => '',
];
$u = DB::table('s_list')->where(['entrust_id' => $orderNo])->update($data);
$i_log = DB::table('s_list_log')->insert([
'list_id' => $entrust->id,
'reg_num' => $entrust->reg_num,
'old_status' => 2,
'new_status' => 1,
'create_user' => 'Pacs接口',
'note' => '通知Pacs失败',
'data' => json_encode(['checkNo' => $checkNo], JSON_UNESCAPED_UNICODE)
]);
return \Yz::JsonReturn(false, '报道失败', ['orderNo' => $orderNo, 'pacs_info' => $pacs_res]);
}
}else{ }else{
return \Yz::JsonError('报道失败'); return \Yz::JsonError('报道失败');
} }

@ -22,6 +22,7 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ
$allDevice = [];//所有医嘱检查项目绑定的设备id $allDevice = [];//所有医嘱检查项目绑定的设备id
$commPatientType = [];//所有医嘱共同的病人类型 $commPatientType = [];//所有医嘱共同的病人类型
$zhanweiCount=0;//勾选的检查项目共计占多少名额 $zhanweiCount=0;//勾选的检查项目共计占多少名额
$shareSlotMaxSeats = 0;//共享号源项目的use_seats最大值
$allItemRules = [];//所有检查项目的TIME_RESTRICTION规则 $allItemRules = [];//所有检查项目的TIME_RESTRICTION规则
foreach ($entrustids as $key => $entrustid) { foreach ($entrustids as $key => $entrustid) {
// $info = DB::table('s_list')->where(['reg_num' => $regnum, 'entrust_id' => $entrustid, 'episodeid' => $episodeid, 'is_nullify' => 0])->first(); // $info = DB::table('s_list')->where(['reg_num' => $regnum, 'entrust_id' => $entrustid, 'episodeid' => $episodeid, 'is_nullify' => 0])->first();
@ -35,7 +36,11 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ
$itemInfo = DB::table('s_check_item')->where(['item_name' => $info->entrust, 'status' => 1, "is_del" => 0])->get(); $itemInfo = DB::table('s_check_item')->where(['item_name' => $info->entrust, 'status' => 1, "is_del" => 0])->get();
if (count($itemInfo) == 0) return \Yz::echoError1('没有找到可用的检查项目信息'); if (count($itemInfo) == 0) return \Yz::echoError1('没有找到可用的检查项目信息');
$itemInfo = $itemInfo[0]; $itemInfo = $itemInfo[0];
$zhanweiCount+=isset($itemInfo->use_seats)?$itemInfo->use_seats:0; if (!empty($itemInfo->is_share_slot)) {
$shareSlotMaxSeats = max($shareSlotMaxSeats, isset($itemInfo->use_seats) ? $itemInfo->use_seats : 0);
} else {
$zhanweiCount += isset($itemInfo->use_seats) ? $itemInfo->use_seats : 0;
}
$qudaos = explode(',', $itemInfo->reservation_method); $qudaos = explode(',', $itemInfo->reservation_method);
//只判断主渠道,如果主渠道支持,则子渠道默认也支持,即使项目没绑定子渠道 //只判断主渠道,如果主渠道支持,则子渠道默认也支持,即使项目没绑定子渠道
if (!in_array($appointment_type, $qudaos)) return \Yz::echoError1('此检查项目不支持在当前渠道预约'); if (!in_array($appointment_type, $qudaos)) return \Yz::echoError1('此检查项目不支持在当前渠道预约');
@ -64,6 +69,12 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ
} }
} }
// 共享号源项目合并计算:只取最大值
if ($shareSlotMaxSeats > 0) {
$zhanweiCount += $shareSlotMaxSeats;
}
$newSharedMax = $shareSlotMaxSeats;
$commonDevice = []; //多个检查项目共同的设备id $commonDevice = []; //多个检查项目共同的设备id
$first = true; $first = true;
foreach ($allDevice as $set) { foreach ($allDevice as $set) {
@ -262,6 +273,30 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ
$pl2 = []; $pl2 = [];
$pp = []; $pp = [];
$nowtime = date('Y-m-d H:i:s'); $nowtime = date('Y-m-d H:i:s');
// 查询该患者已有共享项目在各排班下的 max
$existingSharedAtPlan = [];
if (!empty($regnum)) {
$existingSharedItems = DB::table('s_list')
->join('s_check_item', 's_list.entrust', '=', 's_check_item.item_name')
->where('s_list.reg_num', $regnum)
->where('s_list.list_status', 1)
->where('s_list.roster_id', '>', 0)
->where('s_check_item.is_share_slot', 1)
->select('s_list.roster_id', 's_check_item.use_seats')
->get();
foreach ($existingSharedItems as $esi) {
$pid = $esi->roster_id;
$existingSharedAtPlan[$pid] = max($existingSharedAtPlan[$pid] ?? 0, $esi->use_seats);
}
}
Log::info('[YuYueDebug] GetEnablePlan', [
'regnum' => $regnum,
'zhanweiCount' => $zhanweiCount,
'newSharedMax' => $newSharedMax,
'existingSharedAtPlan' => $existingSharedAtPlan,
]);
foreach ($plan as $key => $p) { foreach ($plan as $key => $p) {
// //病人类型不符合的过滤掉 // //病人类型不符合的过滤掉
$planPatientType = explode(",", $p->patient_type); $planPatientType = explode(",", $p->patient_type);
@ -284,7 +319,10 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ
//过期的排在后面 //过期的排在后面
$time = $p->date . ' ' . $p->end_time; $time = $p->date . ' ' . $p->end_time;
if ($time > $nowtime) { $remaining = ($p->count ?? 0) - ($p->used_count ?? 0);
$existingMax = $existingSharedAtPlan[$p->id] ?? 0;
$needed = $zhanweiCount - min($newSharedMax, $existingMax);
if ($time > $nowtime && $remaining >= $needed) {
$p->plan_enable=true; $p->plan_enable=true;
$pl1[] = $p; $pl1[] = $p;
} else { } else {
@ -434,32 +472,84 @@ public function GetOptimalPlan($type, $regnum, $entrustids, $episodeid, $appoint
$endDate = new DateTime(); $endDate = new DateTime();
$endDate->modify('+' . $dateRange . ' day'); $endDate->modify('+' . $dateRange . ' day');
// 批量查询每个检查项目的 use_seats // 批量查询每个检查项目的 use_seats 和 is_share_slot
$entrustIds = array_column($items, 'entrust_id'); $entrustIds = array_column($items, 'entrust_id');
$useSeatsMap = []; $useSeatsMap = [];
$shareSlotMap = [];
if (!empty($entrustIds)) { if (!empty($entrustIds)) {
$useSeatsMap = DB::table('s_list') $itemData = DB::table('s_list')
->join('s_check_item', 's_list.entrust', '=', 's_check_item.item_name') ->join('s_check_item', 's_list.entrust', '=', 's_check_item.item_name')
->whereIn('s_list.entrust_id', $entrustIds) ->whereIn('s_list.entrust_id', $entrustIds)
->pluck('s_check_item.use_seats', 's_list.entrust_id') ->select('s_list.entrust_id', 's_check_item.use_seats', 's_check_item.is_share_slot')
->toArray(); ->get();
foreach ($itemData as $row) {
$useSeatsMap[$row->entrust_id] = $row->use_seats;
$shareSlotMap[$row->entrust_id] = $row->is_share_slot ?? 0;
}
} }
foreach ($items as &$item) { foreach ($items as &$item) {
$item['use_seats'] = $useSeatsMap[$item['entrust_id']] ?? 1; $item['use_seats'] = $useSeatsMap[$item['entrust_id']] ?? 1;
$item['is_share_slot'] = $shareSlotMap[$item['entrust_id']] ?? 0;
} }
unset($item); unset($item);
// 共享号源项目合并计算只保留最大值其余设为0
$shareSlotItems = array_filter($items, function($it) { return !empty($it['is_share_slot']); });
if (count($shareSlotItems) > 1) {
$maxSeats = 0;
foreach ($shareSlotItems as $it) {
$maxSeats = max($maxSeats, $it['use_seats']);
}
// 找到 use_seats 最高的共享项目,将 max 分配给它
$maxShareItemIdx = null;
$maxShareSeats = 0;
foreach ($items as $idx => $it) {
if (!empty($it['is_share_slot']) && $it['use_seats'] > $maxShareSeats) {
$maxShareSeats = $it['use_seats'];
$maxShareItemIdx = $idx;
}
}
foreach ($items as &$it) {
if (!empty($it['is_share_slot'])) {
$it['use_seats'] = 0;
}
}
unset($it);
if ($maxShareItemIdx !== null) {
$items[$maxShareItemIdx]['use_seats'] = $maxSeats;
}
}
// 查询该患者已有共享项目在各排班下的 max
$existingSharedAtPlan = [];
$existingSharedItems = DB::table('s_list')
->join('s_check_item', 's_list.entrust', '=', 's_check_item.item_name')
->where('s_list.reg_num', $regnum)
->where('s_list.list_status', 1)
->where('s_list.is_nullify', 0)
->where('s_list.roster_id', '>', 0)
->where('s_check_item.is_share_slot', 1)
->select('s_list.roster_id', 's_check_item.use_seats')
->get();
foreach ($existingSharedItems as $esi) {
$pid = $esi->roster_id;
if (!isset($existingSharedAtPlan[$pid])) {
$existingSharedAtPlan[$pid] = 0;
}
$existingSharedAtPlan[$pid] = max($existingSharedAtPlan[$pid], $esi->use_seats);
}
if ($type === 'full_day') { if ($type === 'full_day') {
return $this->doFullDayAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids); return $this->doFullDayAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids, $existingSharedAtPlan);
} elseif ($type === 'same_day_slot') { } elseif ($type === 'same_day_slot') {
return $this->doSameDaySlotAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids); return $this->doSameDaySlotAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids, $existingSharedAtPlan);
} else { } else {
return $this->doOptimalTimeAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids); return $this->doOptimalTimeAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids, $existingSharedAtPlan);
} }
} }
// 最优时间分配:按科室分组,逐个 item 找最早可用号源,可跨天 // 最优时间分配:按科室分组,逐个 item 找最早可用号源,可跨天
private function doOptimalTimeAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids = []) private function doOptimalTimeAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids = [], $existingSharedAtPlan = [])
{ {
// 按科室分组 // 按科室分组
$deptGroups = $this->groupItemsByDept($items); $deptGroups = $this->groupItemsByDept($items);
@ -512,6 +602,11 @@ private function doOptimalTimeAssign($startDate, $endDate, $regnum, $entrustids,
foreach ($availablePlans as $plan) { foreach ($availablePlans as $plan) {
$planId = $plan->id; $planId = $plan->id;
$useSeats = $item['use_seats'] ?? 1; $useSeats = $item['use_seats'] ?? 1;
// 共享项目号源持有者:减去已有共享项目的 max
if (!empty($item['is_share_slot']) && $useSeats > 0) {
$existingMax = $existingSharedAtPlan[$planId] ?? 0;
$useSeats = max(0, $useSeats - $existingMax);
}
$remaining = ($plan->count ?? 0) - ($plan->used_count ?? 0); $remaining = ($plan->count ?? 0) - ($plan->used_count ?? 0);
$used = $usedCapacity[$planId] ?? 0; $used = $usedCapacity[$planId] ?? 0;
@ -565,7 +660,7 @@ private function doOptimalTimeAssign($startDate, $endDate, $regnum, $entrustids,
} }
// 单天全检分配:所有 item 必须在同一天完成 // 单天全检分配:所有 item 必须在同一天完成
private function doFullDayAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids = []) private function doFullDayAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids = [], $existingSharedAtPlan = [])
{ {
// 按科室分组 // 按科室分组
$deptGroups = $this->groupItemsByDept($items); $deptGroups = $this->groupItemsByDept($items);
@ -604,6 +699,11 @@ private function doFullDayAssign($startDate, $endDate, $regnum, $entrustids, $ep
foreach ($availablePlans as $plan) { foreach ($availablePlans as $plan) {
$planId = $plan->id; $planId = $plan->id;
$useSeats = $item['use_seats'] ?? 1; $useSeats = $item['use_seats'] ?? 1;
// 共享项目号源持有者:减去已有共享项目的 max
if (!empty($item['is_share_slot']) && $useSeats > 0) {
$existingMax = $existingSharedAtPlan[$planId] ?? 0;
$useSeats = max(0, $useSeats - $existingMax);
}
$remaining = ($plan->count ?? 0) - ($plan->used_count ?? 0); $remaining = ($plan->count ?? 0) - ($plan->used_count ?? 0);
$used = $usedCapacity[$planId] ?? 0; $used = $usedCapacity[$planId] ?? 0;
@ -647,7 +747,7 @@ private function doFullDayAssign($startDate, $endDate, $regnum, $entrustids, $ep
} }
// 同一天同一时间段分配:所有 item 必须在同一天且同一时间段完成 // 同一天同一时间段分配:所有 item 必须在同一天且同一时间段完成
private function doSameDaySlotAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids = []) private function doSameDaySlotAssign($startDate, $endDate, $regnum, $entrustids, $episodeid, $appointment_type, $items, $scope, $userDeptId, $occupied_plan_ids = [], $existingSharedAtPlan = [])
{ {
// 按科室分组 // 按科室分组
$deptGroups = $this->groupItemsByDept($items); $deptGroups = $this->groupItemsByDept($items);
@ -723,6 +823,11 @@ private function doSameDaySlotAssign($startDate, $endDate, $regnum, $entrustids,
foreach ($availablePlans as $plan) { foreach ($availablePlans as $plan) {
$planId = $plan->id; $planId = $plan->id;
$useSeats = $item['use_seats'] ?? 1; $useSeats = $item['use_seats'] ?? 1;
// 共享项目号源持有者:减去已有共享项目的 max
if (!empty($item['is_share_slot']) && $useSeats > 0) {
$existingMax = $existingSharedAtPlan[$planId] ?? 0;
$useSeats = max(0, $useSeats - $existingMax);
}
$remaining = ($plan->count ?? 0) - ($plan->used_count ?? 0); $remaining = ($plan->count ?? 0) - ($plan->used_count ?? 0);
$used = $usedCapacity[$planId] ?? 0; $used = $usedCapacity[$planId] ?? 0;
@ -872,6 +977,7 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme
$zhanweiCount=0;//各个检查项目需要占用检查名额的总和 $zhanweiCount=0;//各个检查项目需要占用检查名额的总和
$itemSeatsQueue = []; // 队列:按顺序存储每个项目需要的座位数 [项目ID => 座位数] $itemSeatsQueue = []; // 队列:按顺序存储每个项目需要的座位数 [项目ID => 座位数]
$itemSeatsData = []; // 原始数据临时收集每个项目的use_seats和is_share_slot
$huchiList=[];//互斥item_id对应关系 $huchiList=[];//互斥item_id对应关系
$oldMainInfos = [];//临时存储原来的主表信息,用于改约 $oldMainInfos = [];//临时存储原来的主表信息,用于改约
//遍历多个s_list表id,前端多选,一次预约多个检查项目 //遍历多个s_list表id,前端多选,一次预约多个检查项目
@ -908,9 +1014,11 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme
//判断互斥暂时根据reg_num判断身份 //判断互斥暂时根据reg_num判断身份
//查询想要预约的项目 其自身code //查询想要预约的项目 其自身code
$item = DB::table('s_check_item')->where(['item_code' => $mainInfo->entrust_code, 'status' => 1, 'is_del' => 0])->first(); $item = DB::table('s_check_item')->where(['item_code' => $mainInfo->entrust_code, 'status' => 1, 'is_del' => 0])->first();
$itemSeatsQueue[$mainlistid]=$item->use_seats;
if (!$item) return \Yz::echoError1('此检查项目不可用'); if (!$item) return \Yz::echoError1('此检查项目不可用');
$zhanweiCount+=$item->use_seats; $itemSeatsData[$mainlistid] = [
'use_seats' => $item->use_seats,
'is_share_slot' => $item->is_share_slot ?? 0,
];
//医嘱开具后,预约时间需在设定的等待期之后,单位分钟 //医嘱开具后,预约时间需在设定的等待期之后,单位分钟
$entrust_time = $mainInfo->entrust_date . ' ' . $mainInfo->entrust_time; //医嘱时间 $entrust_time = $mainInfo->entrust_date . ' ' . $mainInfo->entrust_time; //医嘱时间
$date = new DateTime($entrust_time); $date = new DateTime($entrust_time);
@ -1024,6 +1132,73 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme
} }
// 共享号源项目合并计算只保留最大值其余设为0
$shareSlotIds = [];
$shareSlotMax = 0;
foreach ($itemSeatsData as $id => $data) {
if (!empty($data['is_share_slot'])) {
$shareSlotIds[] = $id;
$shareSlotMax = max($shareSlotMax, $data['use_seats']);
}
}
// 查询该排班下已有共享项目的 max
$existingSharedMax = 0;
$additionalNeeded = 0;
$regNum = $oldMainInfos[0]->reg_num ?? null;
if (!empty($shareSlotIds) && $regNum) {
$existingSharedItems = DB::table('s_list')
->join('s_check_item', 's_list.entrust', '=', 's_check_item.item_name')
->where('s_list.reg_num', $regNum)
->where('s_list.roster_id', $planid)
->where('s_list.list_status', 1)
->where('s_check_item.is_share_slot', 1)
->select('s_check_item.use_seats')
->get();
if ($existingSharedItems->isNotEmpty()) {
$existingSharedMax = $existingSharedItems->max('use_seats');
}
$overallMax = max($existingSharedMax, $shareSlotMax);
$additionalNeeded = max(0, $overallMax - $existingSharedMax);
}
// 找到 use_seats 最高的共享项目,将 max 分配给它
$maxShareSlotId = null;
$maxShareSeats = 0;
foreach ($itemSeatsData as $id => $data) {
if (!empty($data['is_share_slot']) && $data['use_seats'] > $maxShareSeats) {
$maxShareSeats = $data['use_seats'];
$maxShareSlotId = $id;
}
}
$zhanweiCount = 0;
foreach ($itemSeatsData as $id => $data) {
if (!empty($data['is_share_slot'])) {
if ($id === $maxShareSlotId) {
$itemSeatsQueue[$id] = $additionalNeeded;
$zhanweiCount += $additionalNeeded;
} else {
$itemSeatsQueue[$id] = 0;
}
} else {
$itemSeatsQueue[$id] = $data['use_seats'];
$zhanweiCount += $data['use_seats'];
}
}
Log::info('[YuYueDebug] YuYue 预约参数', [
'planid' => $planid,
'mainlistids' => $mainlistids,
'itemSeatsData' => $itemSeatsData,
'shareSlotMax' => $shareSlotMax,
'existingSharedMax' => $existingSharedMax,
'additionalNeeded' => $additionalNeeded,
'maxShareSlotId' => $maxShareSlotId,
'itemSeatsQueue' => $itemSeatsQueue,
'zhanweiCount' => $zhanweiCount,
]);
DB::beginTransaction(); DB::beginTransaction();
try { try {
if ($do_type == 2) { if ($do_type == 2) {
@ -1167,6 +1342,14 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme
return \Yz::echoError1('紧急预约失败:未找到匹配的预约渠道配置'); return \Yz::echoError1('紧急预约失败:未找到匹配的预约渠道配置');
} }
} }
Log::info('[YuYueDebug] 流分配结果', [
'plan_qudao_tempCount' => $plan_qudao_tempCount,
'weifenpeiCount' => $weifenpeiCount,
'itemChannelMap' => $itemChannelMap,
'roster_detail_counts' => array_map(function($c) { return ['id' => $c->id, 'type' => $c->appointment_type_id, 'count' => $c->count, 'used' => $c->used_count, 'locked' => $c->locked_count ?? 0]; }, $roster_detail_counts->toArray()),
]);
// --- 3. 最终校验 --- // --- 3. 最终校验 ---
if ($weifenpeiCount > 0) { if ($weifenpeiCount > 0) {
// 如果不是紧急模式,或者紧急模式但没找到渠道导致还有剩余 // 如果不是紧急模式,或者紧急模式但没找到渠道导致还有剩余
@ -1286,11 +1469,27 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme
'is_emergency' => $is_emergency 'is_emergency' => $is_emergency
]; ];
Log::info('[YuYueDebug] 保存预约 detail', [
'id' => $id,
'entrust' => $mainInfo->entrust ?? 'unknown',
'details' => $details,
'roster_id' => $planInfo->id,
]);
$u_mainList = DB::table('s_list')->where('id', $id)->update($u_data); $u_mainList = DB::table('s_list')->where('id', $id)->update($u_data);
if (!$u_mainList) { if (!$u_mainList) {
$list_all_success = false; $list_all_success = false;
break; break;
} }
// 更新后读回确认
$afterUpdate = DB::table('s_list')->where('id', $id)->value('appointment_use_plan_detail');
Log::info('[YuYueDebug] 更新后读回', [
'id' => $id,
'写入值' => json_encode($details),
'读回值' => $afterUpdate,
'affected' => $u_mainList,
]);
} }
if (!$list_all_success) { if (!$list_all_success) {
@ -1405,6 +1604,14 @@ public function CancelYuYue($MainListId, $reg_num,$do_user=null)
->lockForUpdate() ->lockForUpdate()
->first(); ->first();
Log::info('[YuYueDebug] CancelYuYue 读取主表', [
'MainListId' => $MainListId,
'entrust' => $mainInfo->entrust ?? 'null',
'list_status' => $mainInfo->list_status ?? 'null',
'appointment_use_plan_detail' => $mainInfo->appointment_use_plan_detail ?? 'null',
'roster_id' => $mainInfo->roster_id ?? 'null',
]);
if (!$mainInfo) { if (!$mainInfo) {
return \Yz::echoError1('医嘱不存在'); return \Yz::echoError1('医嘱不存在');
} }
@ -1415,6 +1622,12 @@ public function CancelYuYue($MainListId, $reg_num,$do_user=null)
$this->releaseSourceFromDetail($MainListId, $mainInfo); $this->releaseSourceFromDetail($MainListId, $mainInfo);
Log::info('[YuYueDebug] CancelYuYue 释放后', [
'MainListId' => $MainListId,
'entrust' => $mainInfo->entrust,
'释放结果' => 'releaseSourceFromDetail 已执行',
]);
$u_data = [ $u_data = [
'list_status' => 0, 'list_status' => 0,
'reservation_date' => null, 'reservation_date' => null,
@ -1465,6 +1678,135 @@ public function releaseSourceFromDetail($mainListId, $mainInfo = null)
} }
$useDetailJson = $mainInfo->appointment_use_plan_detail; $useDetailJson = $mainInfo->appointment_use_plan_detail;
Log::info('[YuYueDebug] releaseSourceFromDetail 入口', [
'mainListId' => $mainListId,
'entrust' => $mainInfo->entrust,
'useDetailJson' => $useDetailJson,
'reg_num' => $mainInfo->reg_num,
'roster_id' => $mainInfo->roster_id,
]);
// 共享号源逻辑:取消号源持有者时差值释放
$shareItem = DB::table('s_check_item')
->where(['item_code' => $mainInfo->entrust_code, 'status' => 1, 'is_del' => 0])
->select('is_share_slot', 'use_seats')
->first();
$isShareSlot = $shareItem && !empty($shareItem->is_share_slot);
if ($isShareSlot && !empty($useDetailJson) && $useDetailJson !== '[]') {
// 该共享项目是号源持有者:查询其他同排班同资源的共享项目
$otherSharedItems = DB::table('s_list')
->join('s_check_item', 's_list.entrust', '=', 's_check_item.item_name')
->where('s_list.reg_num', $mainInfo->reg_num)
->where('s_list.roster_id', $mainInfo->roster_id)
->where('s_list.id', '!=', $mainListId)
->where('s_list.list_status', 1)
->where('s_check_item.is_share_slot', 1)
->select('s_check_item.use_seats')
->get();
if ($otherSharedItems->isNotEmpty()) {
$remainingMax = $otherSharedItems->max('use_seats');
if ($remainingMax > 0) {
// 解析当前持有量
$useDetails = json_decode($useDetailJson, true);
if (!is_array($useDetails)) {
return $this->releaseSourceFallback($mainInfo);
}
$currentCount = 0;
foreach ($useDetails as $d) {
$currentCount += (int)($d['count'] ?? 0);
}
Log::info('[YuYueDebug] 共享持有者取消', [
'mainListId' => $mainListId,
'entrust' => $mainInfo->entrust,
'useDetails' => $useDetails,
'currentCount' => $currentCount,
'remainingMax' => $remainingMax,
'otherSharedCount' => $otherSharedItems->count(),
]);
// 只释放差值
$releaseCount = $currentCount - $remainingMax;
if ($releaseCount > 0) {
// 调整 detail 为只释放差值:从原始条目中按顺序扣除
$adjustedDetail = [];
$remainingToRelease = $releaseCount;
foreach ($useDetails as $d) {
$entryCount = (int)($d['count'] ?? 0);
$take = min($entryCount, $remainingToRelease);
if ($take > 0) {
$adjustedDetail[] = [
'roster_detail_count_id' => $d['roster_detail_count_id'],
'count' => $take
];
$remainingToRelease -= $take;
}
}
// 更新剩余某个共享项目为新持有者
// 新持有者的 detail = 原始条目中未被释放的剩余部分
$newHolder = DB::table('s_list')
->join('s_check_item', 's_list.entrust', '=', 's_check_item.item_name')
->where('s_list.reg_num', $mainInfo->reg_num)
->where('s_list.roster_id', $mainInfo->roster_id)
->where('s_list.id', '!=', $mainListId)
->where('s_list.list_status', 1)
->where('s_check_item.is_share_slot', 1)
->select('s_list.id')
->first();
if ($newHolder) {
// 有可转移的共享项目:只释放差值
$useDetailJson = json_encode($adjustedDetail);
$newHolderDetail = [];
$adjustmentIdx = 0;
foreach ($useDetails as $d) {
$entryCount = (int)($d['count'] ?? 0);
// 该条目被释放了多少
$releasedFromEntry = 0;
if ($adjustmentIdx < count($adjustedDetail) && $adjustedDetail[$adjustmentIdx]['roster_detail_count_id'] == $d['roster_detail_count_id']) {
$releasedFromEntry = $adjustedDetail[$adjustmentIdx]['count'];
$adjustmentIdx++;
}
$remainingInEntry = $entryCount - $releasedFromEntry;
if ($remainingInEntry > 0) {
$newHolderDetail[] = [
'roster_detail_count_id' => $d['roster_detail_count_id'],
'count' => $remainingInEntry
];
}
}
DB::table('s_list')
->where('id', $newHolder->id)
->update(['appointment_use_plan_detail' => json_encode($newHolderDetail)]);
}
// 没有可转移的共享项目:不修改 useDetailJson正常释放逻辑释放全部
} else {
// currentCount <= remainingMax按实际占用量正常释放全部
// 不修改 useDetailJson让正常释放逻辑处理
}
}
// remainingMax == 0正常释放全部
}
// 没有其他共享项目:正常释放全部
}
Log::info('[YuYueDebug] 进入正常释放逻辑', [
'mainListId' => $mainListId,
'entrust' => $mainInfo->entrust,
'useDetailJson' => $useDetailJson,
'isShareSlot' => $isShareSlot ? 'true' : 'false',
]);
if ($isShareSlot && empty($useDetailJson)) {
// 共享项目但不是号源持有者,不释放号源
return true;
}
if (empty($useDetailJson)) { if (empty($useDetailJson)) {
$fallbackResult = $this->releaseSourceFallback($mainInfo); $fallbackResult = $this->releaseSourceFallback($mainInfo);
return $fallbackResult; return $fallbackResult;
@ -1505,6 +1847,15 @@ public function releaseSourceFromDetail($mainListId, $mainInfo = null)
'updated_at' => date('Y-m-d H:i:s') 'updated_at' => date('Y-m-d H:i:s')
]); ]);
Log::info('[YuYueDebug] 释放号源', [
'mainListId' => $mainListId,
'entrust' => $mainInfo->entrust,
'rosterDetailCountId' => $rosterDetailCountId,
'countToRelease' => $countToRelease,
'currentVersion' => $currentVersion,
'affected' => $affected,
]);
if ($affected == 0) { if ($affected == 0) {
$retryRecord = DB::table('s_source_roster_detail_count')->where(['id' => $rosterDetailCountId])->first(); $retryRecord = DB::table('s_source_roster_detail_count')->where(['id' => $rosterDetailCountId])->first();
if (!$retryRecord) { if (!$retryRecord) {
@ -1543,6 +1894,12 @@ public function releaseSourceFromDetail($mainListId, $mainInfo = null)
} }
} }
Log::info('[YuYueDebug] releaseSourceFromDetail 返回', [
'mainListId' => $mainListId,
'entrust' => $mainInfo->entrust,
'allSuccess' => $allSuccess ? 'true' : 'false',
]);
return $allSuccess; return $allSuccess;
} }

@ -4,24 +4,32 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>检查预约回执单</title> <title>检查预约回执单</title>
<style> <style>
@page {
margin: 5mm;
}
body { body {
margin: 0; margin: 0;
padding: 0; padding: 0;
font-family: 'Microsoft YaHei', '微软雅黑', 'SimHei', '黑体', sans-serif; font-family: 'Microsoft YaHei', '微软雅黑', 'SimHei', '黑体', sans-serif;
font-size: 14px; font-size: 12px;
color: #333; color: #333;
} }
.page { .page {
page-break-after: always; page-break-after: always;
height: 100vh; width: 100%;
padding: 20px; height: 297mm;
box-sizing: border-box; box-sizing: border-box;
} }
.page:last-child { .page:last-child {
page-break-after: auto; page-break-after: auto;
} }
.PrintShenQingDan { .PrintShenQingDan {
height: 100%; width: 100%;
padding: 5mm 6mm;
box-sizing: border-box;
}
.PrintShenQingDan td {
vertical-align: top;
} }
</style> </style>
</head> </head>
@ -31,31 +39,31 @@
@foreach ($patient['rooms'] as $roomKey => $room) @foreach ($patient['rooms'] as $roomKey => $room)
<div class="page"> <div class="page">
<div class="PrintShenQingDan"> <div class="PrintShenQingDan">
<div style="padding-bottom: 5px; position: relative;"> <div style="padding-bottom: 6px; margin-top: 20px; position: relative;">
<div style="width: 100%; text-align: center; font-size: 26px;">秦皇岛市中医医院</div> <div style="width: 100%; text-align: center; font-size: 26px;">秦皇岛市中医医院</div>
<div style="width: 100%; text-align: center; font-size: 18px; font-weight: bold;">检查预约回执单</div> <div style="width: 100%; text-align: center; font-size: 22px; font-weight: bold; margin-top: 5px;">检查预约回执单</div>
<div style="width: 200px; height: 50px; position: absolute; right: 10px; top: 0;"> <div style="width: 251px; height: 69px; position: absolute; right: 15px; top: 0;">
<img src="data:image/png;base64,{{ $patient['barcode'] }}" style="display: block; margin: 0 auto; max-width: 100%; height: auto;" /> <img src="data:image/png;base64,{{ $patient['barcode'] }}" style="display: block; margin: 0 auto; width: 100%; height: auto;" />
<div style="text-align: center;">{{ $patient['barcode_text'] }}</div> <div style="text-align: center; font-size: 14px;">{{ $patient['barcode_text'] }}</div>
</div> </div>
</div> </div>
<div style="border-top: 1px solid #333; border-bottom: 1px solid #333; padding-left: 4px; padding-top: 5px; padding-bottom: 5px;"> <div style="border-top: 1px solid #333; border-bottom: 1px solid #333; padding: 5px 4px;">
<table style="border: none; font-size: 18px; width: 100%;"> <table style="border: none; font-size: 20px; width: 100%;">
<tr style="border: none;"> <tr style="border: none;">
<td style="border: none; width: 23%; text-align: left;"><span style="display: inline-block; width: 3em; letter-spacing: 0.5em;"></span>{{ $patient['patient_name'] }}</td> <td style="border: none; width: 25%; text-align: left;"><span style="display: inline-block; white-space: pre;"></span>{{ $patient['patient_name'] }}</td>
<td style="border: none; width: 37%; text-align: left;"><span style="display: inline-block; width: 3em; letter-spacing: 0.5em;"></span>{{ $patient['user_sex_label'] }}</td> <td style="border: none; width: 36%; text-align: left;"><span style="display: inline-block; white-space: pre;"></span>{{ $patient['user_sex_label'] }}</td>
<td style="border: none; width: 16%; text-align: left;"><span style="display: inline-block; width: 3em; letter-spacing: 0.5em;"></span>{{ $patient['age'] }}</td> <td style="border: none; width: 15%; text-align: left;"><span style="display: inline-block; white-space: pre;"></span>{{ $patient['age'] }}</td>
<td style="border: none; width: 24%; text-align: left;"><span style="display: inline-block; width: 4em;">病人类型</span>{{ $patient['patient_type_label'] }}</td> <td style="border: none; width: 24%; text-align: left;"><span style="display: inline-block;">病人类型</span>{{ $patient['patient_type_label'] }}</td>
</tr> </tr>
<tr style="border: none;"> <tr style="border: none;">
<td style="border: none; width: 23%; text-align: left;"><span style="display: inline-block; width: 3em;">{{ $patient['patient_type_label'] }}号</span>{{ $patient['patient_id'] }}</td> <td style="border: none; width: 25%; text-align: left;"><span style="display: inline-block;">{{ $patient['patient_type_label'] }}号</span>{{ $patient['patient_id'] }}</td>
@if ($patient['patient_type'] == 0) @if ($patient['patient_type'] == 0)
<td style="border: none; width: 33%; text-align: left;"><span style="display: inline-block; width: 3em; letter-spacing: 0.5em;"></span>{{ $patient['warddesc'] }}</td> <td style="border: none; width: 32%; text-align: left;"><span style="float: left; white-space: nowrap; margin-right: 4px;"><span style="white-space: pre;"></span></span>{{ $patient['warddesc'] }}</td>
<td style="border: none; width: 15%; text-align: left;"><span style="display: inline-block; width: 3em; letter-spacing: 0.5em;"></span>{{ $patient['bedno'] }}</td> <td style="border: none; width: 14%; text-align: left;"><span style="display: inline-block; white-space: pre;"></span>{{ $patient['bedno'] }}</td>
<td style="border: none; width: 29%; text-align: left; white-space: nowrap;"><span style="display: inline-block; width: 4em;">联系电话</span>{{ $patient['user_phone'] }}</td> <td style="border: none; width: 29%; text-align: left; white-space: nowrap;"><span style="display: inline-block;">联系电话</span>{{ $patient['user_phone'] }}</td>
@else @else
<td style="border: none; width: 41%; text-align: left;"><span style="display: inline-block; width: 4em;">联系电话</span>{{ $patient['user_phone'] }}</td> <td style="border: none; width: 40%; text-align: left;"><span style="display: inline-block;">联系电话</span>{{ $patient['user_phone'] }}</td>
<td style="border: none; width: 16%; text-align: left;"></td> <td style="border: none; width: 16%; text-align: left;"></td>
<td style="border: none; width: 24%; text-align: left;"></td> <td style="border: none; width: 24%; text-align: left;"></td>
@endif @endif
@ -63,32 +71,32 @@
</table> </table>
</div> </div>
<div style="border-bottom: 1px solid #333; padding-left: 4px; padding-top: 5px; padding-bottom: 5px;"> <div style="border-bottom: 1px solid #333; padding: 5px 4px;">
<table style="border: none;"> <table style="border: none;">
<tr style="border: none; vertical-align: top;"> <tr style="border: none; vertical-align: top;">
<td style="width: 15%; border: none; font-size: 20px; font-weight: 900; text-align: left; white-space: nowrap;">检查项目:</td> <td style="width: 15%; border: none; font-size: 22px; font-weight: 900; text-align: left; white-space: nowrap;">检查项目:</td>
<td style="border: none; font-size: 20px; text-align: left;">{{ $room['items_str'] }}</td> <td style="border: none; font-size: 22px; text-align: left;">{{ $room['items_str'] }}</td>
</tr> </tr>
<tr style="border: none; vertical-align: top;"> <tr style="border: none; vertical-align: top;">
<td style="width: 15%; border: none; font-size: 20px; font-weight: 900; text-align: left; white-space: nowrap;">预约时间:</td> <td style="width: 15%; border: none; font-size: 22px; font-weight: 900; text-align: left; white-space: nowrap;">预约时间:</td>
<td style="border: none; font-size: 20px; text-align: left;">{{ str_replace('-', '/', $room['reservation_date']) }} <td style="border: none; font-size: 22px; text-align: left;">{{ str_replace('-', '/', $room['reservation_date']) }}
@if ($room['period_begin'] && $room['period_end']) @if ($room['period_begin'] && $room['period_end'])
{{ $room['period_begin'] }}-{{ $room['period_end'] }} {{ $room['period_begin'] }}-{{ $room['period_end'] }}
@endif @endif
{{ $room['weekday_label'] }}</td> {{ $room['weekday_label'] }}</td>
</tr> </tr>
<tr style="border: none; vertical-align: top;"> <tr style="border: none; vertical-align: top;">
<td style="width: 15%; border: none; font-size: 20px; font-weight: 900; text-align: left; white-space: nowrap;">检查地点:</td> <td style="width: 15%; border: none; font-size: 22px; font-weight: 900; text-align: left; white-space: nowrap;">检查地点:</td>
<td style="border: none; font-size: 20px; text-align: left;">{{ $room['room_addr'] }}</td> <td style="border: none; font-size: 22px; text-align: left;">{{ $room['room_addr'] }}</td>
</tr> </tr>
</table> </table>
</div> </div>
<div style="padding-left: 4px; padding-top: 5px; padding-bottom: 5px;"> <div style="padding: 5px 4px;">
<table style="border: none;"> <table style="border: none;">
<tr style="border: none;"> <tr style="border: none;">
<td style="width: 15%; border: none; font-size: 20px; font-weight: 900; text-align: left; vertical-align: top;">温馨提示:</td> <td style="width: 15%; border: none; font-size: 22px; font-weight: 900; text-align: left; vertical-align: middle;">温馨提示:</td>
<td style="text-align: left; border: none; font-size: 18px;"> <td style="text-align: left; border: none; font-size: 20px; line-height: 1.5;">
<div>1、预约后请您及时缴费门诊患者预约成功后60分钟内不缴费系统会自动取消您的预约申请。自动取消后如需继续预约请到相关检查科室重新预约。</div> <div>1、预约后请您及时缴费门诊患者预约成功后60分钟内不缴费系统会自动取消您的预约申请。自动取消后如需继续预约请到相关检查科室重新预约。</div>
<div>2、预约时间为8点~10点的请8点到登记处签到预约时间为10点~12点的请10点前到登记处签到便于工作人员进行检查评估和准备。</div> <div>2、预约时间为8点~10点的请8点到登记处签到预约时间为10点~12点的请10点前到登记处签到便于工作人员进行检查评估和准备。</div>
<div>3、预约时间不是实际检查时间以现场登记后排队号为准。</div> <div>3、预约时间不是实际检查时间以现场登记后排队号为准。</div>
@ -97,10 +105,10 @@
</table> </table>
</div> </div>
<div style="border-top: 1px solid #333; padding-left: 8px; padding-top: 6px; padding-bottom: 6px; min-height: 50px;"> <div style="border-top: 1px solid #333; padding: 5px 4px; min-height: 50px;">
<div style="font-size: 20px; font-weight: 900;">检查须知:</div> <div style="font-size: 22px; font-weight: 900;">检查须知:</div>
@if (isset($room['check_notice']) && $room['check_notice'] !== '') @if (isset($room['check_notice']) && $room['check_notice'] !== '')
<div style="font-size: 18px;"> <div style="font-size: 20px; line-height: 1.5;">
@foreach(explode("\n", $room['check_notice']) as $line) @foreach(explode("\n", $room['check_notice']) as $line)
<div>{{ $line }}</div> <div>{{ $line }}</div>
@endforeach @endforeach
@ -108,7 +116,7 @@
@endif @endif
</div> </div>
<div style="text-align: right; border-top: 1px solid #333; font-size: 18px; padding-top: 5px; padding-bottom: 5px;"> <div style="text-align: right; border-top: 1px solid #333; font-size: 18px; padding: 5px 0;">
申请时间:{{ $room['entrust_date_time'] }} 申请时间:{{ $room['entrust_date_time'] }}
</div> </div>
</div> </div>

@ -1,17 +1,17 @@
<template> <template>
<div class="PrintShenQingDan"> <div class="PrintShenQingDan">
<div> <div style="margin-top: 20px;">
<div style="width: 100%;text-align: center;font-size: 22px;">秦皇岛市中医医院</div> <div style="width: 100%;text-align: center;font-size: 24px;">秦皇岛市中医医院</div>
<div style="width: 100%;text-align: center;font-size: 18px;font-weight: bold;">检查预约回执单</div> <div style="width: 100%;text-align: center;font-size: 20px;font-weight: bold;">检查预约回执单</div>
<div <div
style="width:200px;text-align: center;padding-bottom: 8px;-webkit-print-color-adjust: exact; position: absolute;right: 10px;top:0px;"> style="width:220px;text-align: center;padding-bottom: 8px;-webkit-print-color-adjust: exact; position: absolute;right: 10px;top:0px;">
<img :src="'data:image/png;base64,' + printInfo.barcode" <img :src="'data:image/png;base64,' + printInfo.barcode"
style="display: block; margin: 0 auto; max-width: 100%; height: auto;" /> style="display: block; margin: 0 auto; max-width: 100%; height: auto;" />
<div style="text-align: center">{{printInfo.patient_type == 0 ? printInfo.episodeid.slice(-10) : printInfo.reg_num}}</div> <div style="text-align: center">{{printInfo.patient_type == 0 ? printInfo.episodeid.slice(-10) : printInfo.reg_num}}</div>
</div> </div>
</div> </div>
<div style="border-top: 1px solid #333; border-bottom: 1px solid #333;padding-left: 4px;"> <div style="border-top: 1px solid #333; border-bottom: 1px solid #333;padding-left: 4px;">
<table style="border: none;font-size: 16px; width: 100%;"> <table style="border: none;font-size: 18px; width: 100%;">
<tr style="border: none;"> <tr style="border: none;">
<td style="border: none; text-align: left;">姓名{{printInfo.user_name}}</td> <td style="border: none; text-align: left;">姓名{{printInfo.user_name}}</td>
<td style="border: none; text-align: left;">性别{{printInfo.user_sex_label}}</td> <td style="border: none; text-align: left;">性别{{printInfo.user_sex_label}}</td>
@ -28,7 +28,7 @@
</tr> </tr>
</table> </table>
</div> </div>
<div style="border-bottom: 1px solid #333;font-size: 18px;padding-left: 8px;"> <div style="border-bottom: 1px solid #333;font-size: 20px;padding-left: 8px;">
<div>检查项目{{printInfo.entrust}}</div> <div>检查项目{{printInfo.entrust}}</div>
<div>预约时间{{printInfo.reservation_date}} <div>预约时间{{printInfo.reservation_date}}
{{printInfo.period_begin_time.substring(0, 5)}}-{{printInfo.period_end_time.substring(0, 5)}} {{printInfo.period_begin_time.substring(0, 5)}}-{{printInfo.period_end_time.substring(0, 5)}}
@ -39,8 +39,8 @@
<div style="padding-left: 4px;"> <div style="padding-left: 4px;">
<table style="border: none;"> <table style="border: none;">
<tr style="border: none;"> <tr style="border: none;">
<td style="width: 15%;border: none;font-size: 18px;font-weight: 700;text-align: left;">温馨提示</td> <td style="width: 15%;border: none;font-size: 20px;font-weight: 700;text-align: left;">温馨提示</td>
<td style="text-align: left;border: none;font-size: 16px;"> <td style="text-align: left;border: none;font-size: 18px;">
<div>1预约后请您及时缴费门诊患者预约成功后60分钟内不缴费系统会自动取消您的预约申请自动取消后如需继续预约请到相关检查科室重新预约</div> <div>1预约后请您及时缴费门诊患者预约成功后60分钟内不缴费系统会自动取消您的预约申请自动取消后如需继续预约请到相关检查科室重新预约</div>
<div>2预约时间为8点~10点的请8点到登记处签到预约时间为10点~12点的请10点前到登记处签到便于工作人员进行检查评估和准备</div> <div>2预约时间为8点~10点的请8点到登记处签到预约时间为10点~12点的请10点前到登记处签到便于工作人员进行检查评估和准备</div>
<div>3预约时间不是实际检查时间以现场登记后排队号为准</div> <div>3预约时间不是实际检查时间以现场登记后排队号为准</div>
@ -49,12 +49,12 @@
</table> </table>
</div> </div>
<div style="border-top: 1px solid #333;padding-left: 8px;"> <div style="border-top: 1px solid #333;padding-left: 8px;">
<div style="font-size: 18px;font-weight: 700;">检查须知</div> <div style="font-size: 20px;font-weight: 700;">检查须知</div>
<div style="font-size: 16px;"> <div style="font-size: 18px;">
腹部检查禁食4小时腹部盆腔泌尿系统检查请尽量饮水充盈肠道及膀胱危重病人需由家属陪同孕妇及婴幼儿请慎行检查 腹部检查禁食4小时腹部盆腔泌尿系统检查请尽量饮水充盈肠道及膀胱危重病人需由家属陪同孕妇及婴幼儿请慎行检查
</div> </div>
</div> </div>
<div style="text-align: right; border-top: 1px solid #333; font-size: 16px;"> <div style="text-align: right; border-top: 1px solid #333; font-size: 18px;">
申请时间{{printInfo.entrust_date}} {{printInfo.entrust_time}} 申请时间{{printInfo.entrust_date}} {{printInfo.entrust_time}}
</div> </div>
</div> </div>

@ -421,8 +421,7 @@
let plan_enable = false let plan_enable = false
if (matchingPlan) { if (matchingPlan) {
const availableCount = matchingPlan.count - matchingPlan.used_count if (matchingPlan.plan_enable === true) {
if (availableCount >= zhanWeiCount && availableCount >= totalUseSeats && matchingPlan.plan_enable === true) {
plan_enable = true plan_enable = true
} }
if (selectedPlanId.value == 0 || selectedPlanId.value == '' || selectedPlanId.value == null) { if (selectedPlanId.value == 0 || selectedPlanId.value == '' || selectedPlanId.value == null) {

@ -660,7 +660,7 @@
); );
let plan_enable = false let plan_enable = false
if (matchingPlan) { if (matchingPlan) {
if (matchingPlan.count - matchingPlan.used_count >= zwCount && matchingPlan.plan_enable===true) { if (matchingPlan.plan_enable===true) {
plan_enable = true plan_enable = true
} }
if(is_emergency===true && matchingPlan.plan_enable===true && canEmergency.value==true){ if(is_emergency===true && matchingPlan.plan_enable===true && canEmergency.value==true){
@ -694,7 +694,6 @@
// //
const firstAvailable = plans.find(v => const firstAvailable = plans.find(v =>
v.department_resources_name == activeZhenShi.value && v.department_resources_name == activeZhenShi.value &&
(v.count - v.used_count) >= zwCount &&
v.plan_enable === true v.plan_enable === true
); );
if (firstAvailable) { if (firstAvailable) {
@ -911,13 +910,6 @@
const plan = cachedPlans.value.find(v => v.id === planid) const plan = cachedPlans.value.find(v => v.id === planid)
if (!plan) return if (!plan) return
//
const remaining = plan.count - plan.used_count
if (remaining < zhanWeiCount.value) {
ElMessage.warning(`剩余号源不足,当前仅剩 ${remaining} 个号位,所选项目需 ${zhanWeiCount.value} 个号位`)
return
}
selectedPlanId.value = planid selectedPlanId.value = planid
highlightedPlanIds.value = [planid] highlightedPlanIds.value = [planid]
checkDaijianFuc() checkDaijianFuc()

@ -59,8 +59,9 @@
{{item.department_resources_name}} {{item.department_resources_name}}
</div> </div>
</div> </div>
<div v-loading="loading" ref="scrollContainer" style="border: 1px solid #efefef;width: 100%; overflow-x: auto; position: relative;"> <div style="flex: 1; min-width: 0;">
<div style="text-align: right; padding: 8px; font-size: 12px; color: #999;">数据格式占位/已用/总数</div> <div style="text-align: right; padding: 4px 8px; font-size: 12px; color: #999;">数据格式占位/已用/总数</div>
<div v-loading="loading" ref="scrollContainer" style="border: 1px solid #efefef; overflow-x: auto; position: relative;">
<table class="planTable" v-if="planTableData.length>0"> <table class="planTable" v-if="planTableData.length>0">
<tr style="background-color: #f1f1f1;position: relative;"> <tr style="background-color: #f1f1f1;position: relative;">
<td> <td>
@ -128,11 +129,12 @@
</tr> </tr>
</table> </table>
<div v-if="isDragging" class="drag-selection-overlay" :style="dragOverlayStyle"></div> <div v-if="isDragging" class="drag-selection-overlay" :style="dragOverlayStyle"></div>
<div v-if="planTableData.length==0" style="width: 100%;background-color: #fff;">> <div v-if="planTableData.length==0" style="width: 100%;background-color: #fff;">
<el-empty description="暂无号源" /> <el-empty description="暂无号源" />
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- 弹窗修改框--> <!-- 弹窗修改框-->
<el-dialog v-model="PlanDetailDialogVisible" title="修改" width="40%"> <el-dialog v-model="PlanDetailDialogVisible" title="修改" width="40%">
<div v-loading="loading"> <div v-loading="loading">
@ -568,8 +570,8 @@
dragStart.value = { dragStart.value = {
row: tr.rowIndex, row: tr.rowIndex,
col: td.cellIndex, col: td.cellIndex,
x: event.clientX - containerRect.left, x: event.clientX - containerRect.left + container.scrollLeft,
y: event.clientY - containerRect.top y: event.clientY - containerRect.top + container.scrollTop
} }
// //
selectedPlanArr.value = [cellData.id] selectedPlanArr.value = [cellData.id]
@ -580,8 +582,8 @@
const container = scrollContainer.value const container = scrollContainer.value
if (!container) return if (!container) return
const containerRect = container.getBoundingClientRect() const containerRect = container.getBoundingClientRect()
const currentX = event.clientX - containerRect.left const currentX = event.clientX - containerRect.left + container.scrollLeft
const currentY = event.clientY - containerRect.top const currentY = event.clientY - containerRect.top + container.scrollTop
// //
dragOverlayStyle.value = { dragOverlayStyle.value = {
left: Math.min(dragStart.value.x, currentX) + 'px', left: Math.min(dragStart.value.x, currentX) + 'px',

@ -59,8 +59,9 @@
{{item.department_resources_name}} {{item.department_resources_name}}
</div> </div>
</div> </div>
<div v-loading="loading" ref="scrollContainer" style="border: 1px solid #efefef;width: 100%; overflow-x: auto; position: relative;"> <div style="flex: 1; min-width: 0;">
<div style="text-align: right; padding: 8px; font-size: 12px; color: #999;">数据格式占位/已用/总数</div> <div style="text-align: right; padding: 4px 8px; font-size: 12px; color: #999;">数据格式占位/已用/总数</div>
<div v-loading="loading" ref="scrollContainer" style="border: 1px solid #efefef; overflow-x: auto; position: relative;">
<table class="planTable" v-if="planTableData.length>0"> <table class="planTable" v-if="planTableData.length>0">
<tr style="background-color: #f1f1f1;position: relative;"> <tr style="background-color: #f1f1f1;position: relative;">
<td> <td>
@ -128,11 +129,12 @@
</tr> </tr>
</table> </table>
<div v-if="isDragging" class="drag-selection-overlay" :style="dragOverlayStyle"></div> <div v-if="isDragging" class="drag-selection-overlay" :style="dragOverlayStyle"></div>
<div v-if="planTableData.length==0" style="width: 100%;background-color: #fff;">> <div v-if="planTableData.length==0" style="width: 100%;background-color: #fff;">
<el-empty description="暂无号源" /> <el-empty description="暂无号源" />
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- 弹窗修改框--> <!-- 弹窗修改框-->
<el-dialog v-model="PlanDetailDialogVisible" title="修改" width="40%"> <el-dialog v-model="PlanDetailDialogVisible" title="修改" width="40%">
<div v-loading="loading"> <div v-loading="loading">
@ -568,8 +570,8 @@
dragStart.value = { dragStart.value = {
row: tr.rowIndex, row: tr.rowIndex,
col: td.cellIndex, col: td.cellIndex,
x: event.clientX - containerRect.left, x: event.clientX - containerRect.left + container.scrollLeft,
y: event.clientY - containerRect.top y: event.clientY - containerRect.top + container.scrollTop
} }
// //
selectedPlanArr.value = [cellData.id] selectedPlanArr.value = [cellData.id]
@ -580,8 +582,8 @@
const container = scrollContainer.value const container = scrollContainer.value
if (!container) return if (!container) return
const containerRect = container.getBoundingClientRect() const containerRect = container.getBoundingClientRect()
const currentX = event.clientX - containerRect.left const currentX = event.clientX - containerRect.left + container.scrollLeft
const currentY = event.clientY - containerRect.top const currentY = event.clientY - containerRect.top + container.scrollTop
// //
dragOverlayStyle.value = { dragOverlayStyle.value = {
left: Math.min(dragStart.value.x, currentX) + 'px', left: Math.min(dragStart.value.x, currentX) + 'px',

@ -315,6 +315,22 @@
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
<el-dialog v-model="ConflictDialogVisible" title="时段冲突 - 生成失败" width="60%">
<div style="margin-bottom: 12px; color: #f56c6c;">
以下模板与已有号源存在时段冲突生成已取消请调整后重试
</div>
<el-table :data="ConflictData" border stripe max-height="400">
<el-table-column prop="date" label="日期" width="120" />
<el-table-column prop="weekname" label="星期" width="80" />
<el-table-column prop="new_time" label="模板时段" width="150" />
<el-table-column prop="existing_time" label="已有号源时段" width="150" />
</el-table>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="ConflictDialogVisible = false">确定</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="ZhanWeiDialogVisible" title="占位设置" width="40%"> <el-dialog v-model="ZhanWeiDialogVisible" title="占位设置" width="40%">
<div v-loading="loading"> <div v-loading="loading">
<el-form v-if="ZhanWeiInfo" label-width="120px" style="padding-right: 40px;"> <el-form v-if="ZhanWeiInfo" label-width="120px" style="padding-right: 40px;">
@ -416,6 +432,8 @@
let dateRange = ref([]) // let dateRange = ref([]) //
let CreatePlanDialogVisible = ref(false) let CreatePlanDialogVisible = ref(false)
let ConflictDialogVisible = ref(false) //
let ConflictData = ref([]) //
// //
let ZhanWeiDialogVisible = ref(false) let ZhanWeiDialogVisible = ref(false)
let ZhanWeiInfo = ref(null) let ZhanWeiInfo = ref(null)
@ -497,6 +515,11 @@
message: res.msg, message: res.msg,
type: 'success', type: 'success',
}) })
} else {
//
if (res.data && res.data.conflicts && res.data.conflicts.length > 0) {
ConflictData.value = res.data.conflicts
ConflictDialogVisible.value = true
} else { } else {
ElMessageBox.alert(res.msg, '提示', { ElMessageBox.alert(res.msg, '提示', {
// if you want to disable its autofocus // if you want to disable its autofocus
@ -505,6 +528,7 @@
dangerouslyUseHTMLString: true, dangerouslyUseHTMLString: true,
}) })
} }
}
}) })
} }
let searchInfo = ref({ let searchInfo = ref({

@ -315,6 +315,22 @@
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
<el-dialog v-model="ConflictDialogVisible" title="时段冲突 - 生成失败" width="60%">
<div style="margin-bottom: 12px; color: #f56c6c;">
以下模板与已有号源存在时段冲突生成已取消请调整后重试
</div>
<el-table :data="ConflictData" border stripe max-height="400">
<el-table-column prop="date" label="日期" width="120" />
<el-table-column prop="weekname" label="星期" width="80" />
<el-table-column prop="new_time" label="模板时段" width="150" />
<el-table-column prop="existing_time" label="已有号源时段" width="150" />
</el-table>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="ConflictDialogVisible = false">确定</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="ZhanWeiDialogVisible" title="占位设置" width="40%"> <el-dialog v-model="ZhanWeiDialogVisible" title="占位设置" width="40%">
<div v-loading="loading"> <div v-loading="loading">
<el-form v-if="ZhanWeiInfo" label-width="120px" style="padding-right: 40px;"> <el-form v-if="ZhanWeiInfo" label-width="120px" style="padding-right: 40px;">
@ -416,6 +432,8 @@
let dateRange = ref([]) // let dateRange = ref([]) //
let CreatePlanDialogVisible = ref(false) let CreatePlanDialogVisible = ref(false)
let ConflictDialogVisible = ref(false) //
let ConflictData = ref([]) //
// //
let ZhanWeiDialogVisible = ref(false) let ZhanWeiDialogVisible = ref(false)
let ZhanWeiInfo = ref(null) let ZhanWeiInfo = ref(null)
@ -498,6 +516,11 @@
message: res.msg, message: res.msg,
type: 'success', type: 'success',
}) })
} else {
//
if (res.data && res.data.conflicts && res.data.conflicts.length > 0) {
ConflictData.value = res.data.conflicts
ConflictDialogVisible.value = true
} else { } else {
ElMessageBox.alert(res.msg, '提示', { ElMessageBox.alert(res.msg, '提示', {
// if you want to disable its autofocus // if you want to disable its autofocus
@ -506,6 +529,7 @@
dangerouslyUseHTMLString: true, dangerouslyUseHTMLString: true,
}) })
} }
}
}) })
} }
let searchInfo = ref({ let searchInfo = ref({

@ -131,6 +131,11 @@
:min="1" :max="99" style="width: 200px;" /> :min="1" :max="99" style="width: 200px;" />
<div style="margin-left: 4px;">预约时占用的号源数量默认1</div> <div style="margin-left: 4px;">预约时占用的号源数量默认1</div>
</div> </div>
<div class="row"><span class="title">共享号源</span>
<el-checkbox v-model="selectedItemInfo.is_share_slot" :true-value="1" :false-value="0">
项目按人数占用号源
</el-checkbox>
</div>
<div class="row"><span class="title">等待时间</span><el-input v-model="selectedItemInfo.check_begin_time" <div class="row"><span class="title">等待时间</span><el-input v-model="selectedItemInfo.check_begin_time"
placeholder="开医嘱后,等待时间" style="width: 200px;" /> placeholder="开医嘱后,等待时间" style="width: 200px;" />
<div style="margin-left: 4px;">医嘱开具后预约时间需在设定的等待期之后,单位分钟</div> <div style="margin-left: 4px;">医嘱开具后预约时间需在设定的等待期之后,单位分钟</div>
@ -355,7 +360,8 @@
check_begin_time: '', check_begin_time: '',
check_notice: '', check_notice: '',
warm_tips: '', warm_tips: '',
use_seats: 1 use_seats: 1,
is_share_slot: 0
}) })
//list //list
let BigClassList = ref([]); let BigClassList = ref([]);
@ -652,6 +658,7 @@
selectedItemInfo.value.reservation_method = row.reservation_method selectedItemInfo.value.reservation_method = row.reservation_method
selectedItemInfo.value.check_time = row.check_time selectedItemInfo.value.check_time = row.check_time
selectedItemInfo.value.use_seats = row.use_seats || 1 selectedItemInfo.value.use_seats = row.use_seats || 1
selectedItemInfo.value.is_share_slot = row.is_share_slot ?? 0
if (row.check_begin_time == '' || row.check_begin_time == null) { if (row.check_begin_time == '' || row.check_begin_time == null) {
row.check_begin_time = 0 row.check_begin_time = 0
} }

@ -117,6 +117,11 @@
:min="1" :max="99" style="width: 200px;" /> :min="1" :max="99" style="width: 200px;" />
<div style="margin-left: 4px;">预约时占用的号源数量默认1</div> <div style="margin-left: 4px;">预约时占用的号源数量默认1</div>
</div> </div>
<div class="row"><span class="title">共享号源</span>
<el-checkbox v-model="selectedItemInfo.is_share_slot" :true-value="1" :false-value="0">
项目按人数占用号源
</el-checkbox>
</div>
<div class="row"><span class="title">等待时间</span><el-input v-model="selectedItemInfo.check_begin_time" <div class="row"><span class="title">等待时间</span><el-input v-model="selectedItemInfo.check_begin_time"
placeholder="开医嘱后,等待时间" style="width: 200px;" /> placeholder="开医嘱后,等待时间" style="width: 200px;" />
<div style="margin-left: 4px;">医嘱开具后预约时间需在设定的等待期之后,单位分钟</div> <div style="margin-left: 4px;">医嘱开具后预约时间需在设定的等待期之后,单位分钟</div>
@ -328,7 +333,8 @@
check_begin_time: '', check_begin_time: '',
check_notice: '', check_notice: '',
warm_tips: '', warm_tips: '',
use_seats: 1 use_seats: 1,
is_share_slot: 0
}) })
//list //list
let BigClassList = ref([]); let BigClassList = ref([]);
@ -601,6 +607,7 @@
selectedItemInfo.value.reservation_method = row.reservation_method selectedItemInfo.value.reservation_method = row.reservation_method
selectedItemInfo.value.check_time = row.check_time selectedItemInfo.value.check_time = row.check_time
selectedItemInfo.value.use_seats = row.use_seats || 1 selectedItemInfo.value.use_seats = row.use_seats || 1
selectedItemInfo.value.is_share_slot = row.is_share_slot ?? 0
if (row.check_begin_time == '' || row.check_begin_time == null) { if (row.check_begin_time == '' || row.check_begin_time == null) {
row.check_begin_time = 0 row.check_begin_time = 0
} }

Loading…
Cancel
Save