sign_image_path = "basic/file/hospital_signature.png"; $this->entity_id = "534534546"; $this->card_num = "91510106MABTJY4K9R"; }elseif($type == 2){ // 用户 $params = array(); $params['user_id'] = $user_id; $user_doctor_info = UserDoctorInfo::getOne($params); if (empty($user_doctor_info)) { throw new BusinessException("用户数据错误"); } $this->sign_image_path = substr($user_doctor_info['sign_image'], 1, strlen($user_doctor_info['sign_image']) - 1); $app_env = config('app_env','dev'); if ($app_env == 'prod'){ $this->entity_id = $user_doctor_info['user_id']; }else{ $this->entity_id = "516904855112556544"; } $this->card_num = $user_doctor_info['card_num']; } elseif ($type == 3){ $params = array(); $params['user_id'] = $user_id; $user_pharmacist_info = UserPharmacistInfo::getOne($params); if (empty($user_pharmacist_info)) { throw new BusinessException("用户数据错误"); } // 去除用户签名图片第一个/ oss不识别 $this->sign_image_path = substr($user_pharmacist_info['sign_image'], 1, strlen($user_pharmacist_info['sign_image']) - 1); $this->entity_id = $user_id; $this->card_num = $user_pharmacist_info['card_num']; } else{ throw new BusinessException("用户类型错误"); } if (empty($this->sign_image_path) || empty($this->entity_id)) { throw new BusinessException("无签名图片/用户唯一标识"); } $order_prescription_id = $order_prescription['order_prescription_id']; // 创建协程客户端 $wg = new WaitGroup(); // 创建通道 $channel = new Channel(); $wg->add(2); // 获取医生自定义科室名称 $doctor_id = $order_prescription['doctor_id']; co(function () use ($wg,$channel,$doctor_id) { defer(function() use ($wg) { $wg->done(); }); // 获取医生数据 $params = array(); $params['doctor_id'] = $doctor_id; $user_doctor = UserDoctor::getOne($params); if (empty($user_doctor)) { $channel->push('医生数据错误'); return; } // 获取医生自定义科室数据 $params = array(); $params['department_custom_id'] = $user_doctor['department_custom_id']; $hospital_department_custom = HospitalDepartmentCustom::getOne($params); if (empty($hospital_department_custom)) { $channel->push('医生自定义数据错误'); return; } $this->department_name = $hospital_department_custom['department_name'] ?: ""; }); // 获取过敏史 $order_inquiry_id = $order_prescription['order_inquiry_id']; co(function () use ($wg,$channel,$order_inquiry_id) { defer(function() use ($wg) { $wg->done(); }); $params = array(); $params['order_inquiry_id'] = $order_inquiry_id; $order_inquiry_case = OrderInquiryCase::getOne($params); if (empty($order_inquiry_case)) { $channel->push('处方病例数据错误'); return; } $this->allergy_history = $order_inquiry_case['allergy_history'] ?: "无"; }); // 结束 $wg->wait(); // 判断通道是否存在异常数据 $res = $channel->isEmpty(); if (!$res){ // 读取通道数据 $data = $channel->pop(); // 关闭channel通道 $channel->close(); throw new BusinessException($data); }else{ // 关闭channel通道 $channel->close(); } // 获取处方关联疾病名称 $params = array(); $params['order_prescription_id'] = $order_prescription_id; $order_prescription_icd = OrderPrescriptionIcd::getList($params); if (empty($order_prescription_icd)) { throw new BusinessException("处方疾病数据错误"); } $this->icd_name = ""; $icd_name = array_column($order_prescription_icd->toArray(), 'icd_name'); if (!empty($icd_name)) { if (count($icd_name) > 1) { $this->icd_name = implode(';', $icd_name); } else { $this->icd_name = $icd_name[0]; } } // 获取处方药品数据 $params = array(); $params['order_prescription_id'] = $order_prescription_id; $order_prescription_product = OrderPrescriptionProduct::getList($params); if (empty($order_prescription_product)) { throw new BusinessException("处方药品数据错误"); } $this->order_prescription_product = $order_prescription_product->toArray(); // 处方pdf本地地址 $this->prescription_pdf_local_path = "./runtime/file/prescription/" . $order_prescription_id . '.pdf'; // 处方pdf oss地址 $this->prescription_pdf_oss_path = "applet/prescription/" . $order_prescription_id. '.pdf'; } /** * 获取云证书签名+验证云证书签名 * @param array|object $order_prescription */ public function getVerifyCertSign(array|object $order_prescription) { $CaOnline = new CaOnline(); // 获取云证书签名 $data = array(); $data['created_at'] = $order_prescription['doctor_created_time']; $data['department_custom_name'] = $this->department_name; $data['user_name'] = $order_prescription['patient_name']; $data['sex'] = sexToStringSex($order_prescription['patient_sex']); $data['age'] = $order_prescription['patient_age']; $data['allergy_history'] = $this->allergy_history; $data['icd_name'] = $this->icd_name; $data['doctor_advice'] = $order_prescription['doctor_advice'] ?: "无"; // 商品数据 $data['product'] = array(); foreach ($this->order_prescription_product as $item) { $product = array(); $product['product_name'] = $item['product_name'] . "(" . $item['product_spec'] . ")"; // 商品名称+商品规格 $product['single_unit'] = $item['single_unit'] ?: ""; // 单次剂量(例:1次1包) $product['frequency_use'] = $item['frequency_use'] ?: ""; // 使用频率(例:1天3次) $product['single_use'] = $item['single_use'] ?: ""; // 单次用法(例:口服) $product['prescription_product_num'] = $item['prescription_product_num'] . $item['packaging_unit']; // 商品数量 + 基本包装单位(例:盒/瓶) $data['product'][] = $product; } dump($this->entity_id); $cert_sign_result = $CaOnline->getCertSign($this->entity_id, $this->entity_id, $data); // 验证云证书签名 验证无需处理,只要不返回错误即可 $CaOnline->verifyPkcs7($cert_sign_result['signP7'], $data); $this->cert_serial_number = $cert_sign_result['certSerialnumber']; } /** * 生成处方图片+处方图片生成pdf * @param array|object $order_prescription * @return string */ public function createPrescriptionImgPdf(array|object $order_prescription): string { // 打开基础处方图片 $prescription_image = fopen("./extend/Ca/prescription.jpg", 'r+'); $manager = new ImageManager(); $image = $manager->make($prescription_image); $fontPath = './extend/Ca/msyh.ttf'; // 处方号 $image->text($order_prescription['prescription_code'], 1480, 540, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(60); $font->align('left'); }); // 日期 $image->text(date('Y-m-d', strtotime($order_prescription['doctor_created_time'])), 354, 675, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(60); $font->align('left'); }); // 科室 $image->text($this->department_name ?: "", 1385, 675, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(60); $font->align('left'); }); // 姓名 $image->text($order_prescription['patient_name'], 354, 795, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(60); $font->align('left'); }); // 性别 $image->text(sexToStringSex($order_prescription['patient_sex']), 1385, 790, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(60); $font->align('left'); }); // 年龄 $image->text($order_prescription['patient_age'], 354, 900, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(60); $font->align('left'); }); // 过敏史 $image->text($this->allergy_history ?: "无", 405, 1030, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(60); $font->align('left'); }); // 初步诊断 $image->text($this->icd_name, 445, 1145, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(60); $font->align('left'); }); // 医生建议 $image->text($order_prescription['doctor_advice'], 445, 1252, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(60); $font->align('left'); }); // 商品数据 foreach ($this->order_prescription_product as $key => $item) { $x_axis = 229; $y_axis = 1600 + $key * 250; $x_axis_num = 1900;// 数量使用 // 商品名称 $image->text($item['product_name'], $x_axis, $y_axis, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(50); $font->align('left'); }); $image->text("X" . $item['prescription_product_num'] . $item['packaging_unit'], $x_axis_num, $y_axis, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(50); $font->align('left'); }); // 用量 $image->text("用量:" . $item['single_unit'] . " " . $item['frequency_use'], $x_axis, $y_axis + 70, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(50); $font->align('left'); }); // 用法 $image->text("用法:" . $item['single_use'], $x_axis, $y_axis + 140, function ($font) use ($fontPath) { $font->file($fontPath); $font->size(50); $font->align('left'); }); } // 生成图片 $img_result = (string)$image->encode('png', 75); // 上传处方图片至oss $oss = new Oss(); $prescription_img_oss_filename = "applet/prescription/" . $order_prescription['order_prescription_id'] . '.' . 'jpg'; $prescription_img_oss_path = $oss->putObject($prescription_img_oss_filename, $img_result); $prescription_img_oss_path = '/' . $prescription_img_oss_path; // 图片生成pdf $pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false); $pdf->AddPage(); $pdf->Image('@' . $img_result, 10, 10, 0, 0, '', '', '', false, 300, '', false, false, 0, false, false, false); $prescription_pdf_local_filename = $order_prescription['order_prescription_id'] . '.' . 'pdf'; $prescription_pdf_local_path = BASE_PATH . "/runtime/file/prescription/"; $res = mkdirs($prescription_pdf_local_path); if (!$res){ throw new BusinessException("处方临时目录创建失败"); } // 图片生成的处方pdf存储为本地文件 runtime目录下 $pdf->Output($prescription_pdf_local_path . $prescription_pdf_local_filename, "F"); return $prescription_img_oss_path; } /** * 下载Oss中处方pdf * @return void */ public function downOssPdfToLocal(): void { $oss = new Oss(); $oss->getObjectToLocal($this->prescription_pdf_oss_path, $this->prescription_pdf_local_path); } /** * 下载CA中pdf至本地文件 * @param string $file_id * @return void */ public function downCaPdfToLocal(string $file_id): void { $CaOnline = new CaOnline(); $prescription_pdf_result = $CaOnline->getSignedFile($this->entity_id, $file_id); $file = fopen($this->prescription_pdf_local_path, "w"); fwrite($file, $prescription_pdf_result); fclose($file); } /** * 下载CA中的pdf并上传至oss * @param string $file_id * @return string oss地址 */ public function downCaPdfToOss(string $file_id): string { $CaOnline = new CaOnline(); $prescription_pdf_result = $CaOnline->getSignedFile($this->entity_id, $file_id); // 上传oss $oss = new Oss(); return $oss->putObject($this->prescription_pdf_oss_path, $prescription_pdf_result); } /** * 进行处方pdf签章 * @param string|int $type 类型 1:医院 2:医生 3:药师 * @return string 文件id */ public function addSignPdf(string|int $type): string { $oss = new Oss(); if ($type == 1){ $style = "image/resize,w_300,h_300"; }else{ $style = "image/resize,m_lfit,w_100,h_350"; } $sign_image = $oss->getCusTomObjectToRAM($this->sign_image_path, $style); $sign_image = base64_encode($sign_image); if (!$sign_image) { throw new BusinessException("签名图片下载失败"); } if ($type == 1){ // 医院 $llx = "370"; // 左边底部X坐标 控制左右(越小越左) $lly = "210"; // 左边底部Y坐标 控制上下(越小越下) $urx = "520"; // 右边上部x坐标 $ury = "360"; // 右边上部y坐标 } elseif ($type == 2){ // 医生端 $llx = "120"; // 左边底部X坐标 $lly = "190"; // 左边底部Y坐标 $urx = "190"; // 右边上部x坐标 $ury = "140"; // 右边上部y坐标 }else{ // 药师端 $llx = "350"; // 左边底部X坐标 $lly = "190"; // 左边底部Y坐标 $urx = "440"; // 右边上部x坐标 $ury = "140"; // 右边上部y坐标 } $sign_param = [ [ "llx" => $llx, // 左边底部X坐标 "lly" => $lly, // 左边底部Y坐标 "urx" => $urx, // 右边上部x坐标 "ury" => $ury, // 右边上部y坐标 "pageList" => [1], "sealImg" => $sign_image ], ]; $CaOnline = new CaOnline(); // 检测是否已添加签章配置 $params = array(); $params['cert_serial_number'] = $this->cert_serial_number; $user_ca_cert = UserCaCert::getOne($params); if (empty($user_ca_cert)){ throw new BusinessException("未申请证书"); } if ($user_ca_cert['is_sign_config'] == 0){ // 添加签章配置 $data = array(); $data['sign_param'] = json_encode($sign_param); $data['seal_img'] = $sign_image; $CaOnline->addUserSignConfig($this->entity_id,$this->card_num,$data); $params = array(); $params['cert_id'] = $user_ca_cert['cert_id']; $data = array(); $data['sign_config'] = json_encode($sign_param); $data['is_sign_config'] = 1; UserCaCert::edit($params,$data); } // 打开处方pdf文件 $pdf_file = fopen($this->prescription_pdf_local_path, 'r'); if (!$pdf_file) { throw new BusinessException("处方pdf打开失败"); } // 处方pdf进行签章 $data = array(); $data['sign_param'] = json_encode($sign_param); $data['pdf_file'] = $pdf_file; $sign_pdf_result = $CaOnline->addSignPdf($this->entity_id, $data); if (empty($sign_pdf_result[0]['fileId'])) { throw new BusinessException("处方签章失败"); } return $sign_pdf_result[0]['fileId']; } }