diff --git a/.gitignore b/.gitignore index 70b4f13..4ef58b1 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ vendor/ .DS_Store .phpunit* *.cache +extend/Ca/msyh.ttf \ No newline at end of file diff --git a/app/Amqp/Consumer/AutoFinishInquiryDelayDirectConsumer.php b/app/Amqp/Consumer/AutoFinishInquiryDelayDirectConsumer.php index b4fe764..7b9659f 100644 --- a/app/Amqp/Consumer/AutoFinishInquiryDelayDirectConsumer.php +++ b/app/Amqp/Consumer/AutoFinishInquiryDelayDirectConsumer.php @@ -93,6 +93,14 @@ class AutoFinishInquiryDelayDirectConsumer extends ConsumerMessage return Result::DROP; } + // 获取医生数据 + $params = array(); + $params['doctor_id'] = $order_inquiry['doctor_id']; + $user_doctor = UserDoctor::getOne($params); + if (empty($user_doctor)){ + Log::getInstance("queue-AutoFinishInquiry")->error("医生为空"); + return Result::DROP; + } Db::beginTransaction(); try { @@ -110,22 +118,34 @@ class AutoFinishInquiryDelayDirectConsumer extends ConsumerMessage return Result::ACK; } - // 处理统计问题 + /** + * 处理统计问题。规则: + * 1、金额大于0 + * 2、快速、购药类型下非坐班医生 + */ if ($order_inquiry['amount_total'] > 0) { - // 处理医生账户总表 - $res = $this->handleDoctorAccount($order_inquiry); - if (!$res) { - Db::rollBack(); - Log::getInstance("queue-AutoFinishInquiry")->error("处理医生账户总表失败"); - return Result::REQUEUE; + $is_handle_doctor_account = 1; + + if ($user_doctor['is_platform_deep_cooperation'] == 1 && in_array($order_inquiry['inquiry_type'],[2,4])){ + $is_handle_doctor_account = 0; } - // 处理医生账户表-日 - $res = $this->handleDoctorAccountDay($order_inquiry); - if (!$res) { - Db::rollBack(); - Log::getInstance("queue-AutoFinishInquiry")->error("处理医生账户表-日失败"); - return Result::REQUEUE; + if ($is_handle_doctor_account == 1){ + // 处理医生账户总表 + $res = $this->handleDoctorAccount($order_inquiry); + if (!$res) { + Db::rollBack(); + Log::getInstance("queue-AutoFinishInquiry")->error("处理医生账户总表失败"); + return Result::REQUEUE; + } + + // 处理医生账户表-日 + $res = $this->handleDoctorAccountDay($order_inquiry); + if (!$res) { + Db::rollBack(); + Log::getInstance("queue-AutoFinishInquiry")->error("处理医生账户表-日失败"); + return Result::REQUEUE; + } } } @@ -162,7 +182,7 @@ class AutoFinishInquiryDelayDirectConsumer extends ConsumerMessage Db::commit(); Log::getInstance("queue-AutoFinishInquiry")->info("成功"); - } catch (\Exception $e) { + } catch (\Throwable $e) { Db::rollBack(); Log::getInstance("queue-AutoFinishInquiry")->error("错误:" . $e->getMessage()); return Result::REQUEUE; // 重回队列 @@ -187,6 +207,8 @@ class AutoFinishInquiryDelayDirectConsumer extends ConsumerMessage */ protected function handleDoctorAccount(array|object $order_inquiry): bool { + $amount_total = bcmul((string)$order_inquiry['amount_total'],"0.75",8); + $params = array(); $params['doctor_id'] = $order_inquiry['doctor_id']; $doctor_account = DoctorAccount::getOne($params); @@ -194,8 +216,8 @@ class AutoFinishInquiryDelayDirectConsumer extends ConsumerMessage // 首次 $data = array(); $data['doctor_id'] = $order_inquiry['doctor_id']; - $data['total_amount'] = $order_inquiry['amount_total'] * 0.75; - $data['balance_account'] = $order_inquiry['amount_total'] * 0.75; + $data['total_amount'] = $amount_total; + $data['balance_account'] = $amount_total; $data['applied_withdrawal_amount'] = 0; $data['actual_withdrawal_amount'] = 0; $data['income_tax'] = 0; @@ -208,11 +230,12 @@ class AutoFinishInquiryDelayDirectConsumer extends ConsumerMessage // 总金额(已结束订单的总金额) $params = array(); $params['account_id'] = $doctor_account['account_id']; - DoctorAccount::inc($params, 'total_amount', $order_inquiry['amount_total'] * 0.75); + DoctorAccount::inc($params, 'total_amount', (float)$amount_total); // 账户余额 - DoctorAccount::inc($params, 'balance_account', $order_inquiry['amount_total'] * 0.75); + DoctorAccount::inc($params, 'balance_account', (float)$amount_total); } + return true; } @@ -223,6 +246,8 @@ class AutoFinishInquiryDelayDirectConsumer extends ConsumerMessage */ protected function handleDoctorAccountDay(array|object $order_inquiry): bool { + $amount_total = bcmul((string)$order_inquiry['amount_total'],"0.75",8); + $params = array(); $params['doctor_id'] = $order_inquiry['doctor_id']; $params['date'] = date('Y-m-d', strtotime($order_inquiry['created_at'])); @@ -235,7 +260,7 @@ class AutoFinishInquiryDelayDirectConsumer extends ConsumerMessage $data['month'] = date('m', strtotime($order_inquiry['created_at'])); $data['day'] = date('d', strtotime($order_inquiry['created_at'])); $data['date'] = date('Y-m-d', strtotime($order_inquiry['created_at'])); - $data['total_amount'] = $order_inquiry['amount_total'] * 0.75; + $data['total_amount'] = $amount_total; $doctor_account_day = DoctorAccountDay::addDoctorAccountDay($data); if (empty($doctor_account_day)) { return false; @@ -244,7 +269,7 @@ class AutoFinishInquiryDelayDirectConsumer extends ConsumerMessage // 非当日首次 $params = array(); $params['account_detail_id'] = $doctor_account_day['account_detail_id']; - DoctorAccountDay::inc($params, 'total_amount', $order_inquiry['amount_total'] * 0.75); + DoctorAccountDay::inc($params, 'total_amount', (float)$amount_total); } return true; @@ -307,7 +332,7 @@ class AutoFinishInquiryDelayDirectConsumer extends ConsumerMessage * 处理回写患者病例 * 回写失败不做处理 * @param array|object $order_inquiry - * @return void + * @return bool */ protected function handleOrderInquiryCase(array|object $order_inquiry): bool { @@ -551,7 +576,7 @@ class AutoFinishInquiryDelayDirectConsumer extends ConsumerMessage return true; }catch (\Throwable $e){ Log::getInstance("queue-AutoFinishInquiry")->error($e->getMessage()); - return false; + return true; } } diff --git a/app/Amqp/Consumer/CancelUnInquiryOrdersDelayDirectConsumer.php b/app/Amqp/Consumer/CancelUnInquiryOrdersDelayDirectConsumer.php index 9480f76..dff5531 100644 --- a/app/Amqp/Consumer/CancelUnInquiryOrdersDelayDirectConsumer.php +++ b/app/Amqp/Consumer/CancelUnInquiryOrdersDelayDirectConsumer.php @@ -66,19 +66,6 @@ class CancelUnInquiryOrdersDelayDirectConsumer extends ConsumerMessage return Result::ACK; } - // 检测锁定 - $redis = $this->container->get(Redis::class); - $redis_key = "order_inquiry_lock_" . $data['order_inquiry_id']; - $redis_lock = $redis->setnx($redis_key,1); - // 设置过期时间 - $redis->expire($redis_key,3); - if (!$redis_lock){ - // 设置失败,表示已经设置该值 - Db::rollBack(); - Log::getInstance()->error("取消未接诊问诊订单失败:正在锁定中" ); - return Result::REQUEUE; - } - // 检测订单状态 if ($order_inquiry['inquiry_status'] == 7) { // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) diff --git a/app/Amqp/Consumer/SendStationMessageConsumer.php b/app/Amqp/Consumer/SendStationMessageConsumer.php index 276bd46..842a5f5 100644 --- a/app/Amqp/Consumer/SendStationMessageConsumer.php +++ b/app/Amqp/Consumer/SendStationMessageConsumer.php @@ -26,16 +26,15 @@ class SendStationMessageConsumer extends ConsumerMessage * @param $data * @param AMQPMessage $message * @return string - * @throws GuzzleException */ public function consumeMessage($data, AMQPMessage $message): string { - Log::getInstance()->info("开始执行 站内消息推送 队列:" . json_encode($data, JSON_UNESCAPED_UNICODE)); + Log::getInstance("queue-SendStationMessage")->info("开始:" . json_encode($data, JSON_UNESCAPED_UNICODE)); // 验证推送参数 $res = $this->checkPushParams($data); if (!$res){ - Log::getInstance()->error("站内消息推送失败:入参错误"); + Log::getInstance("queue-SendStationMessage")->error("站内消息推送失败:入参错误"); return Result::DROP; } @@ -44,7 +43,7 @@ class SendStationMessageConsumer extends ConsumerMessage $params['user_id'] = $data['user_id']; $user = User::getOne($params); if(empty($user)){ - Log::getInstance()->error("站内消息推送失败:推送用户信息错误"); + Log::getInstance("queue-SendStationMessage")->error("站内消息推送失败:推送用户信息错误"); return Result::DROP; } @@ -58,7 +57,7 @@ class SendStationMessageConsumer extends ConsumerMessage // 患者系统消息 $message_type = 5; }else{ - Log::getInstance()->error("站内消息推送失败:消息类型错误"); + Log::getInstance("queue-SendStationMessage")->error("站内消息推送失败:消息类型错误"); $this->saveErrorPushLog($user['user_type'],$data,"消息类型错误"); return Result::DROP; } @@ -89,11 +88,11 @@ class SendStationMessageConsumer extends ConsumerMessage // 新增成功通知消息表 $this->saveMessageNotice($user->toArray(),$data); - Log::getInstance()->info("站内消息推送成功"); + Log::getInstance("queue-SendStationMessage")->info("站内消息推送成功"); $this->saveSuccessPushLog($user['user_type'],$data); } catch (\Exception $e) { - Log::getInstance()->error("站内消息推送执行失败:" . $e->getMessage()); + Log::getInstance("queue-SendStationMessage")->error("站内消息推送执行失败:" . $e->getMessage()); $this->saveErrorPushLog($user['user_type'],$data,$e->getMessage()); @@ -154,7 +153,7 @@ class SendStationMessageConsumer extends ConsumerMessage $data['content'] = json_encode($push_data,JSON_UNESCAPED_UNICODE); $log_message_push = LogMessagePush::addLogMessagePush($data); if (empty($log_message_push)){ - Log::getInstance()->error("站内消息推送成功,增加推送日志失败:" . json_encode($data,JSON_UNESCAPED_UNICODE)); + Log::getInstance("queue-SendStationMessage")->error("站内消息推送成功,增加推送日志失败:" . json_encode($data,JSON_UNESCAPED_UNICODE)); } } @@ -176,7 +175,7 @@ class SendStationMessageConsumer extends ConsumerMessage $data['content'] = json_encode($push_data,JSON_UNESCAPED_UNICODE); $log_message_push = LogMessagePush::addLogMessagePush($data); if (empty($log_message_push)){ - Log::getInstance()->error("站内消息推送成功,增加推送日志失败:" . json_encode($data,JSON_UNESCAPED_UNICODE)); + Log::getInstance("queue-SendStationMessage")->error("站内消息推送成功,增加推送日志失败:" . json_encode($data,JSON_UNESCAPED_UNICODE)); } } @@ -247,7 +246,7 @@ class SendStationMessageConsumer extends ConsumerMessage $message_notice = MessageNotice::addMessageNotice($notice_data); if (empty($message_notice)){ - Log::getInstance()->error("站内消息推送成功,记录通知消息表失败:" . json_encode($notice_data,JSON_UNESCAPED_UNICODE)); + Log::getInstance("queue-SendStationMessage")->error("站内消息推送成功,记录通知消息表失败:" . json_encode($notice_data,JSON_UNESCAPED_UNICODE)); } } } diff --git a/app/Amqp/Consumer/SendVideoNoticeDelayDirectConsumer.php b/app/Amqp/Consumer/SendVideoNoticeDelayDirectConsumer.php new file mode 100644 index 0000000..f3d71c4 --- /dev/null +++ b/app/Amqp/Consumer/SendVideoNoticeDelayDirectConsumer.php @@ -0,0 +1,195 @@ +info("开始:" . json_encode($data, JSON_UNESCAPED_UNICODE)); + + // 检测参数 + if (!isset($data['order_inquiry_id'])){ + Log::getInstance("queue-SendVideoNotice")->error("入参错误"); + return Result::DROP; + } + + // 获取问诊订单数据 + $params = array(); + $params['order_inquiry_id'] = $data['order_inquiry_id']; + $order_inquiry = OrderInquiry::getOne($params); + if (empty($order_inquiry)){ + Log::getInstance("queue-SendVideoNotice")->error("订单错误" ); + return Result::ACK; + } + + // 检测订单状态 + if ($order_inquiry['inquiry_status'] == 7) { + // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + Log::getInstance("queue-SendVideoNotice")->error("订单已取消" ); + return Result::ACK; + } + + // 检测订单状态 + if ($order_inquiry['inquiry_status'] == 5) { + // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + Log::getInstance("queue-SendVideoNotice")->error("订单已完成" ); + return Result::ACK; + } + + // 检测订单状态 + if ($order_inquiry['inquiry_status'] == 6) { + // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + Log::getInstance("queue-SendVideoNotice")->error("订单已结束" ); + return Result::ACK; + } + + // 检测订单状态 + if ($order_inquiry['inquiry_status'] == 3) { + // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + Log::getInstance("queue-SendVideoNotice")->error("订单待接诊" ); + return Result::ACK; + } + + // 检测订单状态 + if ($order_inquiry['inquiry_status'] == 1) { + // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + Log::getInstance("queue-SendVideoNotice")->error("订单待支付" ); + return Result::ACK; + } + + if (!in_array($order_inquiry['inquiry_refund_status'], [0, 4, 5])) { + // 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) + Log::getInstance("queue-SendVideoNotice")->error("订单存在退款" ); + return Result::DROP; + } + + // 获取视频预约状态 + $params = array(); + $params['order_inquiry_id'] = $data['order_inquiry_id']; + $order_inquiry_video_reservation = OrderInquiryVideoReservation::getOne($params); + if (empty($order_inquiry_video_reservation)){ + Log::getInstance("queue-SendVideoNotice")->error("缺少视频预约数据" ); + return Result::DROP; + } + + if ($order_inquiry_video_reservation['is_send_reservation_notice'] == 1){ + Log::getInstance("queue-SendVideoNotice")->info("已发送过一次通知,无需发送" ); + return Result::ACK; + } + + // 检测是否已开过视频 + $params = array(); + $params['order_inquiry_id'] = $order_inquiry_video_reservation['order_inquiry_id']; + $order_inquiry_video_record = OrderInquiryVideoRecord::getOne($params); + if (!empty($order_inquiry_video_record)) { + Log::getInstance("queue-SendVideoNotice")->info("已开过视频,无需发送" ); + return Result::ACK; + } + + // 检测通知时间 + $reservation_time = strtotime($order_inquiry_video_reservation['reservation_time']); + if ($reservation_time < time()){ + Log::getInstance("queue-SendVideoNotice")->info("当前时间已超过预约时间,无需发送" ); + return Result::ACK; + } + + // 5分钟以内 + $diff_time = $reservation_time - time(); + if ($diff_time > 5* 60){ + Log::getInstance("queue-SendVideoNotice")->info("不在发送时间内,无需发送" ); + return Result::ACK; + } + + // 获取患者用户数据 + $params = array(); + $params['user_id'] = $order_inquiry['user_id']; + $user = User::getOne($params); + if (empty($user)){ + Log::getInstance("queue-SendVideoNotice")->error("患者用户数据错误" ); + return Result::ACK; + } + + // 获取医生数据 + $params = array(); + $params['doctor_id'] = $order_inquiry['doctor_id']; + $user_doctor = UserDoctor::getOne($params); + if (empty($user_doctor)){ + Log::getInstance("queue-SendVideoNotice")->error("医生数据错误" ); + return Result::ACK; + } + + // 获取医生用户表数据 + $params = array(); + $params['user_id'] = $user_doctor['user_id']; + $doctor_user = User::getOne($params); + if (empty($doctor_user)){ + Log::getInstance("queue-SendVideoNotice")->error("医生用户数据错误" ); + return Result::ACK; + } + + Db::beginTransaction(); + try { + // 患者-通知患者视频 + $sendSmsService = new SendSmsService($user['mobile']); + $sendSmsService->noticePatientVideo($user_doctor['user_name']); + + // 医生-通知医生视频 + $sendSmsService = new SendSmsService($doctor_user['mobile']); + $sendSmsService->noticeDoctorVideo($order_inquiry['patient_name']); + + // 修改通知表 + $data = array(); + $data['is_send_reservation_notice'] = 1; + + $params = array(); + $params['inquiry_video_id'] = $order_inquiry_video_reservation['inquiry_video_id']; + $res = VideoReservation::edit($params,$data); + if (!$res){ + Db::rollBack(); + Log::getInstance("queue-SendVideoNotice")->error("修改失败"); + return Result::ACK; + } + + Db::commit(); + }catch (\Throwable $e){ + Db::rollBack(); + Log::getInstance("queue-SendVideoNotice")->error($e->getMessage()); + return Result::ACK; + } + + return Result::ACK; + } +} diff --git a/app/Amqp/Consumer/UserCouponExpiredDelayDirectConsumer.php b/app/Amqp/Consumer/UserCouponExpiredDelayDirectConsumer.php index 5301390..5c137af 100644 --- a/app/Amqp/Consumer/UserCouponExpiredDelayDirectConsumer.php +++ b/app/Amqp/Consumer/UserCouponExpiredDelayDirectConsumer.php @@ -72,7 +72,6 @@ class UserCouponExpiredDelayDirectConsumer extends ConsumerMessage // 检测优惠卷过期时间 $valid_end_time = strtotime($user_coupon['valid_end_time']); - Db::beginTransaction(); try { // 处理未过期事件 // 先删除-重新添加队列 @@ -80,14 +79,13 @@ class UserCouponExpiredDelayDirectConsumer extends ConsumerMessage $time = $valid_end_time - time(); $queue_data = array(); - $queue_data['order_inquiry_id'] = $data['order_inquiry_id']; + $queue_data['user_coupon_id'] = $user_coupon['user_coupon_id']; $message = new UserCouponExpiredDelayDirectProducer($queue_data); $message->setDelayMs(1000 * $time); $producer = $this->container->get(Producer::class); $res = $producer->produce($message); if (!$res) { - Db::rollBack(); Log::getInstance("queue-UserCouponExpired")->error("未到过期时间,重新添加队列失败"); return Result::REQUEUE; } @@ -103,12 +101,10 @@ class UserCouponExpiredDelayDirectConsumer extends ConsumerMessage $data['user_coupon_status'] = 3; UserCoupon::edit($params, $data); } catch (\Throwable $e) { - Db::rollBack(); Log::getInstance("queue-UserCouponExpired")->error($e->getMessage()); return Result::REQUEUE; // 重回队列 } - Db::commit(); Log::getInstance("queue-UserCouponExpired")->info("成功"); Db::beginTransaction(); diff --git a/app/Amqp/Producer/SendVideoNoticeDelayDirectProducer.php b/app/Amqp/Producer/SendVideoNoticeDelayDirectProducer.php new file mode 100644 index 0000000..e21506f --- /dev/null +++ b/app/Amqp/Producer/SendVideoNoticeDelayDirectProducer.php @@ -0,0 +1,36 @@ +payload = $data; + } +} diff --git a/app/Command/GrantUserCouponCommand.php b/app/Command/GrantUserCouponCommand.php index 17e5aad..84ff3e9 100644 --- a/app/Command/GrantUserCouponCommand.php +++ b/app/Command/GrantUserCouponCommand.php @@ -43,7 +43,7 @@ class GrantUserCouponCommand extends HyperfCommand // 获取需要发放的优惠卷数据 $params = array(); - $params['coupon_id'] = 3; + $params['coupon_id'] = 5; $coupon = Coupon::getOne($params); if (empty($coupon)){ $this->line("结束:无可执行优惠卷"); @@ -80,6 +80,7 @@ class GrantUserCouponCommand extends HyperfCommand Db::commit(); $this->line("用户" . $user['user_name'] . "执行完毕"); + sleep(1); } $this->line("发放完毕"); diff --git a/app/Command/getProductStockCommand.php b/app/Command/getProductStockCommand.php index d7a1db8..1978741 100644 --- a/app/Command/getProductStockCommand.php +++ b/app/Command/getProductStockCommand.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace App\Command; use App\Model\Product; +use App\Model\ProductAmountRecord; use App\Model\ProductPlatformAmount; use Extend\Prescription\Prescription; use Hyperf\Command\Command as HyperfCommand; @@ -93,6 +94,9 @@ class getProductStockCommand extends HyperfCommand try { Db::beginTransaction(); + // 当前库存数量 + $stock = 0; + $params = array(); $params['product_platform_id'] = $product_platform_id; $params['product_platform_code'] = $product_platform_code; @@ -109,6 +113,8 @@ class getProductStockCommand extends HyperfCommand $this->line("商品库存更新失败,无法新增库存数据" . json_encode($data, JSON_UNESCAPED_UNICODE)); } }else{ + $stock = $product_platform_amount['stock']; + // 存在库存数据,修改 $data = array(); $data['stock'] = $resultData['quantity']; @@ -118,8 +124,27 @@ class getProductStockCommand extends HyperfCommand ProductPlatformAmount::edit($params,$data); } + // 获取商品数据 + $params = array(); + $params['product_platform_id'] = $product_platform_id; + $product = Product::getOne($params); + if (!empty($product)){ + // 增加库存记录 + $data = array(); + $data['product_id'] = $product['product_id']; + $data['change_quantity'] = $resultData['quantity'] - $stock; // 库存变动的数量 变动的库存-原库存 + $data['quantity'] = $resultData['quantity']; // 变动后库存数量 + $data['change_time'] = date('Y-m-d H:i:s',time()); + $data['remark'] = "库存同步"; + $product_amount_record = ProductAmountRecord::addProductAmountRecord($data); + if (empty($product_amount_record)){ + Db::rollBack(); + $this->line("商品库存更新失败,增加库存记录失败" . json_encode($data, JSON_UNESCAPED_UNICODE)); + } + } + Db::commit(); - } catch (\Exception $e) { + } catch (\Throwable $e) { Db::rollBack(); $this->line("商品库存更新失败:" . $e->getMessage()); return false; diff --git a/app/Common/Common.php b/app/Common/Common.php index bff6f43..2340160 100644 --- a/app/Common/Common.php +++ b/app/Common/Common.php @@ -88,7 +88,7 @@ function UserTypeToString(int|string $user_type): string /** * 获取身份证年龄 - * @param $idCard + * @param string $idCard * @return false|int|mixed|string */ function getIdCardAge(string $idCard): mixed diff --git a/app/Controller/CallBackController.php b/app/Controller/CallBackController.php index 6b5073f..c8624a1 100644 --- a/app/Controller/CallBackController.php +++ b/app/Controller/CallBackController.php @@ -23,6 +23,8 @@ use App\Model\OrderInquiry; use App\Model\OrderInquiryCase; use App\Model\OrderInquiryCoupon; use App\Model\OrderInquiryRefund; +use App\Model\OrderInquiryVideoRecord; +use App\Model\OrderInquiryVideoReservation; use App\Model\OrderPrescription; use App\Model\OrderProduct; use App\Model\OrderProductCoupon; @@ -37,6 +39,8 @@ use App\Model\UserCoupon; use App\Model\UserDoctor; use App\Model\UserPatient; use App\Model\UserSystem; +use App\Model\VideoRecord; +use App\Model\VideoReservation; use App\Services\BaseService; use App\Services\ImService; use App\Services\InquiryService; @@ -61,6 +65,7 @@ use Hyperf\Utils\ApplicationContext; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; use Psr\Http\Message\ResponseInterface; +use Extend\TencentVideo\Safe as VideoSafe; class CallBackController extends AbstractController { @@ -709,8 +714,6 @@ class CallBackController extends AbstractController /** * im回调 * @return ResponseInterface - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function imCallBack(): ResponseInterface { @@ -1702,4 +1705,607 @@ class CallBackController extends AbstractController ); } + /** + * 音视频回调-房间与媒体 + * @return ResponseInterface + */ + public function videoTrtcCallBack(): ResponseInterface + { + $request_params = $this->request->getBody()->getContents(); + $SdkAppId = $this->request->header("SdkAppId"); + $Sign = $this->request->header("Sign"); + $Sign = stripslashes($Sign); + + try { + Log::getInstance("CallBackController-videoTrtcCallBack")->info(json_encode($request_params, JSON_UNESCAPED_UNICODE)); + + if (empty($SdkAppId)) { + return $this->videoTrtcErrorReturn("缺少SdkAppId字段"); + } + + if (empty($Sign)) { + return $this->videoTrtcErrorReturn("缺少签名字段"); + } + + // 鉴定回调签名 + $VideoSafe = new VideoSafe(); + $result = $VideoSafe->validateSign($request_params,$Sign); + if (!$result) { + return $this->videoTrtcErrorReturn("回调签名不匹配"); + } + + $request_params = json_decode($request_params,true); + + // 验证参数 + if (!isset($request_params['EventGroupId'])){ + return $this->videoTrtcErrorReturn("缺少回调事件组"); + } + + if (empty($request_params['EventGroupId'])){ + return $this->videoTrtcErrorReturn("回调事件组为空"); + } + + if (!isset($request_params['EventType'])){ + return $this->videoTrtcErrorReturn("回调事件类型"); + } + + if (empty($request_params['EventType'])){ + return $this->videoTrtcErrorReturn("回调事件类型为空"); + } + + if (!isset($request_params['EventInfo'])){ + return $this->videoTrtcErrorReturn("缺少回调事件信息"); + } + + if (empty($request_params['EventInfo'])){ + return $this->videoTrtcErrorReturn("回调事件信息为空"); + } + + if (!isset($request_params['EventInfo']['RoomId'])){ + return $this->videoTrtcErrorReturn("缺少房间id"); + } + + if (empty($request_params['EventInfo']['RoomId'])){ + return $this->videoTrtcErrorReturn("房间id为空"); + } + + if (!isset($request_params['EventInfo']['EventMsTs'])){ + return $this->videoTrtcErrorReturn("缺少时间戳"); + } + + if (empty($request_params['EventInfo']['EventMsTs'])){ + return $this->videoTrtcErrorReturn("时间戳为空"); + } + + // 排除数据 + if ($request_params['EventGroupId'] != 1 && $request_params['EventGroupId'] != 2){ + return $this->videoTrtcErrorReturn("回调地址推送错误"); + } + + if (!in_array($request_params['EventType'],[102,103,201,203])){ + return $this->videoTrtcSuccessReturn(); + } + } catch (\Throwable $e) { + // 验证失败 + return $this->videoTrtcErrorReturn($e->getMessage()); + } + + // 处理业务逻辑 + try { + // 获取视频预约记录 + $params = array(); + $params['room_id'] = $request_params['EventInfo']['RoomId']; + $order_inquiry_video_reservation = OrderInquiryVideoReservation::getLastOne($params); + if (empty($order_inquiry_video_reservation)){ + return $this->videoTrtcErrorReturn("未查询到该房间号,此条数据不接收"); + } + + // 获取视频记录 + $params = array(); + $params['room_id'] = $request_params['EventInfo']['RoomId']; + $params['order_inquiry_id'] = $order_inquiry_video_reservation['order_inquiry_id']; + $order_inquiry_video_record = OrderInquiryVideoRecord::getLastOne($params); + if (empty($order_inquiry_video_record)){ + return $this->videoTrtcErrorReturn("缺少视频开启记录"); + } + + // 检测缓存-只允许同时处理同一房间的一个请求,防止数据库冲突 + $redis = $this->container->get(Redis::class); + $redis_key = "videoTrtcCallBack_" . $request_params['EventInfo']['RoomId']; + $redis_value = $redis->get($redis_key); + + // 加入缓存 + $redis->set($redis_key, $request_params['EventType'], 20); + if (!empty($redis_value)){ + if ($redis_value == $request_params['EventType']){ + // 存在正在执行的相同事件,此次事件不处理 + return $this->videoTrtcSuccessReturn(); + } + + // 解散房间 + if ($redis_value == 102){ + // 正在处理结束通话事件,此次事件不处理 + return $this->videoTrtcSuccessReturn(); + } + + // 视频推流 + if ($redis_value == 201){ + if ($request_params['EventType'] == 103){ + // 正在处理视频推流事件,进入房间事件不处理 + return $this->videoTrtcSuccessReturn(); + } + + if ($request_params['EventType'] == 203){ + // 正在处理视频推流事件,音频推流事件不处理 + return $this->videoTrtcSuccessReturn(); + } + } + + // 音频推流 + if ($redis_value == 203){ + if ($request_params['EventType'] == 103){ + // 正在处理视频推流事件,进入房间事件不处理 + return $this->videoTrtcSuccessReturn(); + } + + if ($request_params['EventType'] == 201){ + // 正在处理视频推流事件,视频推流事件不处理 + return $this->videoTrtcSuccessReturn(); + } + } + } + + // 处理业务逻辑 + switch ($request_params['EventType']) { + case '103': // 进入房间 + if (empty($request_params['EventInfo']['UserId'])){ + return $this->videoTrtcErrorReturn("缺少用户id"); + } + + // 获取用户数据 + $params = array(); + $params['user_id'] = $request_params['EventInfo']['UserId']; + $user = User::getOne($params); + if (empty($user)){ + return $this->videoTrtcErrorReturn("非法用户"); + } + + if ($user['user_type'] != 1){ + return $this->videoTrtcSuccessReturn(); + } + + // 检测视频状态 + if ($order_inquiry_video_record['video_status'] == 3 || $order_inquiry_video_record['video_status'] == 4){ + // 已开始/结束通话,进入房间动作不做处理 + return $this->videoTrtcSuccessReturn(); + } + + // 修改视频状态 + $params = array(); + $params['records_id'] = $order_inquiry_video_record['records_id']; + + $data = array(); + $data['video_status'] = 2; + $res = OrderInquiryVideoRecord::edit($params,$data); + if (!$res){ + return $this->videoTrtcErrorReturn("修改视频状态失败"); + } + + break; + case '102': // 解散房间 + // 检测视频状态 + if ($order_inquiry_video_record['video_status'] == 4){ + // 已结束通话,解散房间动作不做处理 + return $this->videoTrtcSuccessReturn(); + } + + // 修改视频状态 + $params = array(); + $params['records_id'] = $order_inquiry_video_record['records_id']; + + $data = array(); + $data['video_status'] = 4; + $data['stop_video_time'] = date('Y-m-d H:i:s',$request_params['EventInfo']['EventMsTs']); + $res = OrderInquiryVideoRecord::edit($params,$data); + if (!$res){ + return $this->videoTrtcErrorReturn("修改视频状态失败"); + } + + break; + case '201': // 视频推流 + // 检测视频状态 + if ($order_inquiry_video_record['video_status'] == 4){ + // 已结束通话,视频推流动作不做处理 + return $this->videoTrtcSuccessReturn(); + } + + if ($order_inquiry_video_record['video_status'] == 3){ + // 已开始通话,视频推流动作不做处理 + return $this->videoTrtcSuccessReturn(); + } + + // 修改视频状态 + $params = array(); + $params['records_id'] = $order_inquiry_video_record['records_id']; + + $data = array(); + $data['video_status'] = 3; + $data['stop_video_time'] = date('Y-m-d H:i:s',$request_params['EventInfo']['EventMsTs']); + $res = OrderInquiryVideoRecord::edit($params,$data); + if (!$res){ + return $this->videoTrtcErrorReturn("修改视频状态失败"); + } + + break; + case '203': // 音频推流 + // 检测视频状态 + if ($order_inquiry_video_record['video_status'] == 4){ + // 已结束通话,音频推流动作不做处理 + return $this->videoTrtcSuccessReturn(); + } + + if ($order_inquiry_video_record['video_status'] == 3){ + // 已开始通话,音频推流动作不做处理 + return $this->videoTrtcSuccessReturn(); + } + + // 修改视频状态 + $params = array(); + $params['records_id'] = $order_inquiry_video_record['records_id']; + + $data = array(); + $data['video_status'] = 3; + $data['stop_video_time'] = date('Y-m-d H:i:s',$request_params['EventInfo']['EventMsTs']); + $res = OrderInquiryVideoRecord::edit($params,$data); + if (!$res){ + return $this->videoTrtcErrorReturn("修改视频状态失败"); + } + + break; + + default: + return $this->videoTrtcErrorReturn("未知事件"); + } + + // 删除缓存 + $redis->del($redis_key); + }catch (\Throwable $e){ + return $this->videoTrtcErrorReturn($e->getMessage()); + } + + Log::getInstance("CallBackController-videoTrtcCallBack")->info("音视频回调-房间与媒体处理成功"); + return $this->videoTrtcSuccessReturn(); + } + + /** + * 音视频返回错误响应 + * @param string $message + * @return ResponseInterface + */ + protected function videoTrtcErrorReturn(string $message): ResponseInterface + { + Log::getInstance("CallBackController-videoTrtcCallBack")->error($message); + return $this->response + ->withStatus(200) + ->withBody( + new SwooleStream( + strval( + json_encode([ + 'code' => 0, + 'ErrorInfo' => $message, + ], JSON_UNESCAPED_UNICODE) + ) + ) + ); + } + + /** + * 音视频返回正确响应 + * @return ResponseInterface + */ + protected function videoTrtcSuccessReturn(): ResponseInterface + { + return $this->response + ->withStatus(200) + ->withBody( + new SwooleStream( + strval( + json_encode([ + 'code' => 0, + 'ErrorInfo' => "", + ], JSON_UNESCAPED_UNICODE) + ) + ) + ); + } + + /** + * 音视频回调-云端录制 + * @return ResponseInterface + */ + public function videoRecordingCallBack(): ResponseInterface + { + $request_params = $this->request->getBody()->getContents(); + $SdkAppId = $this->request->header("SdkAppId"); + $Sign = $this->request->header("Sign"); + $Sign = stripslashes($Sign); + + try { + Log::getInstance("CallBackController-videoRecordingCallBack")->info(json_encode($request_params, JSON_UNESCAPED_UNICODE)); + + if (empty($SdkAppId)) { + return $this->videoRecordingErrorReturn("缺少SdkAppId字段"); + } + + if (empty($Sign)) { + return $this->videoRecordingErrorReturn("缺少签名字段"); + } + + // 鉴定回调签名 + $VideoSafe = new VideoSafe(); + $result = $VideoSafe->validateSign($request_params,$Sign); + if (!$result) { + return $this->videoRecordingErrorReturn("回调签名不匹配"); + } + + $request_params = json_decode($request_params,true); + + // 验证参数 + if (!isset($request_params['EventGroupId'])){ + return $this->videoRecordingErrorReturn("缺少回调事件组"); + } + + if (empty($request_params['EventGroupId'])){ + return $this->videoRecordingErrorReturn("回调事件组为空"); + } + + if (!isset($request_params['EventType'])){ + return $this->videoRecordingErrorReturn("缺少回调事件类型"); + } + + if (empty($request_params['EventType'])){ + return $this->videoRecordingErrorReturn("回调事件类型为空"); + } + + if (!isset($request_params['EventInfo'])){ + return $this->videoRecordingErrorReturn("缺少回调事件信息"); + } + + if (empty($request_params['EventInfo'])){ + return $this->videoRecordingErrorReturn("回调事件信息为空"); + } + + if (!isset($request_params['EventInfo']['RoomId'])){ + return $this->videoRecordingErrorReturn("缺少房间id"); + } + + if (empty($request_params['EventInfo']['RoomId'])){ + return $this->videoRecordingErrorReturn("房间id为空"); + } + + // 排除数据 + if ($request_params['EventGroupId'] != 3){ + return $this->videoRecordingErrorReturn("回调地址推送错误"); + } + + if (!in_array($request_params['EventType'],[311])){ + return $this->videoRecordingSuccessReturn(); + } + + if (!isset($request_params['EventInfo']['Payload'])){ + return $this->videoRecordingErrorReturn("缺少有效载荷"); + } + + if (empty($request_params['EventInfo']['Payload'])){ + return $this->videoRecordingErrorReturn("有效载荷为空"); + } + + if (!isset($request_params['EventInfo']['Payload']['Status'])){ + return $this->videoRecordingErrorReturn("缺少录制状态"); + } + + } catch (\Throwable $e) { + // 验证失败 + return $this->videoRecordingErrorReturn($e->getMessage()); + } + + // 处理业务逻辑 + Db::beginTransaction(); + + try { + // 获取视频预约记录 + $params = array(); + $params['room_id'] = $request_params['EventInfo']['RoomId']; + $order_inquiry_video_reservation = OrderInquiryVideoReservation::getLastOne($params); + if (empty($order_inquiry_video_reservation)){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("未查询到该房间号,此条数据不接收"); + } + + // 获取视频记录 + $params = array(); + $params['room_id'] = $request_params['EventInfo']['RoomId']; + $params['order_inquiry_id'] = $order_inquiry_video_reservation['order_inquiry_id']; + $order_inquiry_video_record = OrderInquiryVideoRecord::getLastOne($params); + if (empty($order_inquiry_video_record)){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("缺少视频开启记录"); + } + + if (!empty($order_inquiry_video_record['doctor_vod_path']) && !empty($order_inquiry_video_record['patient_vod_path'])){ + // 已存在点播路径,此次请求无需处理 + Db::rollBack(); + return $this->videoRecordingSuccessReturn(); + } + + // 检测缓存-只允许同时处理同一房间的一个请求,防止数据库冲突 + $redis = $this->container->get(Redis::class); + $redis_key = "videoRecordingCallBack_" . $request_params['EventInfo']['RoomId'] . $order_inquiry_video_reservation['patient_user_id']; + $redis_value = $redis->get($redis_key); + + // 加入缓存 + $redis->set($redis_key, $request_params['EventType'], 20); + if (!empty($redis_value)){ + // 事件正在处理,重复请求不处理 + Db::rollBack(); + return $this->videoRecordingSuccessReturn(); + } + + // 处理业务逻辑 + if (!isset($request_params['EventInfo']['Payload']['TencentVod'])){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("缺少关键参数"); + } + + if (empty($request_params['EventInfo']['Payload']['TencentVod'])){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("缺少关键参数"); + } + + if (!isset($request_params['EventInfo']['Payload']['TencentVod']['UserId'])){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("缺少用户id参数"); + } + + if (empty($request_params['EventInfo']['Payload']['TencentVod']['UserId'])){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("缺少用户id参数"); + } + + // 获取用户数据 + $params = array(); + $params['user_id'] = $request_params['EventInfo']['Payload']['TencentVod']['UserId']; + $user = User::getOne($params); + if (empty($user)){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("非法用户"); + } + + if ($request_params['EventInfo']['Payload']['Status'] == 0){ + if (!isset($request_params['EventInfo']['Payload']['TencentVod']['VideoUrl'])){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("缺少播放地址参数"); + } + + if (empty($request_params['EventInfo']['Payload']['TencentVod']['VideoUrl'])){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("缺少播放地址参数"); + } + + // 修改视频状态 + $params = array(); + $params['records_id'] = $order_inquiry_video_record['records_id']; + + if ($user['user_type'] == 1){ + $data = array(); + $data['vod_path_patient'] = $request_params['EventInfo']['Payload']['TencentVod']['VideoUrl']; + $data['vod_status_patient'] = 1; + $res = OrderInquiryVideoRecord::edit($params,$data); + if (!$res){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("播放地址存储失败"); + } + }elseif($user['user_type'] == 2){ + $data = array(); + $data['vod_path_doctor'] = $request_params['EventInfo']['Payload']['TencentVod']['VideoUrl']; + $data['vod_status_doctor'] = 1; + $res = OrderInquiryVideoRecord::edit($params,$data); + if (!$res){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("播放地址存储失败"); + } + }else{ + Db::rollBack(); + return $this->videoRecordingErrorReturn("非法用户类型"); + } + }else{ + // 录制上传失败 + if (!isset($request_params['EventInfo']['Payload']['Errmsg'])){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("录制上传失败但缺少错误描述"); + } + + if (empty($request_params['EventInfo']['Payload']['Errmsg'])){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("录制上传失败但错误描述为空"); + } + + // 修改视频状态 + $params = array(); + $params['records_id'] = $order_inquiry_video_record['records_id']; + + $data = array(); + if ($user['user_type'] == 1){ + $data['vod_status_patient'] = 2; + $data['vod_err_patient'] = $request_params['EventInfo']['Payload']['Errmsg']; + }elseif($user['user_type'] == 2){ + $data['vod_status_doctor'] = 2; + $data['vod_err_doctor'] = $request_params['EventInfo']['Payload']['Errmsg']; + }else{ + Db::rollBack(); + return $this->videoRecordingErrorReturn("非法用户类型"); + } + + $res = OrderInquiryVideoRecord::edit($params,$data); + if (!$res){ + Db::rollBack(); + return $this->videoRecordingErrorReturn("修改视频状态失败"); + } + } + + Db::commit(); + + // 删除缓存 + $redis->del($redis_key); + }catch (\Throwable $e){ + Db::rollBack(); + return $this->videoRecordingErrorReturn($e->getMessage()); + } + + Log::getInstance("CallBackController-videoRecordingCallBack")->info("音视频回调-云端录制处理成功"); + return $this->videoTrtcSuccessReturn(); + } + + /** + * 音视频回调-云端录制-返回错误响应 + * @param string $message + * @return ResponseInterface + */ + protected function videoRecordingErrorReturn(string $message): ResponseInterface + { + Log::getInstance("CallBackController-videoRecordingCallBack")->error($message); + return $this->response + ->withStatus(200) + ->withBody( + new SwooleStream( + strval( + json_encode([ + 'code' => 0, + 'ErrorInfo' => $message, + ], JSON_UNESCAPED_UNICODE) + ) + ) + ); + } + + /** + * 音视频回调-云端录制-返回正确响应 + * @return ResponseInterface + */ + protected function videoRecordingSuccessReturn(): ResponseInterface + { + return $this->response + ->withStatus(200) + ->withBody( + new SwooleStream( + strval( + json_encode([ + 'code' => 0, + 'ErrorInfo' => "", + ], JSON_UNESCAPED_UNICODE) + ) + ) + ); + } + } \ No newline at end of file diff --git a/app/Controller/DoctorAuthController.php b/app/Controller/DoctorAuthController.php index 6e4345b..805716c 100644 --- a/app/Controller/DoctorAuthController.php +++ b/app/Controller/DoctorAuthController.php @@ -11,7 +11,7 @@ use Psr\Container\NotFoundExceptionInterface; use Psr\Http\Message\ResponseInterface; /** - * 医生认证 + * 医生身份认证 */ class DoctorAuthController extends AbstractController { @@ -45,14 +45,9 @@ class DoctorAuthController extends AbstractController /** * 获取身份认证信息 * @return ResponseInterface - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function getAuthIden(): ResponseInterface { - $request = $this->container->get(DoctorAuthRequest::class); - $request->scene('getAuthIden')->validateResolved(); - $DoctorAuthService = new DoctorAuthService(); $data = $DoctorAuthService->getAuthIden(); return $this->response->json($data); @@ -100,4 +95,53 @@ class DoctorAuthController extends AbstractController $data = $DoctorAuthService->addAuthMulti(); return $this->response->json($data); } + + /** + * 获取身份认证审核失败原因 + * @return ResponseInterface + */ + public function getIdenAuthFailReason(): ResponseInterface + { + $DoctorAuthService = new DoctorAuthService(); + $data = $DoctorAuthService->getIdenAuthFailReason(); + return $this->response->json($data); + } + + /** + * 获取个人简介审核失败原因 + * @return ResponseInterface + */ + public function getDoctorIntroductionFailReason(): ResponseInterface + { + $DoctorAuthService = new DoctorAuthService(); + $data = $DoctorAuthService->getDoctorIntroductionFailReason(); + return $this->response->json($data); + } + + /** + * 获取个人简介 + * @return ResponseInterface + */ + public function getDoctorIntroduction(): ResponseInterface + { + $DoctorAuthService = new DoctorAuthService(); + $data = $DoctorAuthService->getDoctorIntroduction(); + return $this->response->json($data); + } + + /** + * 修改个人简介 + * @return ResponseInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function putDoctorIntroduction(): ResponseInterface + { + $request = $this->container->get(DoctorAuthRequest::class); + $request->scene('putDoctorIntroduction')->validateResolved(); + + $DoctorAuthService = new DoctorAuthService(); + $data = $DoctorAuthService->putDoctorIntroduction(); + return $this->response->json($data); + } } \ No newline at end of file diff --git a/app/Controller/DoctorInquiryConfigController.php b/app/Controller/DoctorInquiryConfigController.php new file mode 100644 index 0000000..3b98f12 --- /dev/null +++ b/app/Controller/DoctorInquiryConfigController.php @@ -0,0 +1,110 @@ +container->get(DoctorInquiryConfigRequest::class); + $request->scene('getDoctorInquiryConfig')->validateResolved(); + + $DoctorInquiryService = new DoctorInquiryService(); + $data = $DoctorInquiryService->getDoctorInquiryConfig(); + return $this->response->json($data); + } + + /** + * 医生问诊开关 + * @return ResponseInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function putDoctorInquiryOpen(): ResponseInterface + { + $request = $this->container->get(DoctorInquiryConfigRequest::class); + $request->scene('putDoctorInquiryOpen')->validateResolved(); + + $DoctorInquiryService = new DoctorInquiryService(); + $data = $DoctorInquiryService->putDoctorInquiryOpen(); + return $this->response->json($data); + } + + /** + * 修改医生问诊配置 + * @return ResponseInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function putDoctorInquiryConfig(): ResponseInterface + { + $request = $this->container->get(DoctorInquiryConfigRequest::class); + $request->scene('putDoctorInquiryConfig')->validateResolved(); + + $DoctorInquiryService = new DoctorInquiryService(); + $data = $DoctorInquiryService->putDoctorInquiryConfig(); + return $this->response->json($data); + } + + /** + * 获取医生问诊配置-服务设置 + * @return ResponseInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function getInquiryServiceConfig(): ResponseInterface + { + $request = $this->container->get(DoctorInquiryConfigRequest::class); + $request->scene('getInquiryServiceConfig')->validateResolved(); + + $DoctorInquiryService = new DoctorInquiryService(); + $data = $DoctorInquiryService->getInquiryServiceConfig(); + return $this->response->json($data); + } + + /** + * 新增医生问诊配置-服务设置 + * @return ResponseInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function addInquiryServiceConfig(): ResponseInterface + { + $request = $this->container->get(DoctorInquiryConfigRequest::class); + $request->scene('addInquiryServiceConfig')->validateResolved(); + + $DoctorInquiryService = new DoctorInquiryService(); + $data = $DoctorInquiryService->addInquiryServiceConfig(); + return $this->response->json($data); + } + + /** + * 修改医生问诊配置-服务设置 + * @return ResponseInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function putInquiryServiceConfig(): ResponseInterface + { + $request = $this->container->get(DoctorInquiryConfigRequest::class); + $request->scene('putInquiryServiceConfig')->validateResolved(); + + $DoctorInquiryService = new DoctorInquiryService(); + $data = $DoctorInquiryService->putInquiryServiceConfig(); + return $this->response->json($data); + } +} \ No newline at end of file diff --git a/app/Controller/InquiryController.php b/app/Controller/InquiryController.php index a6e083a..cebd4db 100644 --- a/app/Controller/InquiryController.php +++ b/app/Controller/InquiryController.php @@ -123,7 +123,6 @@ class InquiryController extends AbstractController /** * 结束问诊 * @return ResponseInterface - * @throws GuzzleException */ public function putFinishInquiry(): ResponseInterface { @@ -135,6 +134,8 @@ class InquiryController extends AbstractController /** * 获取患者最后一条问诊订单id * @return ResponseInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function getPatientLastInquiryId(): ResponseInterface { @@ -145,4 +146,31 @@ class InquiryController extends AbstractController $data = $InquiryService->getPatientLastInquiryId(); return $this->response->json($data); } + + /** + * 医生赠送沟通回合数 + * @return ResponseInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function addDoctorGiveInquiryOrder(): ResponseInterface + { + $request = $this->container->get(InquiryRequest::class); + $request->scene('addDoctorGiveInquiryOrder')->validateResolved(); + + $InquiryService = new InquiryService(); + $data = $InquiryService->addDoctorGiveInquiryOrder(); + return $this->response->json($data); + } + + /** + * 获取视频问诊消息内页基础数据 + * @return ResponseInterface + */ + public function getInquiryVideoMessageBasic(): ResponseInterface + { + $InquiryService = new InquiryService(); + $data = $InquiryService->getInquiryVideoMessageBasic(); + return $this->response->json($data); + } } \ No newline at end of file diff --git a/app/Controller/PatientDoctorController.php b/app/Controller/PatientDoctorController.php index 4078855..aaa978a 100644 --- a/app/Controller/PatientDoctorController.php +++ b/app/Controller/PatientDoctorController.php @@ -31,17 +31,6 @@ class PatientDoctorController extends AbstractController return $this->response->json($data); } - /** - * 获取问诊医生详情 - * @return ResponseInterface - */ - public function getInquiryDoctorInfo(): ResponseInterface - { - $PatientDoctorService = new PatientDoctorService(); - $data = $PatientDoctorService->getInquiryDoctorInfo(); - return $this->response->json($data); - } - /** * 医生详情简介-详情中的简介 * @return ResponseInterface diff --git a/app/Controller/SafeController.php b/app/Controller/SafeController.php index 5a1a1de..9e0e15e 100644 --- a/app/Controller/SafeController.php +++ b/app/Controller/SafeController.php @@ -29,8 +29,6 @@ class SafeController extends AbstractController /** * 获取im签名数据 * @return ResponseInterface - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function getImSign(): ResponseInterface { @@ -38,4 +36,15 @@ class SafeController extends AbstractController $data = $SafeService->getImSign(); return $this->response->json($data); } + + /** + * 获取音视频签名数据 + * @return ResponseInterface + */ + public function getVideoSign(): ResponseInterface + { + $SafeService = new SafeService(); + $data = $SafeService->getVideoSign(); + return $this->response->json($data); + } } \ No newline at end of file diff --git a/app/Controller/UserDoctorController.php b/app/Controller/UserDoctorController.php index 3e15027..9faaef4 100644 --- a/app/Controller/UserDoctorController.php +++ b/app/Controller/UserDoctorController.php @@ -10,6 +10,7 @@ use App\Request\UserDoctorRequest; use App\Services\DoctorAuthService; use App\Services\DoctorInquiryService; use App\Services\ImService; +use App\Services\PatientDoctorService; use App\Services\UserDoctorService; use Extend\TencentIm\Account; use GuzzleHttp\Exception\GuzzleException; @@ -40,54 +41,6 @@ class UserDoctorController extends AbstractController return $this->response->json($data); } - /** - * 获取医生问诊配置 - * @return ResponseInterface - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - */ - public function getInquiryConfig(): ResponseInterface - { - $request = $this->container->get(UserDoctorRequest::class); - $request->scene('getInquiryConfig')->validateResolved(); - - $DoctorInquiryService = new DoctorInquiryService(); - $data = $DoctorInquiryService->getInquiryConfig(); - return $this->response->json($data); - } - - /** - * 医生问诊开关 - * @return ResponseInterface - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - */ - public function putInquiryOpen(): ResponseInterface - { - $request = $this->container->get(UserDoctorRequest::class); - $request->scene('putInquiryOpen')->validateResolved(); - - $DoctorInquiryService = new DoctorInquiryService(); - $data = $DoctorInquiryService->putInquiryOpen(); - return $this->response->json($data); - } - - /** - * 修改医生问诊配置 - * @return ResponseInterface - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - */ - public function putInquiryConfig(): ResponseInterface - { - $request = $this->container->get(UserDoctorRequest::class); - $request->scene('putInquiryConfig')->validateResolved(); - - $DoctorInquiryService = new DoctorInquiryService(); - $data = $DoctorInquiryService->putInquiryConfig(); - return $this->response->json($data); - } - /** * 获取医生银行卡 * @return ResponseInterface @@ -378,7 +331,8 @@ class UserDoctorController extends AbstractController /** * 新增医生接诊 * @return ResponseInterface - * @throws GuzzleException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function addDoctorInquiry(): ResponseInterface { @@ -386,4 +340,26 @@ class UserDoctorController extends AbstractController $data = $UserDoctorService->addDoctorInquiry(); return $this->response->json($data); } + + /** + * 获取医生详情-问诊 + * @return ResponseInterface + */ + public function getDoctorInfoInquiry(): ResponseInterface + { + $userDoctorService = new UserDoctorService(); + $data = $userDoctorService->getDoctorInfoInquiry(); + return $this->response->json($data); + } + + /** + * 获取医生开启的服务 + * @return ResponseInterface + */ + public function getDoctorOpenInquiryService(): ResponseInterface + { + $userDoctorService = new UserDoctorService(); + $data = $userDoctorService->getDoctorOpenInquiryService(); + return $this->response->json($data); + } } \ No newline at end of file diff --git a/app/Controller/VideoController.php b/app/Controller/VideoController.php new file mode 100644 index 0000000..49b482a --- /dev/null +++ b/app/Controller/VideoController.php @@ -0,0 +1,49 @@ +container->get(VideoRequest::class); + $request->scene('addVideoReservationDate')->validateResolved(); + + $videoService = new VideoService(); + $data = $videoService->addVideoReservationDate(); + return $this->response->json($data); + } + + /** + * 创建音视频房间 + * @return ResponseInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function addVideoRoom(): ResponseInterface + { + $request = $this->container->get(VideoRequest::class); + $request->scene('addVideoRoom')->validateResolved(); + + $videoService = new VideoService(); + $data = $videoService->addVideoRoom(); + return $this->response->json($data); + } +} \ No newline at end of file diff --git a/app/Model/DoctorIdenFail.php b/app/Model/DoctorIdenFail.php index d524673..691b7f7 100644 --- a/app/Model/DoctorIdenFail.php +++ b/app/Model/DoctorIdenFail.php @@ -31,11 +31,6 @@ class DoctorIdenFail extends Model */ protected array $fillable = ['iden_fail_id', 'doctor_id', 'field_name', 'fail_reason', 'created_at', 'updated_at']; - /** - * The attributes that should be cast to native types. - */ - protected array $casts = ['iden_fail_id' => 'integer', 'doctor_id' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime']; - protected string $primaryKey = "iden_fail_id"; /** diff --git a/app/Model/DoctorInquiryConfigService.php b/app/Model/DoctorInquiryConfigService.php new file mode 100644 index 0000000..ae93cc1 --- /dev/null +++ b/app/Model/DoctorInquiryConfigService.php @@ -0,0 +1,81 @@ +first($fields); + } + + /** + * 获取信息-多条 + * @param array $params + * @param array $fields + * @return object|null + */ + public static function getList(array $params, array $fields = ['*']): object|null + { + return self::where($params)->get($fields); + } + + /** + * 新增 + * @param array $data + * @return DoctorInquiryConfigService|\Hyperf\Database\Model\Model + */ + public static function addDoctorInquiryConfigService(array $data): \Hyperf\Database\Model\Model|DoctorInquiryConfigService + { + return self::create($data); + } + + /** + * 修改 + * @param array $params + * @param array $data + * @return int + */ + public static function edit(array $params = [], array $data = []): int + { + return self::where($params)->update($data); + } +} diff --git a/app/Model/DoctorIntroductionRecord.php b/app/Model/DoctorIntroductionRecord.php new file mode 100644 index 0000000..510aa17 --- /dev/null +++ b/app/Model/DoctorIntroductionRecord.php @@ -0,0 +1,95 @@ +first($fields); + } + + /** + * 获取信息-多条 + * @param array $params + * @param array $fields + * @return object|null + */ + public static function getList(array $params, array $fields = ['*']): object|null + { + return self::where($params)->get($fields); + } + + /** + * 新增 + * @param array $data + * @return DoctorIntroductionRecord|\Hyperf\Database\Model\Model + */ + public static function addDoctorIntroductionRecord(array $data): \Hyperf\Database\Model\Model|DoctorIntroductionRecord + { + return self::create($data); + } + + /** + * 获取信息-单条 + * @param array $params + * @param array $fields + * @return object|null + */ + public static function getLastOne(array $params, array $fields = ['*']): object|null + { + return self::where($params)->latest()->first($fields); + } + + /** + * 获取某种状态的最后一条数据 + * @param array $params + * @param array $introduction_status + * @param array $fields + * @return object|null + */ + public static function getStatusLastOne(array $params, array $introduction_status,array $fields = ["*"]): object|null + { + return self::where($params) + ->whereIn("introduction_status", $introduction_status) + ->latest() + ->first($fields); + } + +} diff --git a/app/Model/OrderEvaluation.php b/app/Model/OrderEvaluation.php index b521edd..1638cfe 100644 --- a/app/Model/OrderEvaluation.php +++ b/app/Model/OrderEvaluation.php @@ -7,6 +7,7 @@ namespace App\Model; use Hyperf\Database\Model\Collection; +use Hyperf\Database\Model\Relations\HasMany; use Hyperf\Snowflake\Concern\Snowflake; /** @@ -40,6 +41,14 @@ class OrderEvaluation extends Model protected string $primaryKey = "evaluation_id"; + /** + * 关联问诊订单表 + */ + public function OrderInquiry(): \Hyperf\Database\Model\Relations\BelongsTo + { + return $this->belongsTo(OrderInquiry::class, 'order_inquiry_id','order_inquiry_id'); + } + /** * 获取评价列表-分页 * @param array $params 条件 @@ -50,7 +59,10 @@ class OrderEvaluation extends Model */ public static function getPage(array $params, array $fields = ["*"], int $page = null, ?int $per_page = 10): array { - $raw = self::where($params)->orderBy('created_at','desc')->paginate($per_page, $fields, "page", $page); + $raw = self::with(['OrderInquiry']) + ->where($params) + ->orderBy('created_at','desc') + ->paginate($per_page, $fields, "page", $page); $data = array(); $data['current_page'] = $raw->currentPage();// 当前页码 $data['total'] = $raw->total();//数据总数 @@ -72,7 +84,8 @@ class OrderEvaluation extends Model */ public static function getScorePage(array $params, array $avg_score_params,array $fields = ["*"], int $page = null, ?int $per_page = 10): array { - $raw = self::where($params) + $raw = self::with(['OrderInquiry']) + ->where($params) ->whereBetween('avg_score',$avg_score_params) ->orderBy('created_at','desc') ->paginate($per_page, $fields, "page", $page); diff --git a/app/Model/OrderInquiry.php b/app/Model/OrderInquiry.php index d2d1de1..b28a5e5 100644 --- a/app/Model/OrderInquiry.php +++ b/app/Model/OrderInquiry.php @@ -17,12 +17,12 @@ use Hyperf\Snowflake\Concern\Snowflake; * @property int $patient_id 患者id * @property int $doctor_id 医生id(未分配时为null) * @property int $family_id 家庭成员id(就诊用户) - * @property int $inquiry_type 订单类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药) - * @property int $inquiry_mode 订单问诊方式(1:图文 2:视频 3:语音 4:电话 5:会员) + * @property int $inquiry_type 订单类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药 5:检测) + * @property int $inquiry_mode 接诊方式(1:图文 2:视频 3:语音 4:电话 5:会员 6:疑难会诊 7:附赠) * @property int $inquiry_status 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) * @property int $is_delete 删除状态(0:否 1:是) * @property int $inquiry_refund_status 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常) - * @property int $inquiry_pay_channel 支付渠道(1:小程序支付 2:微信扫码支付) + * @property int $inquiry_pay_channel 支付渠道(1:小程序支付 2:微信扫码支付 3:模拟支付) * @property int $inquiry_pay_status 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) * @property string $inquiry_no 系统订单编号 * @property string $escrow_trade_no 第三方支付流水号 @@ -40,14 +40,16 @@ use Hyperf\Snowflake\Concern\Snowflake; * @property string $cancel_time 订单取消时间 * @property int $cancel_reason 取消订单原因(1:医生未接诊 2:主动取消 3:无可分配医生 4:客服取消 5:支付超时) * @property string $cancel_remarks 取消订单备注(自动添加) + * @property int $times_number 沟通次数(0为不限制次数) + * @property int $duration 沟通时长(分钟,0为不限制时长) * @property string $patient_name 患者姓名-就诊人 * @property string $patient_name_mask 患者姓名-就诊人(掩码) * @property int $patient_sex 患者性别-就诊人(0:未知 1:男 2:女) * @property int $patient_age 患者年龄-就诊人 * @property \Carbon\Carbon $created_at 创建时间 * @property \Carbon\Carbon $updated_at 修改时间 - * @property-read OrderInquiryCase $OrderInquiryCase - * @property-read UserDoctor $UserDoctor + * @property-read OrderInquiryCase|null $OrderInquiryCase + * @property-read UserDoctor|null $UserDoctor */ class OrderInquiry extends Model { @@ -61,7 +63,7 @@ class OrderInquiry extends Model /** * The attributes that are mass assignable. */ - protected array $fillable = ['order_inquiry_id', 'user_id', 'patient_id', 'doctor_id', 'family_id', 'inquiry_type', 'inquiry_mode', 'inquiry_status', 'is_delete', 'inquiry_refund_status', 'inquiry_pay_channel', 'inquiry_pay_status', 'inquiry_no', 'escrow_trade_no', 'amount_total', 'coupon_amount_total', 'payment_amount_total', 'pay_time', 'reception_time', 'complete_time', 'finish_time', 'statistics_status', 'statistics_time', 'is_withdrawal', 'withdrawal_time', 'cancel_time', 'cancel_reason', 'cancel_remarks', 'patient_name', 'patient_name_mask', 'patient_sex', 'patient_age', 'created_at', 'updated_at']; + protected array $fillable = ['order_inquiry_id', 'user_id', 'patient_id', 'doctor_id', 'family_id', 'inquiry_type', 'inquiry_mode', 'inquiry_status', 'is_delete', 'inquiry_refund_status', 'inquiry_pay_channel', 'inquiry_pay_status', 'inquiry_no', 'escrow_trade_no', 'amount_total', 'coupon_amount_total', 'payment_amount_total', 'pay_time', 'reception_time', 'complete_time', 'finish_time', 'statistics_status', 'statistics_time', 'is_withdrawal', 'withdrawal_time', 'cancel_time', 'cancel_reason', 'cancel_remarks', 'times_number', 'duration', 'patient_name', 'patient_name_mask', 'patient_sex', 'patient_age', 'created_at', 'updated_at']; protected string $primaryKey = "order_inquiry_id"; @@ -145,8 +147,6 @@ class OrderInquiry extends Model return self::where($params)->orderBy('created_at', 'desc')->first($fields); } -// public static function - /** * 获取医生某一时间段接诊订单分页数据 * 已结束 @@ -180,17 +180,21 @@ class OrderInquiry extends Model * @param array $params * @param array $reception_time 接诊时间区间 ['2023-01','2023-01'] * @param array $inquiry_status_params + * @param array $inquiry_type_not_params * @param array $fields * @param int|null $page * @param int|null $per_page * @return int|mixed|string */ - public static function getDoctorCreatedDateOrderInquiryPage(array $params, array $reception_time, array $inquiry_status_params,array $fields = ["*"], int $page = null, ?int $per_page = 10): mixed + public static function getDoctorCreatedDateOrderInquiryPage(array $params, array $reception_time, array $inquiry_status_params,array $inquiry_type_not_params = [],array $fields = ["*"], int $page = null, ?int $per_page = 10): mixed { $raw = self::where($params) + ->when($inquiry_type_not_params, function ($query, $inquiry_type_not_params) { + $query->whereNotIn('inquiry_type', $inquiry_type_not_params); + }) ->whereIn('inquiry_status', $inquiry_status_params) ->whereBetween('reception_time', $reception_time) - ->orderBy('reception_time') + ->orderBy('reception_time','desc') ->paginate($per_page, $fields, "page", $page); $data = array(); @@ -203,18 +207,40 @@ class OrderInquiry extends Model return $data; } + /** + * 获取医生可提现金额-坐班医生 + * @param array $params + * @param array $inquiry_status_params + * @param array $inquiry_type_not_params + * @param array $fields + * @return int|mixed|string + */ + public static function getCooperationDoctorCanWithdrawalInquiryOrder(array $params, array $inquiry_status_params,array $inquiry_type_not_params = [],array $fields = ["*"]): mixed + { + $data = self::where($params) + ->when($inquiry_type_not_params, function ($query, $inquiry_type_not_params) { + $query->whereNotIn('inquiry_type', $inquiry_type_not_params); + }) + ->whereIn('inquiry_status', $inquiry_status_params) + ->get($fields); + + return $data; + } + /** * 获取医生接诊订单分页数据 * 已结束 * @param array $params + * @param array $inquiry_status_params * @param array $fields * @param int|null $page * @param int|null $per_page * @return int|mixed|string */ - public static function getDoctorOrderInquiryPage(array $params, array $fields = ["*"], int $page = null, ?int $per_page = 10): mixed + public static function getDoctorOrderInquiryPage(array $params, array $inquiry_status_params, array $fields = ["*"], int $page = null, ?int $per_page = 10): mixed { $raw = self::where($params) + ->whereIn('inquiry_status', $inquiry_status_params) ->orderBy('finish_time', 'desc') ->paginate($per_page, $fields, "page", $page); @@ -229,13 +255,44 @@ class OrderInquiry extends Model } /** - * 获取医生某一时间段,某种状态的订单金额 + * 获取医生接诊订单分页数据-坐班医生 + * 已结束 + * @param array $params + * @param array $inquiry_status_params + * @param array $inquiry_type_not_params + * @param array $fields + * @param int|null $page + * @param int|null $per_page + * @return int|mixed|string + */ + public static function getCooperationDoctorOrderInquiryPage(array $params, array $inquiry_status_params,array $inquiry_type_not_params = [], array $fields = ["*"], int $page = null, ?int $per_page = 10): mixed + { + $raw = self::where($params) + ->whereIn('inquiry_status', $inquiry_status_params) + ->when($inquiry_type_not_params, function ($query, $inquiry_type_not_params) { + $query->whereNotIn('inquiry_type', $inquiry_type_not_params); + }) + ->orderBy('finish_time', 'desc') + ->paginate($per_page, $fields, "page", $page); + + $data = array(); + $data['current_page'] = $raw->currentPage();// 当前页码 + $data['total'] = $raw->total();//数据总数 + $data['data'] = $raw->items();//数据 + $data['per_page'] = $raw->perPage();//每页个数 + $data['last_page'] = $raw->lastPage();//最后一页 + + return $data; + } + + /** + * 获取医生接诊的订单金额 * @param array $params * @param array $reception_time 接诊时间区间 * @param array $inquiry_status_params inquiry_status字段搜索条件 * @return int|mixed|string */ - public static function getOrderInquiryBetweenTimeAmountTotalSum(array $params, array $reception_time, array $inquiry_status_params): mixed + public static function getDoctorAmountTotal(array $params, array $reception_time, array $inquiry_status_params): mixed { return self::where($params) ->whereIn('inquiry_status', $inquiry_status_params) @@ -244,6 +301,25 @@ class OrderInquiry extends Model ->sum("amount_total"); } + /** + * 获取医生接诊的订单金额-坐班医生 + * @param array $params + * @param array $reception_time 接诊时间区间 + * @param array $inquiry_status_params inquiry_status字段搜索条件 + * @return int|mixed|string + */ + public static function getCooperationDoctorAmountTotal(array $params, array $reception_time, array $inquiry_status_params,array $inquiry_type_not_params = []): mixed + { + return self::where($params) + ->when($inquiry_type_not_params, function ($query, $inquiry_type_not_params) { + $query->whereNotIn('inquiry_type', $inquiry_type_not_params); + }) + ->whereIn('inquiry_status', $inquiry_status_params) + ->whereBetween('reception_time', $reception_time) + ->orderBy('reception_time') + ->sum("amount_total"); + } + /** * 获取医生某种状态的订单金额 * @param array $params diff --git a/app/Model/OrderInquiryVideoRecord.php b/app/Model/OrderInquiryVideoRecord.php new file mode 100644 index 0000000..a7e18ed --- /dev/null +++ b/app/Model/OrderInquiryVideoRecord.php @@ -0,0 +1,92 @@ +first($fields); + } + + /** + * 获取信息-多条 + * @param array $params + * @param array $fields + * @return object|null + */ + public static function getList(array $params, array $fields = ['*']): object|null + { + return self::where($params)->get($fields); + } + + /** + * 新增-批量 + * @param array $data 新增数据 + * @return \Hyperf\Database\Model\Model|OrderInquiryVideoRecord + */ + public static function addOrderInquiryVideoRecord(array $data): \Hyperf\Database\Model\Model|OrderInquiryVideoRecord + { + return self::create($data); + } + + public static function edit(array $params = [], array $data = []): int + { + return self::where($params)->update($data); + } + + /** + * 获取信息-最后一条 + * @param array $params + * @param array $fields + * @return object|null + */ + public static function getLastOne(array $params, array $fields = ['*']): object|null + { + return self::where($params)->latest()->first($fields); + } + +} diff --git a/app/Model/OrderInquiryVideoReservation.php b/app/Model/OrderInquiryVideoReservation.php new file mode 100644 index 0000000..794569d --- /dev/null +++ b/app/Model/OrderInquiryVideoReservation.php @@ -0,0 +1,89 @@ +first($fields); + } + + /** + * 获取信息-多条 + * @param array $params + * @param array $fields + * @return object|null + */ + public static function getList(array $params, array $fields = ['*']): object|null + { + return self::where($params)->get($fields); + } + + /** + * 新增-批量 + * @param array $data 新增数据 + * @return \Hyperf\Database\Model\Model|OrderInquiryVideoReservation + */ + public static function addOrderInquiryVideoReservation(array $data): \Hyperf\Database\Model\Model|OrderInquiryVideoReservation + { + return self::create($data); + } + + public static function edit(array $params = [], array $data = []): int + { + return self::where($params)->update($data); + } + + /** + * 获取信息-最后一条 + * @param array $params + * @param array $fields + * @return object|null + */ + public static function getLastOne(array $params, array $fields = ['*']): object|null + { + return self::where($params)->latest()->first($fields); + } +} diff --git a/app/Model/ProductAmountRecord.php b/app/Model/ProductAmountRecord.php new file mode 100644 index 0000000..db17d6e --- /dev/null +++ b/app/Model/ProductAmountRecord.php @@ -0,0 +1,70 @@ +first($fields); + } + + /** + * 获取数据-多 + * @param array $params + * @param array $fields + * @return Collection|array + */ + public static function getList(array $params = [], array $fields = ['*']): Collection|array + { + return self::where($params)->get($fields); + } + + /** + * 新增 + * @param array $data + * @return \Hyperf\Database\Model\Model|ProductAmountRecord + */ + public static function addProductAmountRecord(array $data = []): \Hyperf\Database\Model\Model|ProductAmountRecord + { + return self::create($data); + } +} diff --git a/app/Model/SystemInquiryConfig.php b/app/Model/SystemInquiryConfig.php index fe85e20..5b69a1d 100644 --- a/app/Model/SystemInquiryConfig.php +++ b/app/Model/SystemInquiryConfig.php @@ -11,8 +11,9 @@ use Hyperf\Snowflake\Concern\Snowflake; /** * @property string $system_inquiry_config_id 主键id - * @property int $inquiry_type 接诊类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药) - * @property int $inquiry_mode 接诊方式(1:图文 2:视频 3:语音 4:电话 5:会员) + * @property int $inquiry_type 接诊类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药 5:检测) + * @property int $inquiry_mode 接诊方式(1:图文 2:视频 3:语音 4:电话 5:会员 6:疑难会诊 7:附赠) + * @property int $default_work_num_day 默认每日接诊数量 * @property int $max_work_num_day 每日最大接诊数量 * @property string $inquiry_price 接诊价格 * @property string $min_inquiry_price 最低接诊价格(专家问诊) @@ -34,12 +35,12 @@ class SystemInquiryConfig extends Model /** * The attributes that are mass assignable. */ - protected array $fillable = ['system_inquiry_config_id', 'inquiry_type', 'inquiry_mode', 'max_work_num_day', 'inquiry_price', 'min_inquiry_price', 'max_inquiry_price', 'times_number', 'duration', 'created_at', 'updated_at']; + protected array $fillable = ['system_inquiry_config_id', 'inquiry_type', 'inquiry_mode', 'default_work_num_day', 'max_work_num_day', 'inquiry_price', 'min_inquiry_price', 'max_inquiry_price', 'times_number', 'duration', 'created_at', 'updated_at']; /** * The attributes that should be cast to native types. */ - protected array $casts = ['system_inquiry_config_id' => 'string', 'inquiry_type' => 'integer', 'inquiry_mode' => 'integer', 'max_work_num_day' => 'integer', 'times_number' => 'integer', 'duration' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime']; + protected array $casts = ['system_inquiry_config_id' => 'string', 'inquiry_type' => 'integer', 'inquiry_mode' => 'integer', 'max_work_num_day' => 'integer', 'times_number' => 'integer', 'duration' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime', 'default_work_num_day' => 'integer']; protected string $primaryKey = "system_inquiry_config_id"; diff --git a/app/Model/User.php b/app/Model/User.php index 99d7c37..925b593 100644 --- a/app/Model/User.php +++ b/app/Model/User.php @@ -22,6 +22,7 @@ use Hyperf\Snowflake\Concern\Snowflake; * @property int $register_method 注册方式(1:微信小程序 2:后台添加 ) * @property int $age 年龄 * @property int $sex 性别(0:未知 1:男 2:女) + * @property string $email 邮箱 * @property string $avatar 头像 * @property int $is_online 是否在线(0:不在线 1:在线) * @property string $login_at 小程序登陆时间 @@ -43,7 +44,7 @@ class User extends Model /** * The attributes that are mass assignable. */ - protected array $fillable = ['user_id', 'user_name', 'user_account', 'mobile', 'wx_mobile', 'user_password', 'salt', 'user_type', 'user_status', 'register_method', 'age', 'sex', 'avatar', 'is_online', 'login_at', 'im_login_at', 'login_ip', 'created_by', 'created_at', 'updated_at']; + protected array $fillable = ['user_id', 'user_name', 'user_account', 'mobile', 'wx_mobile', 'user_password', 'salt', 'user_type', 'user_status', 'register_method', 'age', 'sex', 'email', 'avatar', 'is_online', 'login_at', 'im_login_at', 'login_ip', 'created_by', 'created_at', 'updated_at']; protected string $primaryKey = "user_id"; diff --git a/app/Model/UserDoctor.php b/app/Model/UserDoctor.php index 78ff19a..2bba577 100644 --- a/app/Model/UserDoctor.php +++ b/app/Model/UserDoctor.php @@ -29,6 +29,8 @@ use Hyperf\Utils\Arr; * @property int $multi_point_status 医生多点执业认证状态(0:未认证 1:认证通过 2:审核中 3:认证失败) * @property string $multi_point_time 审核时间 * @property string $multi_point_fail_reason 多点执业认证失败原因 + * @property int $introduction_status 个人简介审核状态(0:未审核 1:审核通过 2:审核中 3:审核失败) + * @property string $introduction_time 审核时间 * @property int $is_bind_bank 是否已绑定结算银行卡(0:否 1:是) * @property int $is_recommend 是否首页推荐(0:否 1:是) * @property string $avatar 头像 @@ -56,6 +58,7 @@ use Hyperf\Utils\Arr; * @property-read \Hyperf\Database\Model\Collection|DoctorInquiryConfig[]|null $DoctorInquiryConfig * @property-read Hospital|null $Hospital * @property-read \Hyperf\Database\Model\Collection|OrderInquiry[]|null $OrderInquiry + * @property-read User|null $User */ class UserDoctor extends Model { @@ -69,7 +72,7 @@ class UserDoctor extends Model /** * The attributes that are mass assignable. */ - protected array $fillable = ['doctor_id', 'user_id', 'user_name', 'open_id', 'union_id', 'wx_session_key', 'status', 'idcard_status', 'iden_auth_status', 'iden_auth_time', 'iden_auth_fail_reason', 'multi_point_status', 'multi_point_time', 'multi_point_fail_reason', 'is_bind_bank', 'is_recommend', 'avatar', 'doctor_title', 'department_custom_id', 'department_custom_name', 'department_custom_mobile', 'hospital_id', 'served_patients_num', 'praise_rate', 'avg_response_time', 'number_of_fans', 'is_img_expert_reception', 'is_img_welfare_reception', 'is_img_quick_reception', 'is_platform_deep_cooperation', 'is_enterprise_deep_cooperation', 'is_sys_diagno_cooperation', 'qr_code', 'be_good_at', 'brief_introduction', 'created_at', 'updated_at']; + protected array $fillable = ['doctor_id', 'user_id', 'user_name', 'open_id', 'union_id', 'wx_session_key', 'status', 'idcard_status', 'iden_auth_status', 'iden_auth_time', 'iden_auth_fail_reason', 'multi_point_status', 'multi_point_time', 'multi_point_fail_reason', 'introduction_status', 'introduction_time', 'is_bind_bank', 'is_recommend', 'avatar', 'doctor_title', 'department_custom_id', 'department_custom_name', 'department_custom_mobile', 'hospital_id', 'served_patients_num', 'praise_rate', 'avg_response_time', 'number_of_fans', 'is_img_expert_reception', 'is_img_welfare_reception', 'is_img_quick_reception', 'is_platform_deep_cooperation', 'is_enterprise_deep_cooperation', 'is_sys_diagno_cooperation', 'qr_code', 'be_good_at', 'brief_introduction', 'created_at', 'updated_at']; protected string $primaryKey = "doctor_id"; @@ -211,26 +214,21 @@ class UserDoctor extends Model * @param array $hospital_params 医院搜索条件 * @param array $doctor_params 医生搜索条件 * @param array $doctor_expertise_params - * @param int $is_search_welfare_reception 是否搜索公益问诊 - * @param string|int $is_first_online 是否优先在线(1:是) + * @param array $inquiry_type + * @param array $inquiry_mode + * @param string|int $is_first_online 是否优先在线(1:是) * @param string|int $sort_order * @param array $fields * @param int|null $page * @param int|null $per_page * @return array */ - public static function getInquiryDoctorPage(string $keyword = "", array $hospital_params = [], array $doctor_params = [], array $doctor_expertise_params = [],int $is_search_welfare_reception = 0,string|int $is_first_online = 0, string|int $sort_order = 1, array $fields = ["*"], int $page = null, ?int $per_page = 10): array + public static function getInquiryDoctorPage(string $keyword = "", array $hospital_params = [], array $doctor_params = [], array $doctor_expertise_params = [],array $inquiry_type = [],array $inquiry_mode = [],string|int $is_first_online = 0, string|int $sort_order = 1, array $fields = ["*"], int $page = null, ?int $per_page = 10): array { $query = self::with([ "Hospital:hospital_id,hospital_name,hospital_status,hospital_level_name,province_id,city_id", "DoctorExpertise", - "DoctorInquiryConfig" => function ($query) use ($is_search_welfare_reception) { - $query->where('inquiry_mode', 1); - if (!empty($is_search_welfare_reception)){ - $query->where('inquiry_type', 3); - $query->where('is_enable', 1); - } - }, + "DoctorInquiryConfig", "User:user_id,is_online" ]) ->where($doctor_params) @@ -248,20 +246,42 @@ class UserDoctor extends Model }) ->whereHas('DoctorExpertise', function ($query) use ($doctor_expertise_params) { $query->where($doctor_expertise_params); - }) - ->whereHas('DoctorInquiryConfig', function ($query) use ($is_search_welfare_reception) { - $params = array(); - $params['inquiry_mode'] = 1;// 接诊方式:图文 - if (!empty($is_search_welfare_reception)){ - $params['is_enable'] = 1; - } - - $query->where($params); - - if (!empty($is_search_welfare_reception)){ - $query->where('inquiry_type', 3); - } }); +// ->whereHas('DoctorInquiryConfig', function ($query) use ($doctor_inquiry_config_params) { +// $params = array(); +// $params['is_enable'] = 1; +// +// if (!empty($doctor_inquiry_config_params)){ +// if (!empty($doctor_inquiry_config_params['inquiry_mode'])){ +// $params['inquiry_mode'] = $doctor_inquiry_config_params['inquiry_mode']; +// } +// +// if (!empty($doctor_inquiry_config_params['inquiry_type'])){ +// $params['inquiry_type'] = $doctor_inquiry_config_params['inquiry_type']; +// } +// } +// +// $query->where($params); +// }); +// ->whereHas('DoctorInquiryConfig', function ($query) use ($doctor_inquiry_config_params) { +// $params = array(); +// $params['is_enable'] = 1; +// +// if (!empty($doctor_inquiry_config_params)){ +// if (!empty($doctor_inquiry_config_params['inquiry_mode'])){ +// $inquiry_mode = explode(',',$doctor_inquiry_config_params['inquiry_mode']); +// $query->whereIn('inquiry_mode', $inquiry_mode); +// } +// +// if (!empty($doctor_inquiry_config_params['inquiry_type'])){ +// $inquiry_type = explode(',',$doctor_inquiry_config_params['inquiry_type']); +// $query->whereIn('inquiry_type', $inquiry_type); +// } +// } +// +// $query->where($params); +// }); + if ($is_first_online == 1){ $query->join('user as u', function ($query) { @@ -272,16 +292,46 @@ class UserDoctor extends Model } if (!empty($sort_order)){ +// if (in_array($sort_order,[1,3,4])){ +// $query = $query->join('doctor_inquiry_config', function ($query) { +// $query->on('user_doctor.doctor_id', '=', 'doctor_inquiry_config.doctor_id') +// ->whereIn('inquiry_type', [1, 3]) +// ->whereIn('inquiry_mode', [1,2,6,7]) +// ->orderBy('inquiry_price', 'desc') +// ->take(1); +// }) +// ->select("user_doctor.*") +// ->groupBy("user_doctor.doctor_id"); +// } + + // select doctor_id, min(price) price_min from price group by doctor_id if (in_array($sort_order,[1,3,4])){ - $query = $query->join('doctor_inquiry_config', function ($query) { - $query->on('user_doctor.doctor_id', '=', 'doctor_inquiry_config.doctor_id') - ->whereIn('inquiry_type', [1, 3]) - ->where('inquiry_mode', 1) - ->orderBy('inquiry_price', 'desc') - ->take(1); - }) - ->select("user_doctor.*") - ->groupBy("user_doctor.doctor_id"); + $raw = "inquiry_price as min_inquiry_price"; + if ($sort_order == 1){ + // 综合-价格从低到高 + $raw = "MIN(inquiry_price) as min_inquiry_price"; + } elseif ($sort_order == 3){ + // 价格从低到高 + $raw = "MIN(inquiry_price) as min_inquiry_price"; + } elseif ($sort_order == 4){ + // 价格从高到低 + $raw = "MAX(inquiry_price) as min_inquiry_price"; + } + + $latestPosts = Db::table('doctor_inquiry_config') + ->select('doctor_inquiry_config.doctor_id', Db::raw($raw)) + ->where('is_enable', 1); + if (!empty($inquiry_type)){ + $latestPosts = $latestPosts->whereIn('inquiry_type', $inquiry_type) + ->whereIn('inquiry_mode',$inquiry_mode); + } + + $latestPosts = $latestPosts->groupBy(["doctor_inquiry_config.doctor_id"]); + + $query = $query + ->joinSub($latestPosts, 'doctor_inquiry_config', function($join) { + $join->on('user_doctor.doctor_id', '=', 'doctor_inquiry_config.doctor_id'); + }); } if ($sort_order == 1) { @@ -291,7 +341,7 @@ class UserDoctor extends Model $query->orderBy('avg_response_time'); $query->orderBy('served_patients_num', 'desc');// 服务数从多到少 $query->orderBy(Db::raw("convert(substr(gdxz_user_doctor.user_name,1,1) using `GBK`)"), 'asc');// 名称排名 - $query->orderBy('doctor_inquiry_config.inquiry_price', 'asc'); + $query->orderBy('doctor_inquiry_config.min_inquiry_price', 'asc'); } elseif ($sort_order == 2) { // 响应时间快 $query->orderByRaw('avg_response_time = 0 ASC'); @@ -305,7 +355,7 @@ class UserDoctor extends Model $query->orderBy(Db::raw("convert(substr(gdxz_user_doctor.user_name,1,1) using `GBK`)"), 'asc');// 名称排名 } elseif ($sort_order == 4) { // 价格从高到低 - $query->orderBy('doctor_inquiry_config.inquiry_price', 'desc'); + $query->orderBy('doctor_inquiry_config.min_inquiry_price', 'desc'); $query->orderByRaw('avg_response_time = 0 ASC'); $query->orderBy('avg_response_time'); $query->orderBy(Db::raw("convert(substr(gdxz_user_doctor.user_name,1,1) using `GBK`)"), 'asc');// 名称排名 diff --git a/app/Model/VideoRecord.php b/app/Model/VideoRecord.php new file mode 100644 index 0000000..63f172b --- /dev/null +++ b/app/Model/VideoRecord.php @@ -0,0 +1,84 @@ +first($fields); + } + + /** + * 获取信息-多条 + * @param array $params + * @param array $fields + * @return object|null + */ + public static function getList(array $params, array $fields = ['*']): object|null + { + return self::where($params)->get($fields); + } + + /** + * 新增-批量 + * @param array $data 新增数据 + * @return \Hyperf\Database\Model\Model|VideoRecord + */ + public static function addVideoRecord(array $data): \Hyperf\Database\Model\Model|VideoRecord + { + return self::create($data); + } + + public static function edit(array $params = [], array $data = []): int + { + return self::where($params)->update($data); + } + + /** + * 获取信息-最后一条 + * @param array $params + * @param array $fields + * @return object|null + */ + public static function getLastOne(array $params, array $fields = ['*']): object|null + { + return self::where($params)->latest()->first($fields); + } +} diff --git a/app/Model/VideoReservation.php b/app/Model/VideoReservation.php new file mode 100644 index 0000000..eb7c760 --- /dev/null +++ b/app/Model/VideoReservation.php @@ -0,0 +1,88 @@ +first($fields); + } + + /** + * 获取信息-多条 + * @param array $params + * @param array $fields + * @return object|null + */ + public static function getList(array $params, array $fields = ['*']): object|null + { + return self::where($params)->get($fields); + } + + /** + * 新增-批量 + * @param array $data 新增数据 + * @return \Hyperf\Database\Model\Model|VideoReservation + */ + public static function addVideoReservation(array $data): \Hyperf\Database\Model\Model|VideoReservation + { + return self::create($data); + } + + public static function edit(array $params = [], array $data = []): int + { + return self::where($params)->update($data); + } + + /** + * 获取信息-最后一条 + * @param array $params + * @param array $fields + * @return object|null + */ + public static function getLastOne(array $params, array $fields = ['*']): object|null + { + return self::where($params)->latest()->first($fields); + } +} diff --git a/app/Request/DoctorAuthRequest.php b/app/Request/DoctorAuthRequest.php index 9d44bfd..002b886 100644 --- a/app/Request/DoctorAuthRequest.php +++ b/app/Request/DoctorAuthRequest.php @@ -14,9 +14,6 @@ class DoctorAuthRequest extends FormRequest 'card_name', 'card_num' ], - 'getAuthIden' => [ // 获取身份认证信息 - 'source',// 来源(1:身份认证 2:简介) - ], 'addAuthIden' => [ // 新增身份认证信息 'avatar', 'hospital_id', @@ -31,12 +28,19 @@ class DoctorAuthRequest extends FormRequest // 'work_cert', 'doctor_expertise', 'source', + 'email', ], 'addAuthMulti' => [ // 新增多点执业认证信息 'id_card_front', 'id_card_back', 'sign_image' ], + 'putDoctorIntroduction' => [ // 修改个人简介 + 'avatar', + 'brief_introduction', + 'be_good_at', + 'doctor_expertise', + ], ]; /** @@ -70,6 +74,7 @@ class DoctorAuthRequest extends FormRequest 'id_card_back' => 'required|url', 'sign_image' => 'required|url', 'source' => 'required|integer|min:1|max:2', + 'email' => 'required', ]; } @@ -114,6 +119,7 @@ class DoctorAuthRequest extends FormRequest 'source.integer' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), 'source.min' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), 'source.max' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'email.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), ]; } } diff --git a/app/Request/DoctorInquiryConfigRequest.php b/app/Request/DoctorInquiryConfigRequest.php new file mode 100644 index 0000000..b3ed7cb --- /dev/null +++ b/app/Request/DoctorInquiryConfigRequest.php @@ -0,0 +1,108 @@ + [ // 获取医生问诊配置 + 'inquiry_type', + 'inquiry_mode', + ], + 'putDoctorInquiryOpen' => [ // 医生问诊开关 + 'inquiry_type', + 'inquiry_mode', + 'is_open', + ], + 'putDoctorInquiryConfig' => [ // 修改医生问诊配置 + 'inquiry_type', + 'inquiry_mode', + 'inquiry_price', + 'work_num_day', + ], + 'getInquiryServiceConfig' => [ // 获取医生问诊配置-服务设置 + 'inquiry_type', + 'inquiry_mode', + ], + 'addInquiryServiceConfig' => [ // 新增医生问诊配置-服务设置 + 'service_content', + 'service_process', + 'service_period', + 'service_rounds', + ], + 'putInquiryServiceConfig' => [ // 修改医生问诊配置-服务设置 + 'service_content', + 'service_process', + 'service_period', + 'service_rounds', + ], + ]; + + /** + * Determine if the user is authorized to make this request. + */ + public function authorize(): bool + { + return true; + } + + /** + * Get the validation rules that apply to the request. + */ + public function rules(): array + { + return [ + 'inquiry_type' => 'required|integer|min:1|max:3', + 'inquiry_mode' => 'required|integer|min:1|max:6', + 'is_open' => "required|boolean", + 'inquiry_price' => "required|min:0|numeric", + 'work_num_day' => "required|min:0|numeric", + 'service_content' => "required", + 'service_process' => "required", + 'service_period' => "required|min:2|max:30|numeric", + 'service_rounds' => "required|min:0|max:300|numeric", + ]; + } + + /** + * 获取已定义验证规则的错误消息. + */ + public function messages(): array + { + return [ + 'inquiry_type.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'inquiry_type.integer' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'inquiry_type.min' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'inquiry_type.max' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'inquiry_mode.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'inquiry_mode.integer' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'inquiry_mode.min' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'inquiry_mode.max' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'is_open.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'is_open.boolean' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'inquiry_price.required' => "请填写价格", + 'inquiry_price.min' => "价格填写错误", + 'inquiry_price.numeric' => "价格填写错误", + 'inquiry_mode.numeric' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'work_num_day.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'work_num_day.min' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'work_num_day.numeric' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'service_content.required' => "请填写服务内容", + 'service_process.required' => "请填写服务流程", + 'service_period.required' => "请填写服务周期", + 'service_period.min' => "服务周期最小值不可低于2", + 'service_period.max' => "服务周期最大值不可超过30", + 'service_period.numeric' => "服务周期填写错误", + 'service_rounds.required' => "请填写服务回合数", + 'service_rounds.min' => "服务回合数最小值不可低于0", + 'service_rounds.max' => "服务回合数最大值不可超过300", + 'service_rounds.numeric' => "服务回合数填写错误", + ]; + } +} diff --git a/app/Request/InquiryRequest.php b/app/Request/InquiryRequest.php index 9486c49..1e3c3b3 100644 --- a/app/Request/InquiryRequest.php +++ b/app/Request/InquiryRequest.php @@ -44,6 +44,15 @@ class InquiryRequest extends FormRequest 'patient_id', 'doctor_id', ], + 'addDoctorGiveInquiryOrder' => [ // 医生赠送沟通回合数 + 'order_inquiry_id', + 'times_number', // 沟通次数(0为不限制次数) + 'duration', // 沟通时长(分钟,0为不限制时长) + ], + 'addVideoReservationDate' => [ // 医生设置视频预约时间 + 'order_inquiry_id', + 'reservation_time', // 预约时间 + ], ]; /** @@ -61,7 +70,7 @@ class InquiryRequest extends FormRequest { return [ 'inquiry_type' => 'required|integer|min:1|max:4', - 'inquiry_mode' => 'required|integer|min:1|max:5', + 'inquiry_mode' => 'required|integer|min:1|max:6', 'patient_id' => 'required', 'family_id' => 'required', 'disease_class_id' => 'required', @@ -80,6 +89,9 @@ class InquiryRequest extends FormRequest 'reply_progress' => 'required|integer|min:0|max:5',// 'inquiry_status' => 'required|integer|min:0|max:4', + 'times_number' => "required|min:0|max:999|numeric", + 'duration' => "required|min:0|max:21600|numeric", + 'reservation_time' => "required", ]; } @@ -116,6 +128,7 @@ class InquiryRequest extends FormRequest 'inquiry_status.min' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), 'inquiry_status.max' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), 'order_inquiry_id.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'reservation_time.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), ]; } } diff --git a/app/Request/PatientDoctorRequest.php b/app/Request/PatientDoctorRequest.php index 8fc12fb..d71f563 100644 --- a/app/Request/PatientDoctorRequest.php +++ b/app/Request/PatientDoctorRequest.php @@ -44,7 +44,7 @@ class PatientDoctorRequest extends FormRequest return [ 'sort_order' => 'sometimes|integer|min:1|max:5', 'inquiry_type' => 'required|integer|min:1|max:4', - 'inquiry_mode' => 'required|integer|min:1|max:5', + 'inquiry_mode' => 'required|integer|min:1|max:7', 'my_doctor_type' => 'required|integer|min:1|max:2', 'is_first_online' => 'integer|min:0|max:1', ]; diff --git a/app/Request/UserDoctorRequest.php b/app/Request/UserDoctorRequest.php index 0e823ad..29d741d 100644 --- a/app/Request/UserDoctorRequest.php +++ b/app/Request/UserDoctorRequest.php @@ -11,21 +11,6 @@ use Hyperf\Validation\Rule; class UserDoctorRequest extends FormRequest { protected array $scenes = [ - 'getInquiryConfig' => [ // 获取医生问诊配置 - 'inquiry_type', - 'inquiry_mode', - ], - 'putInquiryOpen' => [ // 医生问诊开关 - 'inquiry_type', - 'inquiry_mode', - 'is_open', - ], - 'putInquiryConfig' => [ // 修改医生问诊配置 - 'inquiry_type', - 'inquiry_mode', - 'inquiry_price', - 'work_num_day', - ], 'addDoctorBankCard' => [ // 新增绑定医生银行卡 'bank_id', 'bank_card_code', @@ -92,10 +77,7 @@ class UserDoctorRequest extends FormRequest { return [ 'inquiry_type' => 'required|integer|min:1|max:3', - 'inquiry_mode' => 'required|integer|min:1|max:5', - 'is_open' => "required|boolean", - 'inquiry_price' => "required|min:0|numeric", - 'work_num_day' => "required|min:0|numeric", + 'inquiry_mode' => 'required|integer|min:1|max:6', 'bank_id' => "required", 'bank_card_code' => ['required'], 'province_id' => 'required|required_with:city_id,county_id', @@ -130,16 +112,7 @@ class UserDoctorRequest extends FormRequest 'inquiry_mode.integer' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), 'inquiry_mode.min' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), 'inquiry_mode.max' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), - 'is_open.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), - 'is_open.boolean' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), - 'inquiry_price.required' => "请填写价格", - 'inquiry_price.min' => "价格填写错误", - 'inquiry_price.numeric' => "价格填写错误", 'inquiry_mode.numeric' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), - 'work_num_day.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), - 'work_num_day.min' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), - 'work_num_day.numeric' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), - 'bank_id.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), 'bank_card_code.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), 'bank_card_code.regex' => "银行卡号填写错误", diff --git a/app/Request/VideoRequest.php b/app/Request/VideoRequest.php new file mode 100644 index 0000000..bae804f --- /dev/null +++ b/app/Request/VideoRequest.php @@ -0,0 +1,52 @@ + [ // 医生设置视频预约时间 + 'order_inquiry_id', + 'reservation_time', // 预约时间 + ], + 'addVideoRoom' => [ // 创建音视频房间 + 'order_inquiry_id', + ], + ]; + + /** + * Determine if the user is authorized to make this request. + */ + public function authorize(): bool + { + return true; + } + + /** + * Get the validation rules that apply to the request. + */ + public function rules(): array + { + return [ + 'order_inquiry_id' => 'required', + 'reservation_time' => "required", + ]; + } + + /** + * 获取已定义验证规则的错误消息. + */ + public function messages(): array + { + return [ + 'order_inquiry_id.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'reservation_time.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + ]; + } +} diff --git a/app/Services/DoctorAccountService.php b/app/Services/DoctorAccountService.php index 080386d..4872aee 100644 --- a/app/Services/DoctorAccountService.php +++ b/app/Services/DoctorAccountService.php @@ -32,12 +32,29 @@ class DoctorAccountService extends BaseService $date = date('Y-m-d',time()); - // 今日接诊收入 - $inquiryService = new InquiryService(); - $doctor_today_inquiry_total = $inquiryService->getDoctorDayAmountTotal($user_info['client_user_id'],$date); + // 获取医生数据 + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $user_doctor = UserDoctor::getOne($params); + if (empty($user_doctor)){ + return fail(); + } - // 今日已完成收入 - $doctor_day_completed_amount_total = $inquiryService->getDoctorDayCompletedAmountTotal($user_info['client_user_id'],$date); + $inquiryService = new InquiryService(); + + if ($user_doctor['is_platform_deep_cooperation'] == 0){ + // 获取医生当日接诊的订单金额 + $doctor_today_inquiry_total = $inquiryService->getDoctorDayAmountTotal($user_info['client_user_id'],$date); + + // 获取医生当日已完成未结束的订单金额 + $doctor_day_completed_amount_total = $inquiryService->getDoctorDayCompletedAmountTotal($user_info['client_user_id'],$date); + }else{ + // 获取医生当日接诊的订单金额-坐班医生 + $doctor_today_inquiry_total = $inquiryService->getCooperationDoctorDayAmountTotal($user_info['client_user_id'],$date); + + // 获取医生当日已完成未结束的订单金额-坐班医生 + $doctor_day_completed_amount_total = $inquiryService->getCooperationDoctorCompletedAmountTotal($user_info['client_user_id'],$date); + } // 获取医生账户余额 $balance_account = $this->getDoctorBalanceAccount($user_info['client_user_id']); @@ -69,7 +86,7 @@ class DoctorAccountService extends BaseService if (!empty($doctor_account_days)) { foreach ($doctor_account_days as $doctor_account_day) { $data = array(); - $data['total_amount'] = bcmul($doctor_account_day['total_amount'],1,2); + $data['total_amount'] = bcmul((string)$doctor_account_day['total_amount'],1,2); $data['month'] = $doctor_account_day['month']; $bill[] = $data; } @@ -77,9 +94,9 @@ class DoctorAccountService extends BaseService } $result = array(); - $result['doctor_today_inquiry_total'] = bcmul($doctor_today_inquiry_total,0.75,2); // 今日接诊收入 - $result['doctor_day_completed_amount_total'] = bcmul($doctor_day_completed_amount_total ,0.75,2); // 今日已完成收入 - $result['balance_account'] = bcmul($balance_account ,1,2); // 账户余额 + $result['doctor_today_inquiry_total'] = bcmul((string)$doctor_today_inquiry_total,"0.75",2); // 今日接诊收入 + $result['doctor_day_completed_amount_total'] = bcmul((string)$doctor_day_completed_amount_total ,"0.75",2); // 今日已完成收入 + $result['balance_account'] = bcmul((string)$balance_account ,"1",2); // 账户余额 $result['bill'] = $bill; // 账单 return success($result); @@ -97,6 +114,14 @@ class DoctorAccountService extends BaseService $page = $this->request->input('page', 1); $per_page = $this->request->input('per_page', 10); + // 获取医生数据 + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $user_doctor = UserDoctor::getOne($params); + if (empty($user_doctor)){ + return fail(); + } + // 获取当月开始时间 $start_date = date('Y-m-01 00:00:00', strtotime($date)); @@ -129,10 +154,15 @@ class DoctorAccountService extends BaseService $params = array(); $params['doctor_id'] = $user_info['client_user_id']; $inquiry_status_params = [4,5,6,7]; // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) - $order_inquiry = OrderInquiry:: getDoctorCreatedDateOrderInquiryPage($params, $reception_time, $inquiry_status_params,$fields,$page,$per_page); + + if ($user_doctor['is_platform_deep_cooperation'] == 0){ + $order_inquiry = OrderInquiry:: getDoctorCreatedDateOrderInquiryPage($params, $reception_time, $inquiry_status_params,[],$fields,$page,$per_page); + }else{ + $order_inquiry = OrderInquiry:: getDoctorCreatedDateOrderInquiryPage($params, $reception_time, $inquiry_status_params,[2,4],$fields,$page,$per_page); + } if (!empty($order_inquiry['data'])) { foreach ($order_inquiry['data'] as &$item) { - $item['estimate_income'] = bcmul($item['amount_total'],0.75,2); + $item['estimate_income'] = bcmul((string)$item['amount_total'],"0.75",2); // 入账状态 if ($item['inquiry_status'] == 4 || $item['inquiry_status'] == 5){ @@ -229,24 +259,28 @@ class DoctorAccountService extends BaseService $order_inquiry = OrderInquiry::getInList($params,$in_params); if (!empty($order_inquiry)){ foreach ($order_inquiry as $value){ - $amount_total = bcadd($amount_total,$value["amount_total"],2); + $amount_total = bcadd((string)$amount_total,(string)$value["amount_total"],2); } } $order_inquiry_id_array = $in_params; }else{ $InquiryService = new InquiryService(); - $order_inquiry = $InquiryService->getDoctorCanWithdrawalInquiryOrder($user_info['client_user_id']); + if ($user_doctor['is_platform_deep_cooperation'] == 0){ + $order_inquiry = $InquiryService->getDoctorCanWithdrawalInquiryOrder($user_info['client_user_id']); + }else{ + $order_inquiry = $InquiryService->getCooperationDoctorCanWithdrawalInquiryOrder($user_info['client_user_id']); + } if (!empty($order_inquiry)){ foreach ($order_inquiry as $value){ - $amount_total = bcadd($amount_total,$value["amount_total"],2); + $amount_total = bcadd((string)$amount_total,(string)$value["amount_total"],2); } $order_inquiry_id_array = array_column($order_inquiry,'order_inquiry_id'); } } - $amount_total = bcmul($amount_total,0.75,2); + $amount_total = bcmul((string)$amount_total,"0.75",2); // 计算医生个人所得税 @@ -277,6 +311,14 @@ class DoctorAccountService extends BaseService $page = $this->request->input('page', 1); $per_page = $this->request->input('per_page', 10); + // 获取医生信息 + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $user_doctor = UserDoctor::getOne($params); + if (empty($user_doctor)) { + return fail(); + } + // 获取医生当日接诊订单金额 $fields = [ 'order_inquiry_id', @@ -296,10 +338,18 @@ class DoctorAccountService extends BaseService $params = array(); $params['doctor_id'] = $user_info['client_user_id']; - $params['inquiry_status'] = 6; // inquiry_status:问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) $params['inquiry_refund_status'] = 0; // inquiry_refund_status:问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) - $order_inquiry = OrderInquiry:: getDoctorOrderInquiryPage($params, $fields,$page,$per_page); + $inquiry_status_params = [6]; // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + + + if ($user_doctor['is_platform_deep_cooperation'] == 0){ + $order_inquiry = OrderInquiry:: getDoctorOrderInquiryPage($params,$inquiry_status_params, $fields,$page,$per_page); + }else{ + $inquiry_type_not_params = [2,4]; + $order_inquiry = OrderInquiry:: getCooperationDoctorOrderInquiryPage($params,$inquiry_status_params,$inquiry_type_not_params, $fields,$page,$per_page); + } + if (!empty($order_inquiry['data'])) { foreach ($order_inquiry['data'] as &$item) { $item['expected_amount_total'] = floor($item['amount_total'] * 0.75 * 100) / 100; diff --git a/app/Services/DoctorAuthService.php b/app/Services/DoctorAuthService.php index 990ab29..74d8a89 100644 --- a/app/Services/DoctorAuthService.php +++ b/app/Services/DoctorAuthService.php @@ -4,8 +4,10 @@ namespace App\Services; use App\Constants\DoctorTitleCode; use App\Constants\HttpEnumCode; +use App\Model\DiseaseClassExpertise; use App\Model\DoctorExpertise; use App\Model\DoctorIdenFail; +use App\Model\DoctorIntroductionRecord; use App\Model\Hospital; use App\Model\HospitalDepartmentCustom; use App\Model\User; @@ -19,7 +21,7 @@ use GuzzleHttp\Exception\GuzzleException; use Hyperf\DbConnection\Db; /** - * 医生认证 + * 医生身份认证 */ class DoctorAuthService extends BaseService { @@ -233,14 +235,13 @@ class DoctorAuthService extends BaseService { $user_info = $this->request->getAttribute("userInfo") ?? []; - $source = $this->request->input('source'); // 来源(1:身份认证 2:简介) - // 获取医生数据 $fields = [ 'doctor_id', 'user_id', 'idcard_status', 'iden_auth_status', + 'introduction_status', 'avatar', 'hospital_id', 'department_custom_id', @@ -273,42 +274,40 @@ class DoctorAuthService extends BaseService // 职称转换 $result['doctor_title_name'] = empty($doctor['doctor_title']) ? "" : DoctorTitleCode::getMessage($doctor['doctor_title']); - if ($source == 1){ - // 获取医生详情数据 - $result['license_cert'] = []; - $result['qualification_cert'] = []; - $result['work_cert'] = []; + // 获取医生详情数据 + $result['license_cert'] = []; + $result['qualification_cert'] = []; + $result['work_cert'] = []; - $params = array(); - $params['doctor_id'] = $user_info['client_user_id']; - $user_doctor_info = UserDoctorInfo::getOne($params); - if (!empty($user_doctor_info)) { - // 医师执业证 - if (!empty($user_doctor_info['license_cert'])) { - $license_cert = explode(',', $user_doctor_info['license_cert']); - foreach ($license_cert as &$item) { - $item = addAliyunOssWebsite($item); - } - $result['license_cert'] = $license_cert; + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $user_doctor_info = UserDoctorInfo::getOne($params); + if (!empty($user_doctor_info)) { + // 医师执业证 + if (!empty($user_doctor_info['license_cert'])) { + $license_cert = explode(',', $user_doctor_info['license_cert']); + foreach ($license_cert as &$item) { + $item = addAliyunOssWebsite($item); } + $result['license_cert'] = $license_cert; + } - // 医师职称证 - if (!empty($user_doctor_info['qualification_cert'])) { - $qualification_cert = explode(',', $user_doctor_info['qualification_cert']); - foreach ($qualification_cert as &$item) { - $item = addAliyunOssWebsite($item); - } - $result['qualification_cert'] = $qualification_cert; + // 医师职称证 + if (!empty($user_doctor_info['qualification_cert'])) { + $qualification_cert = explode(',', $user_doctor_info['qualification_cert']); + foreach ($qualification_cert as &$item) { + $item = addAliyunOssWebsite($item); } + $result['qualification_cert'] = $qualification_cert; + } - // 医师资格证 - if (!empty($user_doctor_info['work_cert'])) { - $work_cert = explode(',', $user_doctor_info['work_cert']); - foreach ($work_cert as &$item) { - $item = addAliyunOssWebsite($item); - } - $result['work_cert'] = $work_cert; + // 医师资格证 + if (!empty($user_doctor_info['work_cert'])) { + $work_cert = explode(',', $user_doctor_info['work_cert']); + foreach ($work_cert as &$item) { + $item = addAliyunOssWebsite($item); } + $result['work_cert'] = $work_cert; } } @@ -338,19 +337,15 @@ class DoctorAuthService extends BaseService $UserDoctorService = new UserDoctorService(); $result['doctor_expertise'] = $UserDoctorService->getDoctorSelectedExpertise($doctor['doctor_id']); - // 获取医生身份认证失败原因 - $iden_auth_fail_reson = $this->getIdenAuthFailReason($doctor['iden_auth_status'], $doctor['doctor_id']); + // 获取用户邮箱 + $result['email'] = ""; - $result['avatar_reason'] = $iden_auth_fail_reson['avatar_reason'] ?? ""; - $result['department_custom_mobile_reason'] = $iden_auth_fail_reson['department_custom_mobile_reason'] ?? ""; - $result['brief_introduction_reason'] = $iden_auth_fail_reson['brief_introduction_reason'] ?? ""; - $result['be_good_at_reason'] = $iden_auth_fail_reson['be_good_at_reason'] ?? ""; - if ($source == 1){ - $result['license_cert_reason'] = $iden_auth_fail_reson['license_cert_reason'] ?? ""; - $result['qualification_cert_reason'] = $iden_auth_fail_reson['qualification_cert_reason'] ?? ""; - $result['work_cert_reason'] = $iden_auth_fail_reson['work_cert_reason'] ?? ""; + $params = array(); + $params['user_id'] = $doctor['user_id']; + $user = User::getOne($params); + if (!empty($user)){ + $result['email'] = $user['email']; } - $result['department_custom_name_reason'] = $iden_auth_fail_reson['department_custom_name_reason'] ?? ""; return success($result); } @@ -384,8 +379,17 @@ class DoctorAuthService extends BaseService return fail(HttpEnumCode::HTTP_ERROR, "审核中,暂不允许修改"); } + // 获取用户数据 + $params = array(); + $params['user_id'] = $doctor['user_id']; + $user = User::getOne($params); + if (empty($user)){ + return fail(HttpEnumCode::HTTP_ERROR, "用户错误"); + } + // 组合存储数据 $doctor_data = array();// 医生 + $user_data = array();// 用户 $doctor_info_data = array();// 医生详情 // 头像 @@ -443,6 +447,16 @@ class DoctorAuthService extends BaseService $doctor_data['be_good_at'] = $request_params['be_good_at']; } + // 邮箱 + if ($user['email'] != $request_params['email']) { + // 验证邮箱 + $res = PcreMatch::validateEmail($request_params['email']); + if (!$res){ + return fail(HttpEnumCode::HTTP_ERROR, "请填写正确邮箱"); + } + $user_data['email'] = $request_params['email']; + } + // 身份认证 if ($request_params['source'] == 1){ // 获取医生详情数据 @@ -617,6 +631,20 @@ class DoctorAuthService extends BaseService } } + // 修改用户邮箱 + if (!empty($user_data)){ + $params = array(); + $params['user_id'] = $user['user_id']; + + $data = array(); + $data['email'] = $request_params['email']; + $res = User::editUser($params, $data); + if (!$res) { + Db::rollBack(); + return fail(HttpEnumCode::SERVER_ERROR); + } + } + Db::commit(); } catch (\Exception $e) { Db::rollBack(); @@ -761,66 +789,375 @@ class DoctorAuthService extends BaseService /** * 获取医生身份认证失败原因 - * @param int|string $iden_auth_status - * @param string|int $doctor_id * @return array */ - public function getIdenAuthFailReason(int|string $iden_auth_status, string|int $doctor_id): array + public function getIdenAuthFailReason(): array { - $result = array(); + $user_info = $this->request->getAttribute("userInfo") ?? []; + + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $doctor = UserDoctor::getOne($params); + if (empty($doctor)) { + return fail(HttpEnumCode::HTTP_ERROR, "未知医生"); + } + + // 实名认证状态(0:未认证 1:认证通过 2:认证失败) + if ($doctor['idcard_status'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先实名认证"); + } // 身份认证状态(0:未认证 1:认证通过 2:审核中 3:认证失败) - if ($iden_auth_status == 3) { + if ($doctor['iden_auth_status'] != 3){ + return success(null); + } + + // 获取认证失败字段 + $params = array(); + $params['doctor_id'] = $doctor['doctor_id']; + $doctor_iden_fails = DoctorIdenFail::getList($params); + if (empty($doctor_iden_fails)){ + return success(null); + } + + $result = null; + foreach ($doctor_iden_fails as $doctor_iden_fail) { + $result[$doctor_iden_fail['field_name']] = $doctor_iden_fail['fail_reason']; + } + + return success($result); + } + + /** + * 获取医生个人简介审核失败原因 + * @return array + */ + public function getDoctorIntroductionFailReason(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $doctor = UserDoctor::getOne($params); + if (empty($doctor)) { + return fail(HttpEnumCode::HTTP_ERROR, "未知医生"); + } + + // 实名认证状态(0:未认证 1:认证通过 2:认证失败) + if ($doctor['idcard_status'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先实名认证"); + } + + // 身份认证状态(0:未认证 1:认证通过 2:审核中 3:认证失败) + if ($doctor['iden_auth_status'] != 3 && $doctor['iden_auth_status'] != 1){ + return success(null); + } + + // 个人简介审核状态(0:未审核 1:审核通过 2:审核中 3:审核失败) + if ($doctor['introduction_status'] != 3){ + return success(null); + } + + // 获取认证失败字段 + $params = array(); + $params['doctor_id'] = $doctor['doctor_id']; + $doctor_iden_fails = DoctorIdenFail::getList($params); + if (empty($doctor_iden_fails)){ + return success(null); + } + + $result = null; + foreach ($doctor_iden_fails as $doctor_iden_fail) { + // 头像 + if ($doctor_iden_fail['field_name'] == "avatar") { + $result[$doctor_iden_fail['field_name']] = $doctor_iden_fail['fail_reason']; + } + + // 医生简介 + if ($doctor_iden_fail['field_name'] == "brief_introduction") { + $result[$doctor_iden_fail['field_name']] = $doctor_iden_fail['fail_reason']; + } + + // 擅长 + if ($doctor_iden_fail['field_name'] == "be_good_at") { + $result[$doctor_iden_fail['field_name']] = $doctor_iden_fail['fail_reason']; + } + } + + return success($result); + } + + /** + * 获取个人简介 + * @return array + */ + public function getDoctorIntroduction(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + + // 获取医生数据 + $fields = [ + 'doctor_id', + 'user_id', + 'idcard_status', + 'iden_auth_status', + 'introduction_status', + 'avatar', + 'hospital_id', + 'department_custom_id', + 'department_custom_name', + 'department_custom_mobile', + 'doctor_title', + 'brief_introduction', + 'be_good_at', + ]; + + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $doctor = UserDoctor::getOne($params, $fields); + if (empty($doctor)) { + return fail(HttpEnumCode::HTTP_ERROR, "未知医生"); + } + + // 实名认证状态(0:未认证 1:认证通过 2:认证失败) + if ($doctor['idcard_status'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先实名认证"); + } + + $result = $doctor->toArray(); + + // 头像 + if (!empty($doctor['avatar'])) { + $result['avatar'] = addAliyunOssWebsite($doctor['avatar']); + } + + // 职称转换 + $result['doctor_title_name'] = empty($doctor['doctor_title']) ? "" : DoctorTitleCode::getMessage($doctor['doctor_title']); + + // 获取医生医院 + $result['hospital'] = []; + + $fields = [ + 'hospital_id', + 'hospital_name', + 'hospital_level_name', + 'province_id', + 'province', + 'city_id', + 'city', + 'county_id', + 'county', + ]; + + $params = array(); + $params['hospital_id'] = $doctor['hospital_id']; + $hospital = Hospital::getOne($params, $fields); + if (!empty($hospital)) { + $result['hospital'] = $hospital; + } + + // 获取医生已选择专长 + $UserDoctorService = new UserDoctorService(); + $result['doctor_expertise'] = $UserDoctorService->getDoctorSelectedExpertise($doctor['doctor_id']); + + // 获取修改数据 + $params = array(); + $params['doctor_id'] = $doctor['doctor_id']; + $doctor_introduction_record = DoctorIntroductionRecord::getOne($params); + if (!empty($doctor_introduction_record)){ + if (!empty($doctor_introduction_record['avatar'])){ + $result['avatar'] = addAliyunOssWebsite($doctor_introduction_record['avatar']); + } + + if (!empty($doctor_introduction_record['be_good_at'])){ + $result['be_good_at'] = $doctor_introduction_record['be_good_at']; + } + + if (!empty($doctor_introduction_record['brief_introduction'])){ + $result['brief_introduction'] = $doctor_introduction_record['brief_introduction']; + } + + // 处理专长 + if (!empty($doctor_introduction_record['expertise_ids'])){ + $result['doctor_expertise'] = array(); + + $expertise_ids = explode(',',$doctor_introduction_record['expertise_ids']); + foreach ($expertise_ids as $expertise_id){ + $params = array(); + $params['expertise_id'] = $expertise_id; + $disease_class_expertise = DiseaseClassExpertise::getOne($params); + if (empty($disease_class_expertise)){ + return fail(); + } + + $data = array(); + $data['expertise_id'] = $expertise_id; + $data['expertise_name'] = $disease_class_expertise['expertise_name']; + $result['doctor_expertise'][] = $data; + } + } + } + + return success($result); + } + + /** + * 修改个人简介 + * @return array + */ + public function putDoctorIntroduction(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + + $request_params = $this->request->all(); + + // 获取医生数据 + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $doctor = UserDoctor::getOne($params); + if (empty($doctor)) { + return fail(HttpEnumCode::HTTP_ERROR, "未知医生"); + } + + // 实名认证状态(0:未认证 1:认证通过 2:认证失败) + if ($doctor['idcard_status'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先实名认证"); + } + + // 身份认证状态(0:未认证 1:认证通过 2:审核中 3:认证失败) + if ($doctor['iden_auth_status'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先完成身份认证"); + } + + // 个人简介审核状态(0:未审核 1:审核通过 2:审核中 3:审核失败) + if ($doctor['introduction_status'] == 0){ + return fail(HttpEnumCode::HTTP_ERROR, "未审核,暂不允许修改"); + } + + if ($doctor['introduction_status'] == 2){ + return fail(HttpEnumCode::HTTP_ERROR, "审核中,暂不允许修改"); + } + + // 组合存储数据 + $doctor_introduction_record_data = array(); + + // 头像 + $request_params['avatar'] = PcreMatch::pregRemoveOssWebsite($request_params['avatar']); + if ($doctor['avatar'] != $request_params['avatar']) { + $doctor_introduction_record_data['avatar'] = $request_params['avatar']; + } + + // 医生简介 + if ($doctor['brief_introduction'] != $request_params['brief_introduction']) { + $doctor_introduction_record_data['brief_introduction'] = $request_params['brief_introduction']; + } + + // 擅长领域 + if ($doctor['be_good_at'] != $request_params['be_good_at']) { + $doctor_introduction_record_data['be_good_at'] = $request_params['be_good_at']; + } + + //已选择专长列表 + $expertise_ids = []; + + // 获取医生专长 + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $doctor_expertise = DoctorExpertise::getList($params); + if (!empty($doctor_expertise)) { + $expertise_ids = array_column($doctor_expertise->toArray(), 'expertise_id'); + } + + // 对比已选择专长 + // 对比专长是否删除 + $is_delete_expertise = array_diff($request_params['doctor_expertise'], $expertise_ids); + + // 对比专长是否新增 + if (empty($is_delete_expertise)) { + $is_add_expertise = array_diff($expertise_ids, $request_params['doctor_expertise']); + } + + // 专长是否改动:false(未改动) true(已改动) + $expertise_is_change = false; + if (!empty($is_delete_expertise) || !empty($is_add_expertise)) { + $doctor_introduction_record_data['expertise_ids'] = implode(',',$request_params['doctor_expertise']); + + $expertise_is_change = true; + } + + if (empty($doctor_introduction_record_data)){ + // 未修改 + return success(); + } + + // 审核失败,重新提交,判断被审核错误字段数据是否更改 + if ($doctor['introduction_status'] == 3){ // 获取认证失败字段 $params = array(); - $params['doctor_id'] = $doctor_id; + $params['doctor_id'] = $user_info['client_user_id']; $doctor_iden_fails = DoctorIdenFail::getList($params); - - if (!empty($doctor_iden_fails)) { - foreach ($doctor_iden_fails as $doctor_iden_fail) { + if (!empty($doctor_iden_fails)){ + foreach ($doctor_iden_fails as $doctor_iden_fail){ // 头像 if ($doctor_iden_fail['field_name'] == "avatar") { - $result['avatar_reason'] = $doctor_iden_fail['fail_reason']; - } - - // 科室电话 - if ($doctor_iden_fail['field_name'] == "department_custom_mobile") { - $result['department_custom_mobile_reason'] = $doctor_iden_fail['fail_reason']; - } - - // 科室名称 - if ($doctor_iden_fail['field_name'] == "department_custom_name") { - $result['department_custom_name_reason'] = $doctor_iden_fail['fail_reason']; + if ($doctor['avatar'] == $request_params['avatar']){ + return fail(HttpEnumCode::HTTP_ERROR,"医生头像" . $doctor_iden_fail['fail_reason']); + } } // 医生简介 if ($doctor_iden_fail['field_name'] == "brief_introduction") { - $result['brief_introduction_reason'] = $doctor_iden_fail['fail_reason']; + if ($doctor['brief_introduction'] == $request_params['brief_introduction']){ + return fail(HttpEnumCode::HTTP_ERROR,"医生简介" . $doctor_iden_fail['fail_reason']); + } } - // 擅长 + // 擅长领域 if ($doctor_iden_fail['field_name'] == "be_good_at") { - $result['be_good_at_reason'] = $doctor_iden_fail['fail_reason']; + if ($doctor['be_good_at'] == $request_params['be_good_at']){ + return fail(HttpEnumCode::HTTP_ERROR,"擅长领域" . $doctor_iden_fail['fail_reason']); + } } - // 医师执业证 - if ($doctor_iden_fail['field_name'] == "license_cert") { - $result['license_cert_reason'] = $doctor_iden_fail['fail_reason']; - } - - // 医师资格证 - if ($doctor_iden_fail['field_name'] == "qualification_cert") { - $result['qualification_cert_reason'] = $doctor_iden_fail['fail_reason']; - } - - // 医师工作证 - if ($doctor_iden_fail['field_name'] == "work_cert") { - $result['work_cert_reason'] = $doctor_iden_fail['fail_reason']; + // 专长 + if ($doctor_iden_fail['field_name'] == "expertise_ids") { + if (!$expertise_is_change){ + return fail(HttpEnumCode::HTTP_ERROR,"专长" . $doctor_iden_fail['fail_reason']); + } } } } } - return $result; + Db::beginTransaction(); + try { + // 新增医生简介修改记录表 + $doctor_introduction_record_data['doctor_id'] = $doctor['doctor_id']; + $doctor_introduction_record = DoctorIntroductionRecord::addDoctorIntroductionRecord($doctor_introduction_record_data); + if (empty($doctor_introduction_record)){ + Db::rollBack(); + return fail(HttpEnumCode::SERVER_ERROR); + } + + // 修改医生表个人简介审核状态 + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + + $data = array(); + $data['introduction_status'] = 2; + $data['updated_at'] = date('Y-m-d H:i:s', time()); + $res = UserDoctor::editUserDoctor($params, $data); + if (!$res) { + Db::rollBack(); + return fail(HttpEnumCode::SERVER_ERROR); + } + + Db::commit(); + } catch (\Exception $e) { + Db::rollBack(); + return fail(HttpEnumCode::SERVER_ERROR, $e->getMessage()); + } + + return success(); } } \ No newline at end of file diff --git a/app/Services/DoctorInquiryService.php b/app/Services/DoctorInquiryService.php index a32bd0b..2394e6b 100644 --- a/app/Services/DoctorInquiryService.php +++ b/app/Services/DoctorInquiryService.php @@ -5,13 +5,14 @@ namespace App\Services; use App\Constants\HttpEnumCode; use App\Exception\BusinessException; use App\Model\DoctorInquiryConfig; +use App\Model\DoctorInquiryConfigService; use App\Model\DoctorInquiryPriceRecord; use App\Model\SystemInquiryConfig; use App\Model\UserDoctor; use Hyperf\DbConnection\Db; /** - * 医生问诊 + * 医生问诊配置 */ class DoctorInquiryService extends BaseService { @@ -19,16 +20,12 @@ class DoctorInquiryService extends BaseService * 获取医生问诊配置 * @return array */ - public function getInquiryConfig(): array + public function getDoctorInquiryConfig(): array { $user_info = $this->request->getAttribute("userInfo") ?? []; $inquiry_type = $this->request->input('inquiry_type');// 接诊类型(1:专家问诊 2:快速问诊 3:公益问诊) - $inquiry_mode = $this->request->input('inquiry_mode');// 接诊方式(1:图文 2:视频 3:语音 4:电话 5:会员) - - $result = array(); - $result['info'] = array(); // 配置信息 - $result['config'] = array(); // 系统配置 + $inquiry_mode = $this->request->input('inquiry_mode');// 接诊方式(1:图文 2:视频 3:语音 4:电话 5:会员 6:疑难会诊) // 获取医生信息 $params = array(); @@ -50,14 +47,16 @@ class DoctorInquiryService extends BaseService return fail(HttpEnumCode::HTTP_ERROR, "请先进行绑定结算银行卡"); } + // 返回数据 + $result = array(); + $info = array(); + $config = array(); + // 接诊开关 $is_open = 0; // 接诊价格 - $result['info']['inquiry_price'] = 0; - - // 接诊人数 - $result['info']['work_num_day'] = 30; + $info['inquiry_price'] = 0; // 系统问诊配置表 $params = array(); @@ -76,22 +75,25 @@ class DoctorInquiryService extends BaseService $doctor_inquiry_config = DoctorInquiryConfig::getOne($params); if (empty($doctor_inquiry_config)) { // 接诊价格 - $result['info']['inquiry_price'] = $system_inquiry_config['inquiry_price'] ?: 0; + $info['inquiry_price'] = $system_inquiry_config['inquiry_price'] ?: 0; if ($inquiry_type == 3) { // 公益问诊,存在价格档次,默认第一档 $inquiry_price = explode(',', $system_inquiry_config['inquiry_price']); - $result['info']['inquiry_price'] = $inquiry_price[0]; - } - } else { - // 接诊价格 - $result['info']['inquiry_price'] = $doctor_inquiry_config['inquiry_price'] ?: 0; - if ($inquiry_type == 2) { - // 快速-系统配置 - $result['info']['inquiry_price'] = $system_inquiry_config['inquiry_price']; + $info['inquiry_price'] = $inquiry_price[0]; } - $result['info']['work_num_day'] = $doctor_inquiry_config['work_num_day'] ?: 0; + // 默认接诊人数 + $info['work_num_day'] = $system_inquiry_config['default_work_num_day'] ?: 0; + } else { + // 接诊价格 + $info['inquiry_price'] = $doctor_inquiry_config['inquiry_price'] ?: 0; + if ($inquiry_type == 2) { + // 快速-系统配置 + $info['inquiry_price'] = $system_inquiry_config['inquiry_price']; + } + + $info['work_num_day'] = $doctor_inquiry_config['work_num_day'] ?: 0; // 接诊开关 if ($doctor_inquiry_config['is_enable'] == 1){ @@ -100,32 +102,35 @@ class DoctorInquiryService extends BaseService } // 接诊开关 - $result['info']['is_open'] = $is_open; + $info['is_open'] = $is_open; // 每日最大接诊数量 - $result['config']['max_work_num_day'] = $system_inquiry_config['max_work_num_day']; + $config['max_work_num_day'] = $system_inquiry_config['max_work_num_day']; // 最低接诊价格(专家问诊) - $result['config']['min_inquiry_price'] = $system_inquiry_config['min_inquiry_price'] ?: 0; + $config['min_inquiry_price'] = $system_inquiry_config['min_inquiry_price'] ?: 0; // 最高接诊价格(专家问诊) - $result['config']['max_inquiry_price'] = $system_inquiry_config['max_inquiry_price'] ?: 0; + $config['max_inquiry_price'] = $system_inquiry_config['max_inquiry_price'] ?: 0; // 默认价格 - $result['config']['default_inquiry_price'] = $system_inquiry_config['max_inquiry_price'] ?: 0; + $config['default_inquiry_price'] = $system_inquiry_config['max_inquiry_price'] ?: 0; // 沟通次数(0为不限制次数) - $result['config']['times_number'] = $system_inquiry_config['times_number']; + $config['times_number'] = $system_inquiry_config['times_number']; // 沟通时长(分钟,0为不限制时长) - $result['config']['duration'] = $system_inquiry_config['duration']; + $config['duration'] = $system_inquiry_config['duration']; // 系统价格(公益问诊) - $result['config']['system_inquiry_price'] = []; + $config['system_inquiry_price'] = []; if ($inquiry_type == 3) { - $result['config']['system_inquiry_price'] = explode(',', $system_inquiry_config['inquiry_price']); + $config['system_inquiry_price'] = explode(',', $system_inquiry_config['inquiry_price']); } + $result['info'] = $info; + $result['config'] = $config; + return success($result); } @@ -133,7 +138,7 @@ class DoctorInquiryService extends BaseService * 医生问诊开关 * @return array */ - public function putInquiryOpen(): array + public function putDoctorInquiryOpen(): array { $user_info = $this->request->getAttribute("userInfo") ?? []; @@ -171,13 +176,6 @@ class DoctorInquiryService extends BaseService $params['inquiry_mode'] = $inquiry_mode; $doctor_inquiry_config = DoctorInquiryConfig::getOne($params); if (empty($doctor_inquiry_config)) { - // 无问诊配置,快速问诊创建问诊配置并打开问诊。其余类型直接返回错误 - if ($inquiry_type != 2){ - // 快速问诊可能会存在未创建的情况 - Db::rollBack(); - return fail(HttpEnumCode::HTTP_ERROR, "请先完善问诊配置"); - } - // 获取系统问诊配置表 $params = array(); $params['inquiry_type'] = $inquiry_type; @@ -196,7 +194,7 @@ class DoctorInquiryService extends BaseService $data['inquiry_mode'] = $inquiry_mode; $data['is_enable'] = 1; // 是否启用(0:否 1:是) $data['last_enable_method'] = 1; // 最后开启方式(1:自己 2:后台) - $data['work_num_day'] = $system_inquiry_config['max_work_num_day'] ?: 0; + $data['work_num_day'] = $system_inquiry_config['default_work_num_day'] ?: 0; $data['inquiry_price'] = $system_inquiry_config['inquiry_price']; $doctor_inquiry_config = DoctorInquiryConfig::addInquiryConfig($data); @@ -228,7 +226,7 @@ class DoctorInquiryService extends BaseService * 修改医生问诊配置 * @return array */ - public function putInquiryConfig(): array + public function putDoctorInquiryConfig(): array { $user_info = $this->request->getAttribute("userInfo") ?? []; @@ -358,7 +356,9 @@ class DoctorInquiryService extends BaseService $data['inquiry_price'] = $inquiry_price; DoctorInquiryConfig::editInquiryConfig($params, $data); + } + if ($doctor_inquiry_config['inquiry_price'] != $inquiry_price) { // 记录修改记录 $data = array(); $data['doctor_id'] = $user_info['client_user_id']; @@ -420,4 +420,181 @@ class DoctorInquiryService extends BaseService return $inquiry_price; } + + /** + * 获取医生问诊配置-服务设置 + * @return array + */ + public function getInquiryServiceConfig(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + + $inquiry_type = $this->request->input('inquiry_type');// 接诊类型(1:专家问诊 2:快速问诊 3:公益问诊) + $inquiry_mode = $this->request->input('inquiry_mode');// 接诊方式(1:图文 2:视频 3:语音 4:电话 5:会员 6:疑难会诊) + + if ($inquiry_mode != 6){ + return fail(); + } + + // 获取医生信息 + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $doctor = UserDoctor::getOne($params); + if (empty($doctor)) { + return fail(HttpEnumCode::HTTP_ERROR, "未知医生"); + } + + if ($doctor['idcard_status'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先进行实名认证"); + } + + if ($doctor['iden_auth_status'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先进行身份认证"); + } + + if ($doctor['is_bind_bank'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先进行绑定结算银行卡"); + } + + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $params['inquiry_type'] = $inquiry_type; + $params['inquiry_mode'] = $inquiry_mode; + $doctor_inquiry_config_service = DoctorInquiryConfigService::getOne($params); + if (empty($doctor_inquiry_config_service)){ + return success(null); + }else{ + return success($doctor_inquiry_config_service->toArray()); + } + } + + /** + * 新增医生问诊配置-服务设置 + * @return array + */ + public function addInquiryServiceConfig(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + + $service_content = $this->request->input('service_content'); + $service_process = $this->request->input('service_process'); + $service_period = $this->request->input('service_period'); + $service_rounds = $this->request->input('service_rounds'); + + // 获取医生信息 + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $doctor = UserDoctor::getOne($params); + if (empty($doctor)) { + return fail(HttpEnumCode::HTTP_ERROR, "未知医生"); + } + + if ($doctor['idcard_status'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先进行实名认证"); + } + + if ($doctor['iden_auth_status'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先进行身份认证"); + } + + if ($doctor['is_bind_bank'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先进行绑定结算银行卡"); + } + + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $params['inquiry_type'] = 1; + $params['inquiry_mode'] = 6; + $doctor_inquiry_config_service = DoctorInquiryConfigService::getOne($params); + if (!empty($doctor_inquiry_config_service)){ + return fail(HttpEnumCode::HTTP_ERROR, "已存在服务设置,请勿重复设置"); + } + + $data = array(); + $data['doctor_id'] = $doctor['doctor_id']; + $data['inquiry_type'] = 1; + $data['inquiry_mode'] = 6; + $data['service_content'] = $service_content; + $data['service_process'] =$service_process; + $data['service_period'] =$service_period; + $data['service_rounds'] =$service_rounds; + $doctor_inquiry_config_service = DoctorInquiryConfigService::addDoctorInquiryConfigService($data); + if (empty($doctor_inquiry_config_service)){ + return fail(); + } + + return success(); + } + + /** + * 修改医生问诊配置-服务设置 + * @return array + */ + public function putInquiryServiceConfig(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + + $config_service_id = $this->request->route('config_service_id'); + + $service_content = $this->request->input('service_content'); + $service_process = $this->request->input('service_process'); + $service_period = $this->request->input('service_period'); + $service_rounds = $this->request->input('service_rounds'); + + // 获取医生信息 + $params = array(); + $params['doctor_id'] = $user_info['client_user_id']; + $doctor = UserDoctor::getOne($params); + if (empty($doctor)) { + return fail(HttpEnumCode::HTTP_ERROR, "未知医生"); + } + + if ($doctor['idcard_status'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先进行实名认证"); + } + + if ($doctor['iden_auth_status'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先进行身份认证"); + } + + if ($doctor['is_bind_bank'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "请先进行绑定结算银行卡"); + } + + $params = array(); + $params['config_service_id'] = $config_service_id; + $params['doctor_id'] = $user_info['client_user_id']; + $doctor_inquiry_config_service = DoctorInquiryConfigService::getOne($params); + if (empty($doctor_inquiry_config_service)){ + return fail(); + } + + $data = array(); + if ($doctor_inquiry_config_service['service_content'] != $service_content){ + $data['service_content'] = $service_content; + } + + if ($doctor_inquiry_config_service['service_process'] != $service_process){ + $data['service_process'] = $service_process; + } + + if ($doctor_inquiry_config_service['service_period'] != $service_period){ + $data['service_period'] = $service_period; + } + + if ($doctor_inquiry_config_service['service_rounds'] != $service_rounds){ + $data['service_rounds'] = $service_rounds; + } + + if (!empty($data)){ + $params = array(); + $params['config_service_id'] = $doctor_inquiry_config_service['config_service_id']; + $res = DoctorInquiryConfigService::edit($params,$data); + if (!$res){ + return fail(); + } + } + + return success(); + } } \ No newline at end of file diff --git a/app/Services/ImService.php b/app/Services/ImService.php index 2b9680c..a4bbd24 100644 --- a/app/Services/ImService.php +++ b/app/Services/ImService.php @@ -281,9 +281,10 @@ class ImService extends BaseService try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -316,9 +317,10 @@ class ImService extends BaseService try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -352,16 +354,18 @@ class ImService extends BaseService * @param array|object $order_inquiry 问诊订单数据 * @param string $doctor_user_id 医生用户id * @param string $patient_user_id 患者用户id + * @param float|int $time * @return void */ - public function doctorInquiry(array|object $order_inquiry, string $doctor_user_id, string $patient_user_id): void + public function doctorInquiry(array|object $order_inquiry, string $doctor_user_id, string $patient_user_id,float|int $time): void { try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -371,19 +375,16 @@ class ImService extends BaseService $message_content_data = array(); $message_content_data['message_type'] = 1; - if ($order_inquiry['inquiry_type'] == 1) { - $message_content_data['title'] = "—问诊已开始,本次问诊可持续24小时—"; - $message_content_data['desc'] = "医生已接诊,为提高沟通效率,您可一次性如实补充病情(具体症状,患病时长,用药情况及想咨询的问题等)。线上咨询不能代替面诊,医生建议仅供参考。"; - } elseif ($order_inquiry['inquiry_type'] == 2) { - $message_content_data['title'] = "—问诊已开始,本次问诊可持续60分钟—"; - $message_content_data['desc'] = "医生已接诊,为提高沟通效率,您可一次性如实补充病情(具体症状,患病时长,就医用药情况及想咨询的问题等)。线上咨询不能代替面诊,医生建议仅供参考。"; - } elseif ($order_inquiry['inquiry_type'] == 3) { - $message_content_data['title'] = "—问诊已开始,本次问诊可持续24小时—"; - $message_content_data['desc'] = "医生已接诊,为提高沟通效率,您可一次性如实补充病情(具体症状,患病时长,就医用药情况及想咨询的问题等)。线上咨询不能代替面诊,医生建议仅供参考。"; - } elseif ($order_inquiry['inquiry_type'] == 4) { - $message_content_data['title'] = "—问诊已开始,本次问诊可持续30分钟—"; - $message_content_data['desc'] = "医生已接诊,为提高沟通效率,您可一次性如实补充病情(具体症状,患病时长,就医用药情况及想咨询的问题等)。线上咨询不能代替面诊,医生建议仅供参考。"; + $time = $time / 60 / 60; + if ($time >= 1){ + $time = $time . "小时"; + }else{ + $time = $time * 60 . "分钟"; } + + $message_content_data['title'] = "—问诊已开始,本次问诊可持续{$time}—"; + $message_content_data['desc'] = "医生已接诊,为提高沟通效率,您可一次性如实补充病情(具体症状,患病时长,用药情况及想咨询的问题等)。线上咨询不能代替面诊,医生建议仅供参考。"; + $message_content = [ 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), ]; @@ -406,9 +407,10 @@ class ImService extends BaseService try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -445,9 +447,10 @@ class ImService extends BaseService try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -485,9 +488,10 @@ class ImService extends BaseService try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -520,9 +524,10 @@ class ImService extends BaseService { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -533,7 +538,7 @@ class ImService extends BaseService $message_content_data['message_type'] = 2; // 订单结束评价弹出 // $message_content_data['title'] = "评价"; $message_content_data['desc'] = ""; - $message_content_data['data']['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $message_content_data['data']['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $message_content = [ 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), @@ -557,9 +562,10 @@ class ImService extends BaseService try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -597,9 +603,10 @@ class ImService extends BaseService try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -631,9 +638,10 @@ class ImService extends BaseService try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -676,6 +684,7 @@ class ImService extends BaseService $cloud_custom_data['order_inquiry_id'] = (string)$data['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $data['inquiry_type']; // 订单类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药 5:检测) + $cloud_custom_data['inquiry_mode'] = $data['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['order_no'] = $data['detection_no']; $cloud_custom_data['patient_family_data']['patient_name'] = $data['patient_name']; @@ -690,7 +699,7 @@ class ImService extends BaseService $message_content_data['data']['order_no'] = (string)$data['detection_no']; $message_content_data['data']['disease_class_names'] = $data['disease_class_names']; $message_content_data['data']['detection_link'] = addAliyunOssWebsite($data['detection_result_pdf']);// 检测结果链接(oss) - $message_content_data['data']['message_path'] = "/pages/checkOrderDetail/checkOrderDetail?order_detection_id=" . $data['detection_no']; // 跳转地址(小程序内页) + $message_content_data['data']['message_path'] = "sugarCheck/pages/checkOrderDetail/checkOrderDetail?order_detection_id=" . $data['detection_no']; // 跳转地址(小程序内页) $message_content = [ 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), ]; @@ -704,12 +713,7 @@ class ImService extends BaseService /** * 糖组检测报告-文字 - * @param array|object $order_detection - * @param string $doctor_name 医生名称 - * @param string $detection_project_name 检测项目名称 - * @param string $doctor_user_id 医生user_id - * @param string $patient_user_id 患者user_id - * @param string|int $inquiry_type + * @param array $data * @return void */ public function detectionTestReportStr(array $data): void @@ -720,6 +724,7 @@ class ImService extends BaseService $cloud_custom_data['order_inquiry_id'] = (string)$data['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $data['inquiry_type']; // 订单类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药 5:检测) + $cloud_custom_data['inquiry_mode'] = $data['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['order_no'] = $data['detection_no']; $cloud_custom_data['patient_family_data']['patient_name'] = $data['patient_name']; @@ -741,7 +746,7 @@ class ImService extends BaseService * 患者病例 * @param array|object $order_inquiry * @param string $doctor_user_id - * @param string $disease_desc + * @param string|null $disease_desc * @return void */ public function patientCase(array|object $order_inquiry, string $doctor_user_id,string|null $disease_desc = ""): void @@ -749,9 +754,10 @@ class ImService extends BaseService try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -762,9 +768,9 @@ class ImService extends BaseService $message_content_data['message_type'] = 11; $message_content_data['title'] = "患者信息"; $message_content_data['desc'] = ""; - $message_content_data['data']['order_no'] = $order_inquiry['inquiry_no']; + $message_content_data['data']['order_no'] = (string)$order_inquiry['inquiry_no']; $message_content_data['data']['disease_desc'] = $disease_desc ?: ""; - $message_content_data['data']['message_path'] = "/Pages/yishi/case/index?order_inquiry_id=" . $order_inquiry['order_inquiry_id']; // 跳转地址(小程序内页) + $message_content_data['data']['message_path'] = "user/pages/case/index?order_inquiry_id=" . $order_inquiry['order_inquiry_id']; // 跳转地址(小程序内页) $message_content = [ 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), ]; @@ -789,9 +795,10 @@ class ImService extends BaseService try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -802,9 +809,9 @@ class ImService extends BaseService $message_content_data['message_type'] = 12; $message_content_data['title'] = "问诊表"; $message_content_data['desc'] = ""; - $message_content_data['data']['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; - $message_content_data['data']['order_no'] = $order_inquiry['inquiry_no']; - $message_content_data['data']['message_path'] = "/pages/sickForm/sickForm"; // 跳转地址(小程序内页) + $message_content_data['data']['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; + $message_content_data['data']['order_no'] = (string)$order_inquiry['inquiry_no']; + $message_content_data['data']['message_path'] = "patient/pages/sickForm/sickForm"; // 跳转地址(小程序内页) $message_content_data['data']['case_not_fill_fields'] = $case_fields; // 病例字段,json格式,医生端发送患者端使用(此字段仅针对message_type为12的情况) $message_content = [ 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), @@ -830,9 +837,10 @@ class ImService extends BaseService try { // 发送消息 $cloud_custom_data = array(); - $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; $cloud_custom_data['is_system'] = 1; $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; $cloud_custom_data['message_rounds'] = 0; $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; @@ -843,10 +851,10 @@ class ImService extends BaseService $message_content_data['message_type'] = 12; $message_content_data['title'] = "问诊表-已填写"; $message_content_data['desc'] = ""; - $message_content_data['data']['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; - $message_content_data['data']['order_no'] = $order_inquiry['inquiry_no']; - $message_content_data['data']['message_path'] = "/Pages/yishi/sick_detail/index"; // 跳转地址(小程序内页) - $message_content_data['data']['case_patient_message_path'] = "/pages/sickDetail/sickDetail"; // 跳转地址(小程序内页) + $message_content_data['data']['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; + $message_content_data['data']['order_no'] = (string)$order_inquiry['inquiry_no']; + $message_content_data['data']['message_path'] = "user/pages/sick_detail/index"; // 跳转地址(小程序内页) + $message_content_data['data']['case_patient_message_path'] = "/patient/sickDetail/sickDetail"; // 跳转地址(小程序内页) $message_content_data['data']['case_filled_fields'] = $case_fields; // 病例字段,json格式,患者端发送医生端使用(此字段仅针对message_type为12的情况) $message_content = [ 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), @@ -858,4 +866,238 @@ class ImService extends BaseService throw new BusinessException($e->getMessage()); } } + + /** + * 赠送回合数消息 + * @param array|object $order_inquiry 问诊表数据 + * @param string|int $doctor_user_id 医生用户id + * @param string|int $patient_user_id 患者用户id + * @param string $times_number 沟通次数(0为不限制次数) + * @param string $give_expiration_time 赠送到期时间 + * @return void + */ + public function giveFreeRounds(array|object $order_inquiry, string|int $doctor_user_id, string|int $patient_user_id, string $times_number, string $give_expiration_time): void + { + try { + // 发送消息 + $cloud_custom_data = array(); + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; + $cloud_custom_data['is_system'] = 1; + $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; + $cloud_custom_data['message_rounds'] = 0; + $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; + $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; + $cloud_custom_data['patient_family_data']['patient_age'] = $order_inquiry['patient_age']; + + // 消息内容 + $message_content_data = array(); + $message_content_data['message_type'] = 13; + $message_content_data['title'] = ""; + $message_content_data['desc'] = "医生已赠送" . "" . $times_number . "个" . "沟通回合数,将在" . "" . $give_expiration_time . "失效 ,如有需要请尽快给医生留言。"; + $message_content_data['data']['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; + $message_content_data['data']['order_no'] = (string)$order_inquiry['inquiry_no']; + $message_content_data['data']['times_number'] = $times_number; + $message_content_data['data']['give_expiration_time'] = $give_expiration_time; + $message_content = [ + 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), + ]; + + $this->sendMessage($doctor_user_id,$patient_user_id, $message_content, "TIMCustomElem", $cloud_custom_data); + } catch (\Throwable $e) { + throw new BusinessException($e->getMessage()); + } + } + + /** + * 订单结束,提醒赠送回合数-发送医生 + * @param array|object $order_inquiry 问诊订单数据 + * @param string $doctor_user_id 医生用户id + * @param string $patient_user_id 患者用户id + * @return void + */ + public function remindGiveFreeRounds(array|object $order_inquiry, string $doctor_user_id, string $patient_user_id): void + { + try { + // 发送消息 + $cloud_custom_data = array(); + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; + $cloud_custom_data['is_system'] = 1; + $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; + $cloud_custom_data['message_rounds'] = 0; + $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; + $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; + $cloud_custom_data['patient_family_data']['patient_age'] = $order_inquiry['patient_age']; + + // 消息内容 医生-患者 + $message_content_data = array(); + $message_content_data['message_type'] = 14; + $message_content_data['title'] = ""; + $message_content_data['desc'] = "点击更多选择【赠送沟通】,您可以赠送患者沟通回合数。"; + $message_content = [ + 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), + ]; + + $this->sendMessage($doctor_user_id, $patient_user_id, $message_content, "TIMCustomElem", $cloud_custom_data); + } catch (\Exception $e) { + throw new BusinessException($e->getMessage()); + } + } + + /** + * 新增视频预约时间-发送医生 + * @param array|object $order_inquiry 问诊订单数据 + * @param string $doctor_user_id 医生用户id + * @param string $patient_user_id 患者用户id + * @param string $reservation_time 预约时间 + * @return void + */ + public function addVideoReservationTimeToDoctor(array|object $order_inquiry, string $doctor_user_id, string $patient_user_id,string $reservation_time): void + { + try { + // 发送消息 + $cloud_custom_data = array(); + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; + $cloud_custom_data['is_system'] = 1; + $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; + $cloud_custom_data['message_rounds'] = 0; + $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; + $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; + $cloud_custom_data['patient_family_data']['patient_age'] = $order_inquiry['patient_age']; + + $date = date("Y年m月d日 H点i分",strtotime($reservation_time)); + + // 消息内容 医生-患者 + $message_content_data = array(); + $message_content_data['message_type'] = 16; + $message_content_data['title'] = ""; + $message_content_data['desc'] = "您和患者已约定于" . "" . $date . "进行视频问诊,请提前进入聊天页面,在约定时间发起视频"; + $message_content = [ + 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), + ]; + + $this->sendMessage($doctor_user_id, $patient_user_id, $message_content, "TIMCustomElem", $cloud_custom_data); + } catch (\Exception $e) { + throw new BusinessException($e->getMessage()); + } + } + + /** + * 修改视频预约时间-发送医生 + * @param array|object $order_inquiry 问诊订单数据 + * @param string $doctor_user_id 医生用户id + * @param string $patient_user_id 患者用户id + * @param string $reservation_time 预约时间 + * @return void + */ + public function modifyVideoReservationTimeToDoctor(array|object $order_inquiry, string $doctor_user_id, string $patient_user_id,string $reservation_time): void + { + try { + // 发送消息 + $cloud_custom_data = array(); + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; + $cloud_custom_data['is_system'] = 1; + $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; + $cloud_custom_data['message_rounds'] = 0; + $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; + $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; + $cloud_custom_data['patient_family_data']['patient_age'] = $order_inquiry['patient_age']; + + $date = date("Y年m月d日 H点i分",strtotime($reservation_time)); + + // 消息内容 医生-患者 + $message_content_data = array(); + $message_content_data['message_type'] = 16; + $message_content_data['title'] = ""; + $message_content_data['desc'] = "您和患者重新约定于" . "" . $date . "进行视频问诊,请提前进入聊天页面,再约定时间发起视频"; + $message_content = [ + 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), + ]; + + $this->sendMessage($doctor_user_id, $patient_user_id, $message_content, "TIMCustomElem", $cloud_custom_data); + } catch (\Exception $e) { + throw new BusinessException($e->getMessage()); + } + } + + /** + * 新增视频预约时间-发送患者 + * @param array|object $order_inquiry 问诊订单数据 + * @param string $doctor_user_id 医生用户id + * @param string $patient_user_id 患者用户id + * @param string $reservation_time 预约时间 + * @return void + */ + public function addVideoReservationTimeToPatient(array|object $order_inquiry, string $doctor_user_id, string $patient_user_id,string $reservation_time): void + { + try { + // 发送消息 + $cloud_custom_data = array(); + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; + $cloud_custom_data['is_system'] = 1; + $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; + $cloud_custom_data['message_rounds'] = 0; + $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; + $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; + $cloud_custom_data['patient_family_data']['patient_age'] = $order_inquiry['patient_age']; + + $date = date("Y年m月d日 H点i分",strtotime($reservation_time)); + + // 消息内容 医生-患者 + $message_content_data = array(); + $message_content_data['message_type'] = 17; + $message_content_data['title'] = ""; + $message_content_data['desc'] = "您和医生已约定于" . "" . $date . "进行视频问诊,请提前进入聊天页面,准备接听。"; + $message_content = [ + 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), + ]; + + $this->sendMessage($doctor_user_id, $patient_user_id, $message_content, "TIMCustomElem", $cloud_custom_data); + } catch (\Exception $e) { + throw new BusinessException($e->getMessage()); + } + } + + /** + * 修改视频预约时间-发送患者 + * @param array|object $order_inquiry 问诊订单数据 + * @param string $doctor_user_id 医生用户id + * @param string $patient_user_id 患者用户id + * @param string $reservation_time 预约时间 + * @return void + */ + public function modifyVideoReservationTimeToPatient(array|object $order_inquiry, string $doctor_user_id, string $patient_user_id,string $reservation_time): void + { + try { + // 发送消息 + $cloud_custom_data = array(); + $cloud_custom_data['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; + $cloud_custom_data['is_system'] = 1; + $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; + $cloud_custom_data['inquiry_mode'] = $order_inquiry['inquiry_mode']; + $cloud_custom_data['message_rounds'] = 0; + $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; + $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; + $cloud_custom_data['patient_family_data']['patient_age'] = $order_inquiry['patient_age']; + + $date = date("Y年m月d日 H点i分",strtotime($reservation_time)); + + // 消息内容 医生-患者 + $message_content_data = array(); + $message_content_data['message_type'] = 17; + $message_content_data['title'] = ""; + $message_content_data['desc'] = "您和医生重新约定于" . "" . $date . "进行视频问诊,请提前进入聊天页面,准备接听。"; + $message_content = [ + 'Data' => json_encode($message_content_data, JSON_UNESCAPED_UNICODE), + ]; + + $this->sendMessage($doctor_user_id, $patient_user_id, $message_content, "TIMCustomElem", $cloud_custom_data); + } catch (\Exception $e) { + throw new BusinessException($e->getMessage()); + } + } } \ No newline at end of file diff --git a/app/Services/IndexService.php b/app/Services/IndexService.php index a2b2517..0af084a 100644 --- a/app/Services/IndexService.php +++ b/app/Services/IndexService.php @@ -148,6 +148,7 @@ class IndexService extends BaseService "iden_auth_status", "iden_auth_fail_reason", "multi_point_status", + "introduction_status", "is_bind_bank", "praise_rate", "avg_response_time", @@ -224,6 +225,7 @@ class IndexService extends BaseService $info['not_accepted_inquiry_num'] = $not_accepted_inquiry_num ?? 0;// 获取未接诊患者个数 $info['accepting_inquiry_num'] = $accepting_inquiry_num ?? 0;// 获取接诊中患者个数 $info['reject_prescription_number'] = $reject_prescription_number ?? 0;// 获取被驳回处方数据 + $info['introduction_status'] = $doctor['introduction_status'];// 个人简介审核状态(0:未审核 1:审核通过 2:审核中 3:审核失败) $data = array(); $data['banner'] = $banner ?? [];// banner diff --git a/app/Services/InquiryConfigService.php b/app/Services/InquiryConfigService.php new file mode 100644 index 0000000..902e507 --- /dev/null +++ b/app/Services/InquiryConfigService.php @@ -0,0 +1,14 @@ +getNotFinishedOrderInquiry($request_params['inquiry_type'], $user_info['client_user_id']); + $order_inquiry_id = $PatientOrderService->getNotFinishedOrderInquiry($request_params['inquiry_type'],$request_params['inquiry_mode'],$user_info['client_user_id']); if (!empty($order_inquiry_id)) { $result['status'] = 2; $result['message'] = "当前患者存在进行中的问诊订单"; @@ -191,13 +200,22 @@ class InquiryService extends BaseService $diagnose_images = PcreMatch::pregRemoveOssWebsite($diagnose_images); } + // 沟通次数,沟通时长 + $params = array(); + $params['inquiry_type'] = $request_params['inquiry_type']; + $params['inquiry_mode'] = $request_params['inquiry_mode']; + $system_inquiry_config = SystemInquiryConfig::getOne($params); + if (empty($system_inquiry_config)) { + return fail(HttpEnumCode::SERVER_ERROR, "订单创建失败"); + } + Db::beginTransaction(); $generator = $this->container->get(IdGeneratorInterface::class); try { // 实际付款金额 - $payment_amount_total = bcsub($inquiry_price , $coupon_amount_total,2); + $payment_amount_total = bcsub($inquiry_price, $coupon_amount_total, 2); if ($payment_amount_total < 0) { $payment_amount_total = 0; } @@ -221,10 +239,12 @@ class InquiryService extends BaseService $data['amount_total'] = $inquiry_price;// 订单金额 $data['coupon_amount_total'] = $coupon_amount_total;// 优惠卷总金额 $data['payment_amount_total'] = $payment_amount_total;// 实际付款金额 + $data['times_number'] = $system_inquiry_config['times_number'];// 沟通次数(0为不限制次数) + $data['duration'] = $system_inquiry_config['duration'];// 沟通时长(分钟,0为不限制时长) $data['patient_name'] = $patient_family['card_name'];// 患者姓名-就诊人 $data['patient_name_mask'] = $patient_family['card_name_mask'];// 患者姓名-就诊人(掩码) $data['patient_sex'] = $patient_family['sex'];// 患者性别-就诊人(0:未知 1:男 2:女) - $data['patient_age'] = $patient_family['age'];// 患者年龄-就诊人 + $data['patient_age'] = getIdCardAge($patient_family['id_number']);// 患者年龄-就诊人 $order_inquiry = OrderInquiry::addOrderInquiry($data); if (empty($order_inquiry)) { Db::rollBack(); @@ -246,109 +266,109 @@ class InquiryService extends BaseService $data['disease_desc'] = $request_params['disease_desc']; // 病情描述(主诉) $data['diagnose_images'] = $diagnose_images ?? ""; // 复诊凭证(多个使用逗号分隔) - if ($patient_family['age'] != null){ - $data['age'] = $patient_family['age'];// 患者年龄 + if ($patient_family['age'] != null) { + $data['age'] = getIdCardAge($patient_family['id_number']);// 患者年龄 } // 身高(cm) - if ($patient_family['height'] != null){ + if ($patient_family['height'] != null) { $data['height'] = $patient_family['height']; } // 体重(kg) - if ($patient_family['weight'] != null){ + if ($patient_family['weight'] != null) { $data['weight'] = $patient_family['weight']; } // 职业id-职业名称 - if ($patient_family['job_id'] != null){ + if ($patient_family['job_id'] != null) { $data['job_id'] = $patient_family['job_id']; - if ($patient_family['job_name'] != null){ + if ($patient_family['job_name'] != null) { $data['job_name'] = $patient_family['job_name']; } } // 民族id-民族名称 - if ($patient_family['nation_id'] != null){ + if ($patient_family['nation_id'] != null) { $data['nation_id'] = $patient_family['nation_id']; - if ($patient_family['nation_name'] != null){ + if ($patient_family['nation_name'] != null) { $data['nation_name'] = $patient_family['nation_name']; } } // 婚姻状况 - if ($patient_family['marital_status'] != null){ + if ($patient_family['marital_status'] != null) { $data['marital_status'] = $patient_family['marital_status']; } // 家庭成员-健康情况 - if (!empty($patient_family_health)){ - if ($patient_family_health['diagnosis_hospital'] != null){ + if (!empty($patient_family_health)) { + if ($patient_family_health['diagnosis_hospital'] != null) { $data['diagnosis_hospital'] = $patient_family_health['diagnosis_hospital']; // 确诊医院 } - if ($patient_family_health['is_take_medicine'] != null){ + if ($patient_family_health['is_take_medicine'] != null) { $data['is_take_medicine'] = $patient_family_health['is_take_medicine']; // 正在服药 - if ($patient_family_health['drugs_name'] != null){ + if ($patient_family_health['drugs_name'] != null) { $data['drugs_name'] = $patient_family_health['drugs_name']; // 正在服药名称 } } } // 家庭成员-个人情况 - if (!empty($patient_family_personal)){ - if ($patient_family_personal['drink_wine_status'] != null){ + if (!empty($patient_family_personal)) { + if ($patient_family_personal['drink_wine_status'] != null) { $data['drink_wine_status'] = $patient_family_personal['drink_wine_status']; // 饮酒状态 } - if ($patient_family_personal['smoke_status'] != null){ + if ($patient_family_personal['smoke_status'] != null) { $data['smoke_status'] = $patient_family_personal['smoke_status']; // 吸烟状态 } - if ($patient_family_personal['chemical_compound_status'] != null){ + if ($patient_family_personal['chemical_compound_status'] != null) { $data['chemical_compound_status'] = $patient_family_personal['chemical_compound_status']; // 化合物状态 - if ($patient_family_personal['chemical_compound_describe'] != null){ + if ($patient_family_personal['chemical_compound_describe'] != null) { $data['chemical_compound_describe'] = $patient_family_personal['chemical_compound_describe']; // 化合物描述 } } - if ($patient_family_personal['is_operation'] != null){ + if ($patient_family_personal['is_operation'] != null) { $data['is_operation'] = $patient_family_personal['is_operation']; // 是否存在手术 - if ($patient_family_personal['operation'] != null){ + if ($patient_family_personal['operation'] != null) { $data['operation'] = $patient_family_personal['operation']; // 手术描述 } } } // 过敏史 - if (array_key_exists("is_allergy_history",$request_params)){ + if (array_key_exists("is_allergy_history", $request_params)) { if ($request_params['is_allergy_history'] !== null) { $data['is_allergy_history'] = $request_params['is_allergy_history']; // 是否存在过敏史(0:否 1:是) - if ($request_params['allergy_history'] != ""){ + if ($request_params['allergy_history'] != "") { $data['allergy_history'] = $request_params['allergy_history']; // 过敏史描述 } } } // 家族病史 - if (array_key_exists("is_family_history",$request_params)){ + if (array_key_exists("is_family_history", $request_params)) { if ($request_params['is_family_history'] !== null) { $data['is_family_history'] = $request_params['is_family_history']; // 是否存在家族病史(0:否 1:是) - if ($request_params['family_history'] != ""){ + if ($request_params['family_history'] != "") { $data['family_history'] = $request_params['family_history']; // 家族病史描述 } } } // 是否备孕、妊娠、哺乳期(0:否 1:是) - if (array_key_exists("is_pregnant",$request_params)){ + if (array_key_exists("is_pregnant", $request_params)) { if ($request_params['is_pregnant'] !== null) { $data['is_pregnant'] = $request_params['is_pregnant']; // 是否备孕、妊娠、哺乳期(0:否 1:是) } } // 是否存在禁忌药物(0:否 1:是)问诊购药时存在 - if (array_key_exists("is_taboo",$request_params)){ + if (array_key_exists("is_taboo", $request_params)) { if ($request_params['is_taboo'] !== null) { $data['is_taboo'] = $request_params['is_taboo']; // 是否存在禁忌药物(0:否 1:是)问诊购药时存在 } @@ -362,7 +382,7 @@ class InquiryService extends BaseService // 处理优惠卷数据 if (!empty($user_coupons)) { - foreach ($user_coupons as $user_coupon){ + foreach ($user_coupons as $user_coupon) { // 增加问诊优惠卷表 $data = array(); $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id'];// 订单-问诊id @@ -509,11 +529,11 @@ class InquiryService extends BaseService // 民族 $nation_name = ""; - if (isset($patient_family)){ - if (!empty($patient_family['nation_name'])){ + if (isset($patient_family)) { + if (!empty($patient_family['nation_name'])) { $nation_name = $patient_family['nation_name']; - }else{ - if (!empty($order_inquiry_case['nation_name'])){ + } else { + if (!empty($order_inquiry_case['nation_name'])) { $nation_name = $order_inquiry_case['nation_name']; } } @@ -853,6 +873,8 @@ class InquiryService extends BaseService return fail(HttpEnumCode::HTTP_ERROR, "订单错误"); } + $order_inquiry = $order_inquiry->toArray(); + if ($user_info['user_type'] == 1) { if ($order_inquiry['patient_id'] != $user_info['client_user_id']) { return fail(HttpEnumCode::SERVER_ERROR); @@ -872,34 +894,12 @@ class InquiryService extends BaseService return fail(); } - $times_number = 0; // 沟通次数 - $duration = 0; // 沟通时长 $follow = false; // 关注状态 $is_evaluation = false; // 评价状态 - // 沟通次数,沟通时长 - $params = array(); - $params['inquiry_type'] = $order_inquiry['inquiry_type']; - $params['inquiry_mode'] = $order_inquiry['inquiry_mode']; - $system_inquiry_config = SystemInquiryConfig::getOne($params); - if (!empty($system_inquiry_config)) { - $times_number = $system_inquiry_config['times_number']; - $duration = $system_inquiry_config['duration']; - } - - // 获取医生问诊配置-问诊购药 - $multi_point_enable = 0; - - $params = array(); - $params['doctor_id'] = $user_doctor['doctor_id']; - $params['inquiry_type'] = 4; - $params['inquiry_mode'] = 1; - $doctor_inquiry_config = DoctorInquiryConfig::getOne($params); - if (!empty($doctor_inquiry_config)) { - if ($doctor_inquiry_config['is_enable'] == 1){ - $multi_point_enable = 1;// 是否开启问诊购药 - } - } + // 处理可处方字段 + $userDoctorService = new UserDoctorService(); + $multi_point_enable = $userDoctorService->getDoctorMultiPointEnable($user_doctor["doctor_id"]); if ($user_info['user_type'] == 1) { // 关注状态 @@ -916,6 +916,41 @@ class InquiryService extends BaseService $is_evaluation = OrderEvaluation::getExists($params); } + // 处理问诊回合数及时长-兼容旧数据 + if (empty($order_inquiry['times_number']) || empty($order_inquiry['duration'])) { + // 疑难问诊特殊处理 + if ($order_inquiry['inquiry_type'] == 1 && $order_inquiry['inquiry_mode'] == 6 ){ + $params = array(); + $params['doctor_id'] = $order_inquiry['doctor_id']; + $params['inquiry_type'] = $order_inquiry['inquiry_type']; + $params['inquiry_mode'] = $order_inquiry['inquiry_mode']; + $doctor_inquiry_config_service = DoctorInquiryConfigService::getOne($params); + if (empty($doctor_inquiry_config_service)){ + return fail(); + } + + $order_inquiry['times_number'] = $doctor_inquiry_config_service['service_rounds']; // 服务回合数 + $order_inquiry['duration'] = $doctor_inquiry_config_service['service_period'] * 24 * 60; // 服务周期 + }else{ + $params = array(); + $params['inquiry_type'] = $order_inquiry['inquiry_type']; + $params['inquiry_mode'] = $order_inquiry['inquiry_mode']; + $system_inquiry_config = SystemInquiryConfig::getOne($params); + if (empty($system_inquiry_config)) { + return fail(); + } + + if (empty($order_inquiry['times_number'])) { + $order_inquiry['times_number'] = $system_inquiry_config['times_number']; + } + + if (empty($order_inquiry['duration'])) { + $order_inquiry['duration'] = $system_inquiry_config['duration']; + } + } + + } + $result = array(); $result['doctor_user_id'] = $user_doctor['user_id']; $result['patient_user_id'] = $order_inquiry['user_id']; @@ -927,9 +962,10 @@ class InquiryService extends BaseService $result['patient_family_sex'] = $order_inquiry['patient_sex']; $result['patient_family_age'] = $order_inquiry['patient_age']; $result['inquiry_type'] = $order_inquiry['inquiry_type']; + $result['inquiry_mode'] = $order_inquiry['inquiry_mode']; $result['inquiry_status'] = $order_inquiry['inquiry_status']; - $result['times_number'] = $times_number; - $result['duration'] = $duration; + $result['times_number'] = $order_inquiry['times_number']; // 沟通次数(0为不限制次数) + $result['duration'] = $order_inquiry['duration']; // 沟通时长(分钟,0为不限制时长) $result['follow'] = $follow; $result['is_evaluation'] = $is_evaluation; $result['reception_time'] = $order_inquiry['reception_time'] ?: null; // 接诊时间 @@ -963,7 +999,7 @@ class InquiryService extends BaseService $params['user_id'] = $item['user_id']; $params['family_id'] = $item['family_id']; - $inquiry_status_params = [5,6]; + $inquiry_status_params = [5, 6]; $fields = [ 'order_inquiry_id', @@ -987,11 +1023,11 @@ class InquiryService extends BaseService 'created_at', ]; - $order_inquiry = OrderInquiry::getInquiryStatusLastOne($params,$inquiry_status_params,$fields); + $order_inquiry = OrderInquiry::getInquiryStatusLastOne($params, $inquiry_status_params, $fields); unset($item['user_id']); unset($item['family_id']); - if (!empty($order_inquiry)){ + if (!empty($order_inquiry)) { $item = $order_inquiry->toArray(); $params = array(); @@ -1007,7 +1043,8 @@ class InquiryService extends BaseService /** * 结束问诊 * @return array - * @throws GuzzleException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function putFinishInquiry(): array { @@ -1089,8 +1126,13 @@ class InquiryService extends BaseService $data = array(); $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $time = 60 * 60 * 24 * 3; + if (\Hyperf\Config\config("app_env") == "dev"){ + $time = 60; + } + $message = new AutoFinishInquiryDelayDirectProducer($data); - $message->setDelayMs(1000 * 60 * 60 * 24 * 3); + $message->setDelayMs(1000 * $time); $producer = $this->container->get(Producer::class); $res = $producer->produce($message); if (!$res) { @@ -1109,6 +1151,9 @@ class InquiryService extends BaseService $imService = new ImService(); $imService->inquiryComplete($order_inquiry, $user_doctor['user_id'], $order_inquiry['user_id']); + // 发送IM消息-订单结束,提醒赠送回合数(医生端) + $imService->remindGiveFreeRounds($order_inquiry, $user_doctor['user_id'], $order_inquiry['user_id']); + // 发送IM消息-问诊结束评价通知 $imService->inquiryEndEvaluation($order_inquiry, $user_doctor['user_id'], $order_inquiry['user_id']); @@ -1146,8 +1191,8 @@ class InquiryService extends BaseService $params['patient_id'] = $patient_id; $params['doctor_id'] = $doctor_id; - $inquiry_status_params = [3,4,5,6,7]; - $order_inquiry = OrderInquiry::getInquiryStatusLastOne($params,$inquiry_status_params); + $inquiry_status_params = [3, 4, 5, 6, 7]; + $order_inquiry = OrderInquiry::getInquiryStatusLastOne($params, $inquiry_status_params); if (empty($order_inquiry)) { return success(""); } @@ -1155,6 +1200,218 @@ class InquiryService extends BaseService return success($order_inquiry['order_inquiry_id']); } + /** + * 医生赠送沟通回合数 + * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function addDoctorGiveInquiryOrder(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + + $order_inquiry_id = $this->request->input('order_inquiry_id'); + $times_number = $this->request->input('times_number'); + $duration = $this->request->input('duration'); + + if (empty($user_info)) { + return fail(HttpEnumCode::HTTP_ERROR, "操作失败"); + } + + // 检测赠送的回合数和周期 + if (!in_array($duration, [3 * 24 * 60, 7 * 24 * 60, 15 * 24 * 60])) { + return fail(HttpEnumCode::HTTP_ERROR, "请重新选择周期"); + } + + // 获取问诊订单数据 + $params = array(); + $params['order_inquiry_id'] = $order_inquiry_id; + $params['doctor_id'] = $user_info['client_user_id']; + $order_inquiry = OrderInquiry::getOne($params); + if (empty($order_inquiry)) { + return fail(); + } + + // 检测订单状态 + if (!in_array($order_inquiry['inquiry_status'], [5, 6, 7])) { + return fail(HttpEnumCode::HTTP_ERROR, "问诊订单未完成,不可赠送"); + } + + // 检测是否存在同类型未完成的问诊订单 + $PatientOrderService = new PatientOrderService(); + $result = $PatientOrderService->getNotFinishedOrderInquiry($order_inquiry['inquiry_type'],$order_inquiry['inquiry_mode'], $order_inquiry['patient_id']); + if (!empty($result)) { + return fail(HttpEnumCode::HTTP_ERROR, "当前患者存在进行中的问诊订单"); + } + + // 检测当前医生是否和患者存在未完成问诊订单 + $InquiryService = new InquiryService(); + $result = $InquiryService->checkPatientDoctorProgressInquiry($order_inquiry['patient_id'], $user_info['client_user_id']); + if (!empty($result)) { + return fail(HttpEnumCode::HTTP_ERROR, "当前患者和您存在问诊订单,不可赠送"); + } + + // 获取本次问诊病例 + $params = array(); + $params['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $order_inquiry_case = OrderInquiryCase::getOne($params); + if (empty($order_inquiry_case)) { + return fail(); + } + + // 创建订单 + Db::beginTransaction(); + + $generator = $this->container->get(IdGeneratorInterface::class); + + try { + // 生成问诊订单 + $data = array(); + $data['user_id'] = $order_inquiry['user_id']; + $data['patient_id'] = $order_inquiry['patient_id']; + $data['doctor_id'] = $order_inquiry['doctor_id']; + $data['family_id'] = $order_inquiry['family_id']; + $data['inquiry_type'] = $order_inquiry['inquiry_type']; + $data['inquiry_mode'] = 7; + $data['inquiry_status'] = 4; + $data['inquiry_pay_channel'] = 3;// 支付渠道(1:小程序支付 2:微信扫码支付) + $data['inquiry_pay_status'] = 2; + $data['inquiry_no'] = $generator->generate();// 订单编号 + $data['escrow_trade_no'] = "GD" . $generator->generate(); // 第三方支付流水号 + $data['amount_total'] = 0;// 订单金额 + $data['coupon_amount_total'] = 0;// 优惠卷总金额 + $data['payment_amount_total'] = 0;// 实际付款金额 + $data['pay_time'] = date('Y-m-d H:i:s', time());// 支付时间 + $data['reception_time'] = date('Y-m-d H:i:s', time());// 接诊时间(已接诊) + $data['times_number'] = $times_number;// 沟通次数(0为不限制次数) + $data['duration'] = $duration;// 沟通时长(分钟,0为不限制时长) + $data['patient_name'] = $order_inquiry['patient_name'];// 患者姓名-就诊人 + $data['patient_name_mask'] = $order_inquiry['patient_name_mask'];// 患者姓名-就诊人(掩码) + $data['patient_sex'] = $order_inquiry['patient_sex'];// 患者性别-就诊人(0:未知 1:男 2:女) + $data['patient_age'] = $order_inquiry['patient_age'];// 患者年龄-就诊人 + $order_inquiry = OrderInquiry::addOrderInquiry($data); + if (empty($order_inquiry)) { + Db::rollBack(); + return fail(HttpEnumCode::SERVER_ERROR, "赠送失败"); + } + + // 增加患者问诊病例 + unset($order_inquiry_case["inquiry_case_id"]); + unset($order_inquiry_case["order_inquiry_id"]); + unset($order_inquiry_case["created_at"]); + unset($order_inquiry_case["updated_at"]); + + $data = array(); + $data = $order_inquiry_case->toArray(); + $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id'];// 订单-问诊id + $order_inquiry_case = OrderInquiryCase::addOrderInquiryCase($data); + if (empty($order_inquiry_case)) { + Db::rollBack(); + return fail(HttpEnumCode::SERVER_ERROR, "赠送失败"); + } + + // 不处理意向用药 + + Db::commit(); + } catch (\Throwable $e) { + Db::rollBack(); + Log::getInstance("InquiryService-addDoctorGiveInquiryOrder")->error($e->getMessage()); + return fail(HttpEnumCode::SERVER_ERROR, $e->getMessage()); + } + + // 发送消息 + try { + // 赠送到期时间 + $give_expiration_time = date('Y-m-d H:i:s', time() + $duration * 60); + + // 获取订单医生数据 + $params = array(); + $params['doctor_id'] = $order_inquiry['doctor_id']; + $user_doctor = UserDoctor::getOne($params); + if (empty($user_doctor)) { + return fail(HttpEnumCode::SERVER_ERROR, "赠送失败"); + } + + // 发送im消息 + $imService = new ImService(); + + // 赠送回合数消息 + $imService->giveFreeRounds($order_inquiry, $user_doctor['user_id'], $order_inquiry['user_id'], $times_number, $give_expiration_time); + + // 发送站内、订阅失败发送短信消息-患者-赠送回合数 + $MessagePush = new MessagePush($order_inquiry['user_id'], $order_inquiry['order_inquiry_id']); + $MessagePush->doctorGiveFreeRounds($times_number, $give_expiration_time); + } catch (\Throwable $e) { + Log::getInstance("InquiryService-addDoctorGiveInquiryOrder")->error($e->getMessage()); + } + + $result = array(); + $result['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; // 订单主键id + $result['inquiry_no'] = (string)$order_inquiry['inquiry_no']; // 订单编号 + + return success($result); + } + + /** + * 获取视频问诊消息内页基础数据 + * @return array + */ + public function getInquiryVideoMessageBasic(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + + $order_inquiry_id = $this->request->route('order_inquiry_id'); + + // 获取问诊订单数据 + $params = array(); + $params['order_inquiry_id'] = $order_inquiry_id; + $order_inquiry = OrderInquiry::getOne($params); + if (empty($order_inquiry)) { + return fail(); + } + + if ($user_info['user_type'] == 1) { + if ($order_inquiry['patient_id'] != $user_info['client_user_id']) { + return fail(HttpEnumCode::SERVER_ERROR); + } + } + + if ($user_info['user_type'] == 2) { + if ($order_inquiry['doctor_id'] != $user_info['client_user_id']) { + return fail(HttpEnumCode::SERVER_ERROR); + } + } + + // 定义返回数据 + $is_reservation_time = false; // 是否已设置预约时间 + $is_video = false; // 是否已开视频(0:否 1:是) + $update_number = 0; // 修改次数 + + // 获取视频预约数据 + $params = array(); + $params['order_inquiry_id'] = $order_inquiry_id; + $order_inquiry_video_reservation = OrderInquiryVideoReservation::getOne($params); + if (!empty($order_inquiry_video_reservation)) { + $is_reservation_time = true; // 是否已设置预约时间 + + $update_number = $order_inquiry_video_reservation['update_number']; // 修改次数 + + // 检测是否已开过视频 + $params = array(); + $params['order_inquiry_id'] = $order_inquiry_id; + $order_inquiry_video_record = OrderInquiryVideoRecord::getOne($params); + if (!empty($order_inquiry_video_record)) { + $is_video = true; // 是否已开视频(0:否 1:是) + } + } + + $result = array(); + $result['is_reservation_time'] = $is_reservation_time; + $result['is_video'] = $is_video; + $result['update_number'] = $update_number; + return success($result); + } + /** * 获取医生未接诊订单数量 * @param string $doctor_id 医生id @@ -1227,9 +1484,43 @@ class InquiryService extends BaseService $reception_time = [$start_date, $end_date]; - $inquiry_status_params = [4,5]; // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + $inquiry_status_params = [4, 5]; // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) - $amount_total_sum = OrderInquiry::getOrderInquiryBetweenTimeAmountTotalSum($params, $reception_time, $inquiry_status_params); + $amount_total_sum = OrderInquiry::getDoctorAmountTotal($params, $reception_time, $inquiry_status_params); + + return $amount_total_sum ?: 0; + } + + /** + * 获取医生当日接诊的订单金额-坐班医生 + * 状态:已接诊 + * 排除快速-购药 + * @param string $doctor_id + * @param string $date + * @return float + */ + public function getCooperationDoctorDayAmountTotal(string $doctor_id, string $date): float + { + // 获取当天开始时间 + $start_date = date('Y-m-d 00:00:00', strtotime($date)); + + // 获取当天结束时间 + $end_date = date('Y-m-d 23:59:59', strtotime($date)); + + // 获取医生当日接诊订单金额 + $params = array(); + $params['doctor_id'] = $doctor_id; + $params['inquiry_refund_status'] = 0; // 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) + $params['inquiry_pay_status'] = 2; // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) + $params['is_withdrawal'] = 0; // 是否提现(0:否 1:是 2:提现中) + + $reception_time = [$start_date, $end_date]; + + $inquiry_status_params = [4, 5]; // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + + $inquiry_type_not_params = [2, 4]; + + $amount_total_sum = OrderInquiry::getCooperationDoctorAmountTotal($params, $reception_time, $inquiry_status_params, $inquiry_type_not_params); return $amount_total_sum ?: 0; } @@ -1260,7 +1551,41 @@ class InquiryService extends BaseService $inquiry_status_params = [5]; // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) - $amount_total_sum = OrderInquiry::getOrderInquiryBetweenTimeAmountTotalSum($params, $reception_time, $inquiry_status_params); + $amount_total_sum = OrderInquiry::getDoctorAmountTotal($params, $reception_time, $inquiry_status_params); + + return $amount_total_sum ?: 0; + } + + /** + * 获取医生当日已完成未结束的订单金额-坐班医生 + * 状态:已完成 + * 排除快速-购药 + * @param string $doctor_id + * @param string $date + * @return float + */ + public function getCooperationDoctorCompletedAmountTotal(string $doctor_id, string $date): float + { + // 获取当天开始时间 + $start_date = date('Y-m-d 00:00:00', strtotime($date)); + + // 获取当天结束时间 + $end_date = date('Y-m-d 23:59:59', strtotime($date)); + + // 获取医生当日接诊订单金额 + $params = array(); + $params['doctor_id'] = $doctor_id; + $params['inquiry_refund_status'] = 0; // 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) + $params['inquiry_pay_status'] = 2; // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) + $params['is_withdrawal'] = 0; // 是否提现(0:否 1:是 2:提现中) + + $reception_time = [$start_date, $end_date]; + + $inquiry_status_params = [5]; // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + + $inquiry_type_not_params = [2, 4]; + + $amount_total_sum = OrderInquiry::getCooperationDoctorAmountTotal($params, $reception_time, $inquiry_status_params, $inquiry_type_not_params); return $amount_total_sum ?: 0; } @@ -1289,6 +1614,33 @@ class InquiryService extends BaseService return $order_inquiry->toArray(); } + /** + * 获取医生可提现金额-坐班医生 + * @param string $doctor_id + * @return array + */ + public function getCooperationDoctorCanWithdrawalInquiryOrder(string $doctor_id): array + { + // 获取医生当日接诊订单金额 + $params = array(); + $params['doctor_id'] = $doctor_id; + $params['inquiry_refund_status'] = 0; // 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) + $params['inquiry_pay_status'] = 2; // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) + $params['statistics_status'] = 1; // 订单统计状态(0:未统计 1:已统计 2:统计失败) + $params['is_withdrawal'] = 0; // 是否提现(0:否 1:是 2:提现中) + + $inquiry_status_params = [6]; // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + + $inquiry_type_not_params = [2, 4]; + + $order_inquiry = OrderInquiry::getCooperationDoctorCanWithdrawalInquiryOrder($params, $inquiry_status_params, $inquiry_type_not_params); + if (empty($order_inquiry)) { + return []; + } + + return $order_inquiry->toArray(); + } + /** * 获取患者某一状态下的问诊订单数量 * @param string $patient_id 患者id @@ -1311,7 +1663,7 @@ class InquiryService extends BaseService * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ - public function inquiryRefund(string $order_inquiry_id, string $refund_reason) + public function inquiryRefund(string $order_inquiry_id, string $refund_reason): void { // 获取订单数据 $params = array(); @@ -1394,9 +1746,9 @@ class InquiryService extends BaseService $params = array(); $params['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; $order_inquiry_coupons = OrderInquiryCoupon::getList($params); - if (!empty($order_inquiry_coupons)){ + if (!empty($order_inquiry_coupons)) { $userCouponService = new UserCouponService(); - foreach ($order_inquiry_coupons as $order_inquiry_coupon){ + foreach ($order_inquiry_coupons as $order_inquiry_coupon) { // 退还优惠卷 $userCouponService->returnUserCoupon($order_inquiry_coupon['user_coupon_id']); @@ -1521,9 +1873,9 @@ class InquiryService extends BaseService $params = array(); $params['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; $order_inquiry_coupons = OrderInquiryCoupon::getList($params); - if (!empty($order_inquiry_coupons)){ + if (!empty($order_inquiry_coupons)) { $userCouponService = new UserCouponService(); - foreach ($order_inquiry_coupons as $order_inquiry_coupon){ + foreach ($order_inquiry_coupons as $order_inquiry_coupon) { // 退还优惠卷 $userCouponService->returnUserCoupon($order_inquiry_coupon['user_coupon_id']); @@ -1648,7 +2000,7 @@ class InquiryService extends BaseService } // 随机初始时间 - $time = mt_rand(60,600); + $time = mt_rand(60, 600); $wait_pay_time = 60 * 30;// 待支付时间 $wait_assign_time = 60 * 5;// 待分配时间 $wait_inquiry_time = 0; // 待接诊时间 @@ -1683,7 +2035,7 @@ class InquiryService extends BaseService case '1': // 待支付 $wait_pay_time = $wait_pay_time - (time() - strtotime($order_inquiry['created_at'])); - if ($wait_pay_time < 0 ){ + if ($wait_pay_time < 0) { $wait_pay_time = 0; } @@ -1696,7 +2048,7 @@ class InquiryService extends BaseService case '3': // 待接诊 $wait_inquiry_time = $wait_inquiry_time - (time() - strtotime($order_inquiry['pay_time'])); - if ($wait_inquiry_time < 0 ){ + if ($wait_inquiry_time < 0) { $wait_inquiry_time = 0; } @@ -1705,7 +2057,7 @@ class InquiryService extends BaseService case '4': // 已接诊 $wait_finish_time = $wait_finish_time - (time() - strtotime($order_inquiry['reception_time'])); - if ($wait_finish_time < 0 ){ + if ($wait_finish_time < 0) { $wait_finish_time = 0; } @@ -1715,7 +2067,7 @@ class InquiryService extends BaseService break; } - if ($time < 0){ + if ($time < 0) { $time = 0; } diff --git a/app/Services/MessagePush.php b/app/Services/MessagePush.php index dc36aea..f3f54eb 100644 --- a/app/Services/MessagePush.php +++ b/app/Services/MessagePush.php @@ -70,8 +70,6 @@ class MessagePush extends BaseService * 公益/专家24小时未接诊 * 站内、订阅 * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function patientNoInquiry(): void { @@ -123,7 +121,7 @@ class MessagePush extends BaseService $sub_data = array(); $sub_data['push_user_id'] = $this->user['user_id']; $sub_data['wx_template_id'] = "UOMww1S30Oq7rErJrqO8wN6lNEVKRo2fgcXnb0tBwHI";//问诊异常通知 - $sub_data['params']['page'] = "pages/orderDetail/orderDetail?order_inquiry_id={$this->order_inquiry['order_inquiry_id']}"; + $sub_data['params']['page'] = "patient/pages/orderDetail/orderDetail?order_inquiry_id={$this->order_inquiry['order_inquiry_id']}"; $sub_data['params']['data'] = [ "character_string1" => (string)$this->order_inquiry['inquiry_no'],// 订单ID "name2" => (string)$user_doctor['user_name'],// 问诊医生 @@ -151,8 +149,6 @@ class MessagePush extends BaseService * 患者-分配医生失败 * 订阅 * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function assignDoctorFail(): void { @@ -168,7 +164,7 @@ class MessagePush extends BaseService $sub_data = array(); $sub_data['push_user_id'] = $this->user['user_id']; $sub_data['wx_template_id'] = "UOMww1S30Oq7rErJrqO8wN6lNEVKRo2fgcXnb0tBwHI";//问诊异常通知 - $sub_data['params']['page'] = "pages/orderDetail/orderDetail?order_inquiry_id={$this->order_inquiry['order_inquiry_id']}"; + $sub_data['params']['page'] = "patient/pages/orderDetail/orderDetail?order_inquiry_id={$this->order_inquiry['order_inquiry_id']}"; $sub_data['params']['data'] = [ "character_string1" => (string)$this->order_inquiry['inquiry_no'],// 订单ID "name2" => $user_doctor['user_name'] ?? "接诊医生",// 问诊医生 @@ -197,8 +193,6 @@ class MessagePush extends BaseService * 订阅 * @param string $content 回复内容 * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function patientReplyNotice(string $content): bool { @@ -309,7 +303,7 @@ class MessagePush extends BaseService $sub_data = array(); $sub_data['push_user_id'] = $this->user['user_id']; $sub_data['wx_template_id'] = "9v6dZhjg09CttLd3W9nEUV_-eshNc4BYYNy59jglvZE";// 问诊提醒 - $sub_data['params']['page'] = "pages/orderDetail/orderDetail?order_inquiry_id={$this->order_inquiry['order_inquiry_id']}"; + $sub_data['params']['page'] = "patient/pages/orderDetail/orderDetail?order_inquiry_id={$this->order_inquiry['order_inquiry_id']}"; $sub_data['params']['data'] = [ "thing1" => (string)$disease_desc,// 问诊内容-病情主诉 "thing2" => "医生已接诊,请您尽快和医生沟通交流病情",// 提醒内容 @@ -399,7 +393,7 @@ class MessagePush extends BaseService $data['notice_brief_title'] = "您的【{$inquiry_type_string}】服务已结束,点击查看详情。"; $data['notice_title'] = "您的【{$inquiry_type_string}】服务已结束,点击查看详情。"; $data['notice_content'] = "您咨询{$user_doctor['user_name']}医生的服务已结束,请对本次问诊服务做出评价。您的评价对医生和其他患者也有很重要的参考价值。您也可以点击医生头像,进入医生主页关注医生。"; - $data['link_type'] = 10;// 聊天详情页 + $data['link_type'] = 10;// 问诊订单详情 $link_params = array(); $link_params['order_inquiry_id'] = $this->order_inquiry['order_inquiry_id']; @@ -430,7 +424,7 @@ class MessagePush extends BaseService $sub_data = array(); $sub_data['push_user_id'] = $this->user['user_id']; $sub_data['wx_template_id'] = "9v6dZhjg09CttLd3W9nEUV_-eshNc4BYYNy59jglvZE"; // 问诊提醒 - $sub_data['params']['page'] = "pages/orderDetail/orderDetail?order_inquiry_id={$this->order_inquiry['order_inquiry_id']}"; + $sub_data['params']['page'] = "patient/pages/orderDetail/orderDetail?order_inquiry_id={$this->order_inquiry['order_inquiry_id']}"; $sub_data['params']['data'] = [ "thing1" => (string)$disease_desc,// 问诊内容 "thing2" => "您的问诊服务已结束,请对本次服务做出评价",// 提醒内容 @@ -456,8 +450,6 @@ class MessagePush extends BaseService * 患者-处方被药师审核通过 * 站内、短信 * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function patientPrescriptionVerifyPass(): void { @@ -533,8 +525,6 @@ class MessagePush extends BaseService * 患者-处方审核未通过 * 站内 * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function patientPrescriptionVerifyFail(): void { @@ -575,8 +565,6 @@ class MessagePush extends BaseService * 站内 * @param string $coupon_name * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function patientDistributeCoupon(string $coupon_name): void { @@ -607,8 +595,6 @@ class MessagePush extends BaseService * 站内 * @param string $coupon_name * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function patientRefundCoupon(string $coupon_name): void { @@ -639,8 +625,6 @@ class MessagePush extends BaseService * 站内 * @param string $coupon_name * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function patientExpireCoupon(string $coupon_name): void { @@ -671,8 +655,6 @@ class MessagePush extends BaseService * 站内、订阅、短信 * @param int $cancel_reason 取消订单原因(1:医生未接诊 2:主动取消 3:无可分配医生 4:客服取消 5:支付超时) * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function refundInquirySuccess(int $cancel_reason): void { @@ -765,8 +747,6 @@ class MessagePush extends BaseService * 站内、订阅、短信 * @param string $order_product_id * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function refundProductSuccess(string $order_product_id): void { @@ -841,7 +821,7 @@ class MessagePush extends BaseService $sub_data = array(); $sub_data['push_user_id'] = $this->user['user_id']; $sub_data['wx_template_id'] = "gQO5vhPQfdnvXtK0XnGns1XqNhQpOrXTjdl-5HWWMUw";//药品订单取消通知 - $sub_data['params']['page'] = "pages/medinceOrderDetail/medinceOrderDetail?order_product_id={$order_product_id}"; + $sub_data['params']['page'] = "patient/pages/medinceOrderDetail/medinceOrderDetail?order_product_id={$order_product_id}"; $sub_data['params']['data'] = [ "character_string3" => (string)$order_product['order_product_no'],// 订单号 @@ -897,8 +877,6 @@ class MessagePush extends BaseService * @param string $status 已揽收、已发货、已签收 * @param string $order_product_id * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function logistics(string $status, string $order_product_id): void { @@ -936,8 +914,6 @@ class MessagePush extends BaseService * 订阅失败发送短信 * @param string $order_product_id * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function productDelivery(string $order_product_id): void { @@ -989,7 +965,7 @@ class MessagePush extends BaseService $sub_data = array(); $sub_data['push_user_id'] = $this->user['user_id']; $sub_data['wx_template_id'] = "YFdVxDclV1ZjhS7E4Cs0zFdshTRizERpwYdZizj_UWo"; // 药品发货通知 - $sub_data['params']['page'] = "pages/medinceOrderDetail/medinceOrderDetail?order_product_id={$order_product_id}"; + $sub_data['params']['page'] = "patient/pages/medinceOrderDetail/medinceOrderDetail?order_product_id={$order_product_id}"; $sub_data['params']['data'] = [ "character_string9" => (string)$order_product['order_product_no'],// 快递单号 "time7" => $order_product['delivery_time'],// 发货时间 @@ -1030,8 +1006,6 @@ class MessagePush extends BaseService * 订阅失败发送短信 * @param string $order_product_id * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function medicationReminder(string $order_product_id): bool { @@ -1048,8 +1022,6 @@ class MessagePush extends BaseService * 医生-医生有新问诊 * 站内、订阅失败发送短信 * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function doctorHaveNewInquiry(): void { @@ -1245,8 +1217,6 @@ class MessagePush extends BaseService * 站内 * 发送给医生 * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function finishInquiryToDoctor(): void { @@ -1293,8 +1263,6 @@ class MessagePush extends BaseService * 医生-开具的处方审核通过 * 站内、订阅失败发送短信 * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function prescriptionVerifySuccess(): void { @@ -1339,7 +1307,7 @@ class MessagePush extends BaseService $sub_data = array(); $sub_data['push_user_id'] = $this->user['user_id']; $sub_data['wx_template_id'] = "kUy70xHlr7ADo4aIHiictM4Te7MSec3E5kHsYvFQu40"; // 处方审核结果通知 - $sub_data['params']['page'] = "Pages/yishi/chufangsetup/index?status=1"; + $sub_data['params']['page'] = "user/pages/yishi/chufangsetup/index?status=1"; $sub_data['params']['data'] = [ "phrase1" => "审方通过",// 审核结果 "thing2" => "审核通过",// 原因 @@ -1378,8 +1346,6 @@ class MessagePush extends BaseService * 订阅失败发送短信 * @param string $order_prescription_id * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function prescriptionVerifyFail(string $order_prescription_id = ""): void { @@ -1397,7 +1363,7 @@ class MessagePush extends BaseService $sub_data = array(); $sub_data['push_user_id'] = $this->user['user_id']; $sub_data['wx_template_id'] = "kUy70xHlr7ADo4aIHiictM4Te7MSec3E5kHsYvFQu40"; // 处方审核结果通知 - $sub_data['params']['page'] = "Pages/yishi/chufangsetup/index?status=2"; + $sub_data['params']['page'] = "user/pages/yishi/chufangsetup/index?status=2"; $sub_data['params']['data'] = [ "phrase1" => "审方不通过",// 审核结果 "thing2" => (string)$order_prescription['pharmacist_fail_reason'],// 原因 @@ -1435,8 +1401,6 @@ class MessagePush extends BaseService * 医师身份通过 * 短信 * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function DoctorIdenAuthSuccess(): bool { @@ -1471,8 +1435,6 @@ class MessagePush extends BaseService * 医师身份未通过 * 短信 * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function DoctorIdenAuthFail(): bool { @@ -1507,8 +1469,6 @@ class MessagePush extends BaseService * 多点执业认证审核通过 * 站内、订阅发送失败发送短信 * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function doctorMultiPointSuccess(): bool { @@ -1586,8 +1546,6 @@ class MessagePush extends BaseService * 多点执业认证审核未通过 * 站内、订阅发送失败发送短信 * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function doctorMultiPointFail(): bool { @@ -1662,8 +1620,6 @@ class MessagePush extends BaseService * 医生简介审核通过-因缺少简介表,审核时间使用的是当前时间 * 站内、订阅发送失败发送短信 * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function doctorBriefSuccess(): bool { @@ -1740,8 +1696,6 @@ class MessagePush extends BaseService * 医生简介审核未通过-因缺少简介表,审核时间使用的是当前时间,驳回理由未填写 * 站内、订阅发送失败发送短信 * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function doctorBriefFail(): bool { @@ -1816,8 +1770,6 @@ class MessagePush extends BaseService * 站内、短信 * @param string $withdrawal_id * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function doctorSettlementSuccess(string $withdrawal_id) { @@ -1896,8 +1848,6 @@ class MessagePush extends BaseService * 站内、短信 * @param string $withdrawal_id * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function doctorSettlementFail(string $withdrawal_id): bool { @@ -1976,8 +1926,6 @@ class MessagePush extends BaseService * @param string $date 日期 * @param string $function 功能 * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function doctorSystemUpgrade(string $date, string $function): bool { @@ -2014,8 +1962,6 @@ class MessagePush extends BaseService * 站内 * @param string $title 协议名称 * @return bool - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function doctorAgreementUpdate(string $title): bool { @@ -2051,8 +1997,6 @@ class MessagePush extends BaseService * 医生-患者取消问诊 * 站内-订阅 * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function patientCancelInquiryToDoctor(): void { @@ -2143,8 +2087,6 @@ class MessagePush extends BaseService * 医生-超时未接诊 * 站内、订阅 * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function doctorNoInquiry(): void { @@ -2218,8 +2160,6 @@ class MessagePush extends BaseService * 订阅 * @param string $order_detection_id * @return void - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ public function patientCancelDetectionOrderSuccess(string $order_detection_id): void { @@ -2245,7 +2185,7 @@ class MessagePush extends BaseService $sub_data = array(); $sub_data['push_user_id'] = $this->user['user_id']; $sub_data['wx_template_id'] = "5aJSrO8SU5rxqdB99zzl4rMVgcOTjt5mQh56cpZI1Hg";//咨询提醒 - $sub_data['params']['page'] = "/pages/checkOrderDetail/checkOrderDetail?order_detection_id=" . $order_detection['detection_no']; + $sub_data['params']['page'] = "patient/pages/checkOrderDetail/checkOrderDetail?order_detection_id=" . $order_detection['detection_no']; $sub_data['params']['data'] = [ "thing1" => $order_detection['patient_name'],// 就诊人 "thing7" => (string)$detection_project['detection_project_name'],// 服务项目 @@ -2309,7 +2249,7 @@ class MessagePush extends BaseService $sub_data = array(); $sub_data['push_user_id'] = $this->user['user_id']; $sub_data['wx_template_id'] = "dNj3azLupP_w3j649v6lqz7je_ScqwgwFsnug6pKvyI"; // 处方审核结果通知 - $sub_data['params']['page'] = "/pages/checkOrderDetail/checkOrderDetail?order_detection_id=" . $order_detection['detection_no']; + $sub_data['params']['page'] = "patient/pages/checkOrderDetail/checkOrderDetail?order_detection_id=" . $order_detection['detection_no']; $sub_data['params']['data'] = [ "thing1" => "【" . $detection_project['detection_project_name'] . "】报告已出",// 报告名称 "time3" => date('Y年m月d日 H:i'),// 生成时间 @@ -2424,7 +2364,7 @@ class MessagePush extends BaseService /** * 患者-im消息通知 * 订阅 - * @param string $data 消息内容 + * @param string $msg * @return void */ public function patientImMessageNotice(string $msg): void @@ -2477,7 +2417,7 @@ class MessagePush extends BaseService /** * 医生-im消息通知 * 订阅 - * @param string $im_data + * @param string $msg * @return void */ public function doctorImMessageNotice(string $msg): void @@ -2537,4 +2477,113 @@ class MessagePush extends BaseService Log::getInstance("MessagePush-patientImMessageNotice")->error($e->getMessage()); } } + + /** + * 患者-赠送回合数 + * 站内、订阅失败发送短信 + * @param string $times_number + * @param string $give_expiration_time 赠送到期时间 + * @return void + */ + public function doctorGiveFreeRounds(string $times_number,string $give_expiration_time): void + { + try { + // 获取医生数据 + $params = array(); + $params['doctor_id'] = $this->order_inquiry['doctor_id']; + $user_doctor = UserDoctor::getOne($params); + if (empty($user_doctor)) { + Log::getInstance("MessagePush")->error("错误:医生数据为空"); + return; + } + + // 获取问诊订单关联病例 + $params = array(); + $params['order_inquiry_id'] = $this->order_inquiry['order_inquiry_id']; + $order_inquiry_case = OrderInquiryCase::getOne($params); + if (empty($order_inquiry_case)) { + Log::getInstance("MessagePush")->error("错误:病例数据为空"); + return; + } + + $producer = ApplicationContext::getContainer()->get(Producer::class); + + $data = array(); + $data['user_id'] = $this->user['user_id']; + $data['notice_type'] = 3; + $data['notice_system_type'] = 1; + $data['from_name'] = "肝胆小秘书"; + $data['notice_brief_title'] = "您好,{$user_doctor['user_name']}医生已赠送您{$times_number}次回复机会,请在有效期内和医生进行问诊,请查看详情。"; + $data['notice_title'] = "您好,{$user_doctor['user_name']}医生已赠送您{$times_number}次回复机会,请在有效期内和医生进行问诊,请查看详情。"; + $data['notice_content'] = "您好,{$user_doctor['user_name']}医生已赠送您{$times_number}次回复机会(过期时间:{$give_expiration_time}),请在有效期内和医生进行问诊,请查看详情。"; + $data['link_type'] = 10;// 问诊订单详情 + + $link_params = array(); + $link_params['order_inquiry_id'] = $this->order_inquiry['order_inquiry_id']; + $link_params['inquiry_type'] = $this->order_inquiry['inquiry_type']; + $link_params['doctor_user_id'] = $user_doctor['user_id']; + $link_params['patient_user_id'] = $this->order_inquiry['user_id']; + $data['link_params'] = json_encode($link_params, JSON_UNESCAPED_UNICODE);// 跳转参数 + + $data['button_type'] = 4; // 订单详情 + + $message = new SendStationMessageProducer($data); + $result = $producer->produce($message); + if (!$result) { + Log::getInstance("MessagePush")->error("错误:加入推送队列失败" . json_encode($data, JSON_UNESCAPED_UNICODE)); + } + + // 订阅 + // 问诊内容-病情主诉 + $disease_desc = $order_inquiry_case['disease_desc']; + if (!empty($disease_desc)) { + if (strlen($disease_desc) > 15) { + $disease_desc = mb_substr($disease_desc, 0, 15); + if ($disease_desc) { + $disease_desc = $disease_desc . "..."; + } + } + } + + // 赠送到期时间 + $give_expiration_time = date('Y-m-d H:i',strtotime($give_expiration_time)); + + $sub_data = array(); + $sub_data['push_user_id'] = $this->user['user_id']; + $sub_data['wx_template_id'] = "9v6dZhjg09CttLd3W9nEUV_-eshNc4BYYNy59jglvZE";// 问诊提醒 + $sub_data['params']['page'] = "patient/pages/orderDetail/orderDetail?order_inquiry_id={$this->order_inquiry['order_inquiry_id']}"; + $sub_data['params']['data'] = [ + "thing1" => (string)$disease_desc,// 问诊内容-病情主诉 + "thing2" => "医生赠送您{$times_number}次沟通机会",// 提醒内容 + "name3" => (string)$user_doctor['user_name'],// 问诊医生 + "thing4" => "有效期至{$give_expiration_time}",// 提示说明 + ]; + + // 短信 + $sms_data = array(); + $sms_data['template_code'] = "SMS_464725006"; + $sms_data['scene_desc'] = "医生赠送免费回合数"; + $sms_data['phone'] = $this->user['mobile']; + $sms_data['user_id'] = $this->user['user_id']; + + $template_param = array(); + $template_param['name'] = $user_doctor['user_name']; + $template_param['number'] = $times_number; + $template_param['time'] = $give_expiration_time; + $sms_data['template_param'] = $template_param; + + $data = array(); + $data['sub_data'] = $sub_data; + $data['sms_data'] = $sms_data; + + $message = new SendSubMessageProducer($data); + $producer = ApplicationContext::getContainer()->get(Producer::class); + $result = $producer->produce($message); + if (!$result) { + Log::getInstance("MessagePush")->error("错误:加入订阅推送队列失败" . json_encode($data, JSON_UNESCAPED_UNICODE)); + } + } catch (\Throwable $e) { + Log::getInstance("MessagePush")->error("错误:加入推送队列失败" . $e->getMessage()); + } + } } \ No newline at end of file diff --git a/app/Services/PatientDoctorService.php b/app/Services/PatientDoctorService.php index 17425fa..50b11f4 100644 --- a/app/Services/PatientDoctorService.php +++ b/app/Services/PatientDoctorService.php @@ -11,6 +11,7 @@ use App\Model\DoctorInquiryConfig as DoctorInquiryConfigModel; use App\Model\Hospital; use App\Model\OrderEvaluation; use App\Model\OrderInquiry; +use App\Model\OrderInquiryCase; use App\Model\PatientFollow; use App\Model\PatientHistoryInquiry as PatientHistoryInquiryModel; use App\Model\SystemInquiryConfig; @@ -34,7 +35,8 @@ class PatientDoctorService extends BaseService $city_id = $this->request->input('city_id'); $sort_order = $this->request->input('sort_order',1); $keyword = $this->request->input('keyword',""); - $is_search_welfare_reception = $this->request->input('is_search_welfare_reception',0); // 是否参加公益图文问诊(0:否 1:是) + $inquiry_type = $this->request->input('inquiry_type',[]); // 接诊类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药) + $inquiry_mode = $this->request->input('inquiry_mode',[]); // 接诊方式(1:图文 2:视频 3:语音 4:电话 5:会员 6:疑难会诊) $is_first_online = $this->request->input('is_first_online',0); // 是否优先在线(1:是) $page = $this->request->input('page',1); $per_page = $this->request->input('per_page',10); @@ -59,6 +61,11 @@ class PatientDoctorService extends BaseService $doctor_expertise_params['expertise_id'] = $expertise_id; } + if (!empty($inquiry_type)){ + $inquiry_type = explode(',',$inquiry_type); + $inquiry_mode = explode(',',$inquiry_mode); + } + // 固定医生查询条件 $doctor_params['status'] = 1; // 状态(0:禁用 1:正常 2:删除) @@ -66,7 +73,7 @@ class PatientDoctorService extends BaseService $doctor_params["is_bind_bank"] = 1;// 是否已绑定结算银行卡(0:否 1:是) $fields = [ - "doctor_id", + "user_doctor.doctor_id", "user_id", "user_name", "multi_point_status", @@ -84,7 +91,7 @@ class PatientDoctorService extends BaseService "be_good_at", ]; - $user_doctors = UserDoctor::getInquiryDoctorPage($keyword,$hospital_params, $doctor_params,$doctor_expertise_params,$is_search_welfare_reception,$is_first_online, $sort_order, $fields,$page,$per_page); + $user_doctors = UserDoctor::getInquiryDoctorPage($keyword,$hospital_params, $doctor_params,$doctor_expertise_params,$inquiry_type,$inquiry_mode,$is_first_online, $sort_order, $fields,$page,$per_page); if (!empty($user_doctors['data'])) { foreach ($user_doctors['data'] as &$user_doctor) { @@ -100,44 +107,16 @@ class PatientDoctorService extends BaseService } } - // 处理问诊价格 - $user_doctor['price'] = 0; - $user_doctor['free_clinic_price'] = 0; - $user_doctor['multi_point_enable'] = 0; - if (!empty($user_doctor['DoctorInquiryConfig'])) { - foreach ($user_doctor['DoctorInquiryConfig'] as $doctor_inquiry_config) { - if ($doctor_inquiry_config['inquiry_mode'] == 1) { - if ($doctor_inquiry_config['inquiry_type'] == 1 && $doctor_inquiry_config['is_enable'] == 1) { - // 专家 - $user_doctor['price'] = $doctor_inquiry_config['inquiry_price'] ?? 0; - } - if ($doctor_inquiry_config['inquiry_type'] == 3 && $doctor_inquiry_config['is_enable'] == 1) { - // 公益 - $user_doctor['free_clinic_price'] = $doctor_inquiry_config['inquiry_price']; - } - } - } - } - // 处理可处方字段 - $user_doctor['multi_point_enable'] = 0; - - $params = array(); - $params['doctor_id'] = $user_doctor["doctor_id"]; - $params['inquiry_type'] = 4; - $params['inquiry_mode'] = 1; - $params['is_enable'] = 1; - $result = DoctorInquiryConfig::getOne($params); - if (!empty($result)){ - $user_doctor['multi_point_enable'] = 1; - } + $userDoctorService = new UserDoctorService(); + $user_doctor['multi_point_enable'] = $userDoctorService->getDoctorMultiPointEnable($user_doctor["doctor_id"]); // 好评率-超过5个已结束的订单后展示 $user_doctor['praise_rate'] = floor($user_doctor['praise_rate'] * 0.05 * 100) / 100; // 响应时间-超过5个已结束的订单后展示 $user_doctor['avg_response_time'] = (float)floor($user_doctor['avg_response_time'] * 10) / 10; - // 获取医生订单数 + // $params = array(); $params['doctor_id'] = $user_doctor['doctor_id']; $params['inquiry_status'] = 6; // 已结束 @@ -155,177 +134,6 @@ class PatientDoctorService extends BaseService return success($user_doctors); } - /** - * 获取问诊医生详情 - * @return array - */ - public function getInquiryDoctorInfo(): array - { - $doctor_id = $this->request->route('doctor_id'); - - $user_info = $this->request->getAttribute("userInfo") ?? []; - - $result = array(); - $result['hospital'] = []; - $result['days'] = 0; - $result['doctor_inquiry_config'] = []; - - $fields = [ - "doctor_id", - "user_id", - "user_name", - "iden_auth_status", - "multi_point_status", - "avatar", - "doctor_title", - "department_custom_id", - "department_custom_name", - "hospital_id", - "served_patients_num", - "praise_rate", - "avg_response_time", - "number_of_fans", - "be_good_at", - "brief_introduction", - ]; - - $params = array(); - $params['doctor_id'] = $doctor_id; - $params['status'] = 1; // 状态(0:禁用 1:正常 2:删除) - $params["iden_auth_status"] = 1;// 身份认证状态(0:未认证 1:认证通过 2:审核中 3:认证失败) - $user_doctor = UserDoctor::getOne($params, $fields); - if (empty($user_doctor)) { - return fail(HttpEnumCode::HTTP_SUCCESS, "医生错误"); - } - - $result = $user_doctor->toArray(); - - $result['doctor_title_name'] = empty($user_doctor['doctor_title']) ? "" : DoctorTitleCode::getMessage($user_doctor['doctor_title']); - - $result['hospital'] = []; - $result['days'] = 0; - $result['doctor_inquiry_config'] = 0; - $result['is_online'] = 0; - - // 获取医生医院数据 - $fields = [ - 'hospital_id', - 'hospital_name', - 'hospital_level_name', - ]; - - $params = array(); - $params['hospital_id'] = $user_doctor['hospital_id']; - $hospital = Hospital::getOne($params, $fields); - if (!empty($hospital)) { - $result['hospital'] = $hospital; - } - - // 获取服务天数 - $params = array(); - $params['patient_id'] = $user_info['client_user_id']; - $params['doctor_id'] = $doctor_id; - $params['history_status'] = 1; - $patient_history_doctor = PatientHistoryInquiryModel::getOrderOne($params); - // 按照天来计算,当日为1,前一天为2 未服务过为0 - if (!empty($patient_history_doctor['created_at'])) { - $result['days'] = ceil((strtotime(date('Y-m-d', strtotime('+1 day'))) - strtotime($patient_history_doctor['created_at'])) / 86400); - } - - // 获取关注状态 - $params = array(); - $params['patient_id'] = $user_info['client_user_id']; - $params['doctor_id'] = $doctor_id; - $result['follow'] = PatientFollow::getExists($params); - - // 获取医生问诊配置-问诊购药 - $result['multi_point_enable'] = 0; - - // 获取问诊价格 - // 专家-公益 - $params = array(); - $params[] = ['doctor_id', '=', $doctor_id]; - $params[] = ['inquiry_mode', '=', 1];// 接诊方式(1:图文 2:视频 3:语音 4:电话 5:会员) - $doctor_inquiry_config = DoctorInquiryConfigModel::getInquiryConfigListByInquiryType($params,['*'],[1,3,4]); - if (!empty($doctor_inquiry_config)) { - foreach ($doctor_inquiry_config as &$value) { - // 获取医生当日的全部订单 - $params = array(); - $params[] = ['doctor_id', '=', $doctor_id]; - $params[] = ['inquiry_type', '=', $value['inquiry_type']]; - $params[] = ['inquiry_mode', '=', 1]; - $params[] = ['inquiry_refund_status', '=', 0]; - - // 获取当天开始时间 - $start_date = date('Y-m-d 00:00:00', time()); - - // 获取当天结束时间 - $end_date = date('Y-m-d 23:59:59', time()); - - $created_at = [$start_date, $end_date]; - - $value['order_inquiry_count'] = OrderInquiry::getDateCount($params,$created_at); - - // 获取系统问诊配置 - $fields = [ - 'system_inquiry_config_id', - 'times_number', - 'duration', - ]; - - $params = array(); - $params['inquiry_type'] = $value['inquiry_type']; - $params['inquiry_mode'] = $value['inquiry_mode']; - $system_inquiry_config = SystemInquiryConfig::getOne($params,$fields); - if (empty($system_inquiry_config)){ - return fail(); - } - - $value['times_number'] = $system_inquiry_config['times_number']; - $value['duration'] = $system_inquiry_config['duration']; - - if ($value['is_enable'] == 1 && $value['inquiry_type'] == 4 && $value['inquiry_mode'] == 1){ - $result['multi_point_enable'] = 1; - } - unset($system_inquiry_config); - } - $result['doctor_inquiry_config'] = $doctor_inquiry_config; - } - - // 获取医生已选择专长 - $UserDoctorService = new UserDoctorService(); - $result['doctor_expertise'] = $UserDoctorService->getDoctorSelectedExpertise($user_doctor['doctor_id']); - - // 好评率-超过5个已结束的订单后展示 - $result['praise_rate'] = floor($user_doctor['praise_rate'] * 0.05 * 100) / 100; - - // 响应时间-超过5个已结束的订单后展示 - $result['avg_response_time'] = floor($user_doctor['avg_response_time'] * 10) / 10; - - $params = array(); - $params['doctor_id'] = $user_doctor['doctor_id']; - $params['inquiry_status'] = 6; // 已结束 - $inquiry_order_count = OrderInquiry::getCount($params); - if (empty($inquiry_order_count) || $inquiry_order_count == 0) { - $result['is_display_score'] = false; - } else { - $result['is_display_score'] = true; - } - - // 头像 - $result['avatar'] = addAliyunOssWebsite($user_doctor['avatar']); - - // 获取用户数据 - $params = array(); - $params['user_id'] = $user_doctor['user_id']; - $user = User::getOne($params); - if (!empty($user)){ - $result['is_online'] = $user['is_online']; - } - - return success($result); - } - /** * 医生详情简介-详情中的简介 * @return array @@ -404,7 +212,7 @@ class PatientDoctorService extends BaseService try { // 检测是否存在同类型未完成的问诊订单 $PatientOrderService = new PatientOrderService(); - $order_inquiry_id = $PatientOrderService->getNotFinishedOrderInquiry($inquiry_type,$user_info['client_user_id']); + $order_inquiry_id = $PatientOrderService->getNotFinishedOrderInquiry($inquiry_type,$inquiry_mode,$user_info['client_user_id']); if (!empty($order_inquiry_id)){ $result['status'] = 2; $result['data']['order_inquiry_id'] = $order_inquiry_id; @@ -445,7 +253,7 @@ class PatientDoctorService extends BaseService $params = array(); $params['doctor_id'] = $user_doctor['doctor_id']; $params['inquiry_type'] = $inquiry_type; - $params['inquiry_mode'] = 1; + $params['inquiry_mode'] = $inquiry_mode; $doctor_inquiry_config = DoctorInquiryConfig::getOne($params); if (empty($doctor_inquiry_config)){ return fail(HttpEnumCode::HTTP_ERROR,"医生暂不可接诊"); @@ -634,6 +442,7 @@ class PatientDoctorService extends BaseService return success(); } + $userDoctorService = new UserDoctorService(); foreach ($recommend_doctors as $recommend_doctor) { $data = array(); $data['doctor_id'] = $recommend_doctor['doctor_id']; @@ -647,32 +456,13 @@ class PatientDoctorService extends BaseService $data['be_good_at'] = $recommend_doctor['be_good_at']; $data['hospital_name'] = $recommend_doctor['Hospital']['hospital_name'] ?? ""; $data['hospital_level_name'] = $recommend_doctor['Hospital']['hospital_level_name'] ?? ""; - $data['multi_point_enable'] = 0; // 是否开启问诊购药 if (!empty($recommend_doctor['user'])){ $data['is_online'] = $recommend_doctor['user']['is_online']; } - // 处理接诊价格 - $data['price'] = 0; - $data['free_clinic_price'] = 0; - foreach ($recommend_doctor['DoctorInquiryConfig'] as $doctor_inquiry_config) { - if ($doctor_inquiry_config['inquiry_mode'] == 1){ - if ($doctor_inquiry_config['inquiry_type'] == 1) { - // 专家问诊 - $data['price'] = $doctor_inquiry_config['inquiry_price']; - } - - if ($doctor_inquiry_config['inquiry_type'] == 3) { - // 公益 - $data['free_clinic_price'] = $doctor_inquiry_config['inquiry_price']; - } - - if ($doctor_inquiry_config['inquiry_type'] == 4 && $doctor_inquiry_config['is_enable'] == 1) { - $data['multi_point_enable'] = 1; // 是否开启问诊购药 - } - } - } + // 是否开启问诊购药 + $data['multi_point_enable'] = $userDoctorService->getDoctorMultiPointEnable("",$recommend_doctor['DoctorInquiryConfig']); $data['doctor_inquiry_config'] = $recommend_doctor['DoctorInquiryConfig']; @@ -705,6 +495,19 @@ class PatientDoctorService extends BaseService $item['service_attitude'] = floor($item['service_attitude'] * 0.05); $item['reply_progress'] = floor($item['reply_progress'] * 0.05); $item['avg_score'] = floor($item['avg_score'] * 0.05); + + $item['inquiry_type'] = $item['OrderInquiry']['inquiry_type']; + $item['inquiry_mode'] = $item['OrderInquiry']['inquiry_mode']; + + // 获取问诊病例 + $params = array(); + $params['order_inquiry_id'] = $item['OrderInquiry']['order_inquiry_id']; + $order_inquiry_case = OrderInquiryCase::getOne($params); + if (!empty($order_inquiry_case)){ + $item['disease_class_name'] = $order_inquiry_case['disease_class_name']; + } + + unset($item['OrderInquiry']); } } return success($order_evaluation); diff --git a/app/Services/PatientFamilyService.php b/app/Services/PatientFamilyService.php index 4d06ae9..9c4dba6 100644 --- a/app/Services/PatientFamilyService.php +++ b/app/Services/PatientFamilyService.php @@ -7,6 +7,7 @@ use App\Model\BasicJob; use App\Model\BasicNation; use App\Model\DiseaseClass; use App\Model\OrderProduct; +use App\Model\PatientFamily; use App\Model\PatientFamily as PatientFamilyModel; use App\Model\PatientFamilyHealth; use App\Model\PatientFamilyPersonal as PatientFamilyPersonalModel; @@ -45,10 +46,33 @@ class PatientFamilyService extends BaseService 'age', 'nation_id', 'nation_name', + 'id_number', ]; $patient_familys = PatientFamilyModel::getList($params, $field); + if (empty($patient_familys)){ + return success(); + } - return empty($patient_familys) ? success() : success($patient_familys->toArray()); + $patient_familys = $patient_familys->toArray(); + foreach ($patient_familys as &$value){ + // 计算年龄 + $age = getIdCardAge($value['id_number']); + unset($value['id_number']); + + // 修正年龄 + if ($value['age'] != $age){ + $params = array(); + $params['family_id'] = $value['family_id']; + + $data = array(); + $data['age'] = $age; + PatientFamily::edit($params,$data); + + $value['age'] = $age; + } + } + + return success($patient_familys); } /** @@ -316,13 +340,17 @@ class PatientFamilyService extends BaseService return success(); } - return success($patient_family->toArray()); + $patient_family = $patient_family->toArray(); + + // 计算年龄 + $patient_family['age'] = getIdCardAge($patient_family['id_number']); + + return success($patient_family); } /** * 修改家庭成员 * @return array - * @throws GuzzleException */ public function editFamily(): array { diff --git a/app/Services/PatientOrderService.php b/app/Services/PatientOrderService.php index ca0078f..e827b85 100644 --- a/app/Services/PatientOrderService.php +++ b/app/Services/PatientOrderService.php @@ -15,6 +15,7 @@ use App\Model\OrderDetection; use App\Model\OrderInquiry; use App\Model\OrderInquiryCase; use App\Model\OrderInquiryCoupon; +use App\Model\OrderInquiryRefund; use App\Model\OrderPrescription; use App\Model\OrderPrescriptionFile; use App\Model\OrderPrescriptionProduct; @@ -276,6 +277,16 @@ class PatientOrderService extends BaseService unset($user_doctor); } + // 获取退款数据 + $order_inquiry['order_inquiry_refund'] = array(); + + $params = array(); + $params['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $order_inquiry_refund = OrderInquiryRefund::getList($params); + if (!empty($order_inquiry_refund)){ + $order_inquiry['order_inquiry_refund'] = $order_inquiry_refund; + } + return success($order_inquiry->toArray()); } @@ -304,13 +315,14 @@ class PatientOrderService extends BaseService $redis = $this->container->get(Redis::class); $redis_key = "order_inquiry_lock_" . $order_inquiry_id; $redis_lock = $redis->setnx($redis_key, 1); - // 设置过期时间 - $redis->expire($redis_key, 3); if (!$redis_lock) { // 设置失败,表示已经设置该值 return fail(HttpEnumCode::HTTP_SUCCESS, "请您稍后重试"); } + // 设置过期时间 + $redis->expire($redis_key, 3); + // 检测订单状态 if (!in_array($order_inquiry['inquiry_status'], [1, 2, 3])) { // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) @@ -706,6 +718,7 @@ class PatientOrderService extends BaseService $result['order_id'] = ""; // 订单主键id(问诊订单:order_inquiry_id 药品订单:order_product_id) $result['created_at'] = ""; // 创建时间 $result['inquiry_type'] = 0; // 订单类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药 5:检测) + $result['inquiry_mode'] = 0; // 接诊方式(1:图文 2:视频 3:语音 4:电话 5:会员 6:疑难会诊) $result['pay_config'] = []; // 小程序支付配置 $result['cannot_use_coupon_reason'] = ""; // 不可使用优惠卷原因 @@ -753,6 +766,7 @@ class PatientOrderService extends BaseService $result['order_id'] = $order_inquiry['order_inquiry_id']; $result['created_at'] = $order_inquiry['created_at']; $result['inquiry_type'] = $order_inquiry['inquiry_type']; + $result['inquiry_mode'] = $order_inquiry['inquiry_mode']; // 获取订单金额 $result['amount_total'] = $order_inquiry['amount_total']; // 订单金额 @@ -1155,6 +1169,7 @@ class PatientOrderService extends BaseService return fail(HttpEnumCode::HTTP_ERROR, "处方存在未知药品"); } + // 检测商品状态 // 检测商品库存 if (!empty($product['ProductPlatformAmount'])) { if ($order_prescription_product['prescription_product_num'] > $product['ProductPlatformAmount']['stock']) { @@ -2105,10 +2120,11 @@ class PatientOrderService extends BaseService * 获取患者未完成订单 * @param string $patient_id * @param string|int $inquiry_type + * @param string|int $inquiry_mode * @param string $family_id * @return string */ - public function getNotFinishedOrderInquiry(string|int $inquiry_type, string $patient_id = '', string $family_id = ''): string + public function getNotFinishedOrderInquiry(string|int $inquiry_type,string|int $inquiry_mode, string $patient_id = '', string $family_id = ''): string { $params = array(); if (!empty($patient_id)) { @@ -2120,7 +2136,7 @@ class PatientOrderService extends BaseService } $params[] = ['inquiry_type', '=', $inquiry_type]; - $params[] = ['inquiry_mode', '=', 1]; + $params[] = ['inquiry_mode', '=', $inquiry_mode]; $params[] = ['inquiry_refund_status', '=', 0]; $order_inquiry = OrderInquiry::getOrderOne($params); if (!empty($order_inquiry)) { diff --git a/app/Services/SafeService.php b/app/Services/SafeService.php index bb7c976..17dfc71 100644 --- a/app/Services/SafeService.php +++ b/app/Services/SafeService.php @@ -10,7 +10,8 @@ use App\Model\UserPatient; use App\Model\UserPharmacist; use Extend\Alibaba\Oss; use Extend\TencentIm\Account; -use Extend\TencentIm\Safe; +use Extend\TencentIm\Safe as ImSafe; +use Extend\TencentVideo\Safe as VideoSafe; /** * 安全服务 @@ -99,7 +100,36 @@ class SafeService extends BaseService return success(); } - $safe = new Safe(); + $safe = new ImSafe(); + $sign = $safe->getUserSign($user['user_id']); + if (empty($sign)){ + return success(); + } + + return success($sign); + } + + /** + * 获取音视频签名数据 + * @return array + */ + public function getVideoSign(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + + if (empty($user_info)){ + return success(); + } + + // 验证用户数据 + $params = array(); + $params['user_id'] = $user_info['user_id']; + $user = User::getOne($params); + if (empty($user)){ + return success(); + } + + $safe = new VideoSafe(); $sign = $safe->getUserSign($user['user_id']); if (empty($sign)){ return success(); diff --git a/app/Services/SendSmsService.php b/app/Services/SendSmsService.php new file mode 100644 index 0000000..2d8e1af --- /dev/null +++ b/app/Services/SendSmsService.php @@ -0,0 +1,72 @@ +mobile = $mobile; + } + } + + // 患者-通知患者视频时间 + public function noticePatientVideoTime(string $doctor_name,$reservation_time){ + try { + // 发送短信-患者-视频预约成功 + $template_code = "SMS_464481352"; + $scene_desc = "通知患者视频时间"; + + $template_param = array(); + $template_param['name'] = $doctor_name; + $template_param['time'] = date('Y-m-d H:i', strtotime($reservation_time)); + + Dysms::sendSms($this->mobile,$template_param,$template_code,$scene_desc); + }catch (\Throwable $e){ + throw new BusinessException("短信发送失败",HttpEnumCode::CODE_FAIL); + } + } + + // 患者-通知患者视频 + public function noticePatientVideo(string $doctor_name){ + try { + // 发送短信-患者-视频预约成功 + $template_code = "SMS_464436348"; + $scene_desc = "通知患者视频"; + + $template_param = array(); + $template_param['name'] = $doctor_name; + + Dysms::sendSms($this->mobile,$template_param,$template_code,$scene_desc); + }catch (\Throwable $e){ + throw new BusinessException("短信发送失败",HttpEnumCode::CODE_FAIL); + } + } + + // 医生-通知医生视频 + public function noticeDoctorVideo(string $patient_name){ + try { + // 发送短信-患者-视频预约成功 + $template_code = "SMS_464486306"; + $scene_desc = "通知医生视频"; + + $template_param = array(); + $template_param['name'] = $patient_name; + + Dysms::sendSms($this->mobile,$template_param,$template_code,$scene_desc); + }catch (\Throwable $e){ + throw new BusinessException("短信发送失败",HttpEnumCode::CODE_FAIL); + } + } +} \ No newline at end of file diff --git a/app/Services/UserDoctorService.php b/app/Services/UserDoctorService.php index 2367f48..40b19a7 100644 --- a/app/Services/UserDoctorService.php +++ b/app/Services/UserDoctorService.php @@ -17,6 +17,8 @@ use App\Model\DoctorAccount; use App\Model\DoctorBankCard; use App\Model\DoctorExpertise; use App\Model\DoctorInquiryConfig; +use App\Model\DoctorInquiryConfig as DoctorInquiryConfigModel; +use App\Model\DoctorInquiryConfigService; use App\Model\DoctorInquiryTime; use App\Model\DoctorWord; use App\Model\Hospital; @@ -29,7 +31,9 @@ use App\Model\OrderPrescriptionFile; use App\Model\OrderPrescriptionIcd; use App\Model\OrderPrescriptionProduct; use App\Model\OrderProductItem; +use App\Model\PatientFollow; use App\Model\PatientHistoryInquiry; +use App\Model\PatientHistoryInquiry as PatientHistoryInquiryModel; use App\Model\Popup; use App\Model\Product; use App\Model\ProductPlatformAmount; @@ -741,9 +745,6 @@ class UserDoctorService extends BaseService return fail(); } - $params = array(); - $params['doctor_id'] = $doctor_id; - // 4-5分为好评、3分为中评、2-1分为差评 if ($evaluation_type == 1) { // 全部 @@ -758,10 +759,24 @@ class UserDoctorService extends BaseService return fail(); } + $params = array(); + $params['doctor_id'] = $doctor_id; $order_evaluation = OrderEvaluation::getScorePage($params, $avg_score_params,['*'],$page,$per_page); if (!empty($order_evaluation['data'])) { foreach ($order_evaluation['data'] as &$item) { $item['avg_score'] = floor($item['avg_score'] * 0.05); + $item['inquiry_type'] = $item['OrderInquiry']['inquiry_type']; + $item['inquiry_mode'] = $item['OrderInquiry']['inquiry_mode']; + + // 获取问诊病例 + $params = array(); + $params['order_inquiry_id'] = $item['OrderInquiry']['order_inquiry_id']; + $order_inquiry_case = OrderInquiryCase::getOne($params); + if (!empty($order_inquiry_case)){ + $item['disease_class_name'] = $order_inquiry_case['disease_class_name']; + } + + unset($item['OrderInquiry']); } } @@ -769,20 +784,32 @@ class UserDoctorService extends BaseService if ($evaluation_type == 1) { // 好评 $avg_score_params = [80, 100]; + + $params = array(); + $params['doctor_id'] = $doctor_id; $good_quantity = OrderEvaluation::getScoreCount($params, $avg_score_params); // 中/差评 $avg_score_params = [0, 79]; + + $params = array(); + $params['doctor_id'] = $doctor_id; $bad_quantity = OrderEvaluation::getScoreCount($params, $avg_score_params); } if ($evaluation_type == 2) { // 全部+ $avg_score_params = [0, 100]; + + $params = array(); + $params['doctor_id'] = $doctor_id; $total_quantity = OrderEvaluation::getScoreCount($params, $avg_score_params); // 中/差评 $avg_score_params = [0, 79]; + + $params = array(); + $params['doctor_id'] = $doctor_id; $bad_quantity = OrderEvaluation::getScoreCount($params, $avg_score_params); } @@ -790,10 +817,16 @@ class UserDoctorService extends BaseService if ($evaluation_type == 3) { // 全部+ $avg_score_params = [0, 100]; + + $params = array(); + $params['doctor_id'] = $doctor_id; $total_quantity = OrderEvaluation::getScoreCount($params, $avg_score_params); // 好评 $avg_score_params = [80, 100]; + + $params = array(); + $params['doctor_id'] = $doctor_id; $good_quantity = OrderEvaluation::getScoreCount($params, $avg_score_params); } @@ -1765,7 +1798,8 @@ class UserDoctorService extends BaseService /** * 新增医生接诊 * @return array - * @throws GuzzleException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function addDoctorInquiry(): array { @@ -1782,16 +1816,41 @@ class UserDoctorService extends BaseService return fail(HttpEnumCode::HTTP_ERROR, "接诊失败"); } - $redis = $this->container->get(Redis::class); - $redis_key = "order_inquiry_lock_" . $order_inquiry_id; - $redis_lock = $redis->setnx($redis_key,1); - // 设置过期时间 - $redis->expire($redis_key,3); - if (!$redis_lock){ - // 设置失败,表示已经设置该值 + try { + $redis = $this->container->get(Redis::class); + $redis_key = "order_inquiry_lock_" . $order_inquiry_id; + $redis_lock = $redis->setnx($redis_key,1); + if (!$redis_lock){ + // 设置失败,表示已经设置该值 + return fail(HttpEnumCode::HTTP_SUCCESS,"请您稍后重试"); + } + + // 设置过期时间 + $redis->expire($redis_key,3); + }catch (\Throwable $e){ return fail(HttpEnumCode::HTTP_SUCCESS,"请您稍后重试"); } + if ($order_inquiry['inquiry_status'] == 4) { + // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + return success(); + } + + if ($order_inquiry['inquiry_status'] == 5) { + // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + return fail(HttpEnumCode::HTTP_ERROR, "订单已完成"); + } + + if ($order_inquiry['inquiry_status'] == 6) { + // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + return fail(HttpEnumCode::HTTP_ERROR, "订单已结束"); + } + + if ($order_inquiry['inquiry_status'] == 7) { + // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + return fail(HttpEnumCode::HTTP_ERROR, "订单已取消"); + } + if ($order_inquiry['inquiry_status'] != 3) { // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) return fail(HttpEnumCode::HTTP_ERROR, "接诊失败"); @@ -1808,6 +1867,15 @@ class UserDoctorService extends BaseService return fail(HttpEnumCode::HTTP_ERROR, "订单未支付,无法接诊"); } + // 获取系统问诊配置 + $params = array(); + $params['inquiry_type'] = $order_inquiry['inquiry_type']; + $params['inquiry_mode'] = $order_inquiry['inquiry_mode']; + $system_inquiry_config = SystemInquiryConfig::getOne($params); + if (empty($system_inquiry_config)){ + return fail(HttpEnumCode::HTTP_ERROR, "接诊失败"); + } + Db::beginTransaction(); try { @@ -1819,23 +1887,32 @@ class UserDoctorService extends BaseService $params['order_inquiry_id'] = $order_inquiry_id; OrderInquiry::edit($params,$data); - // 添加自动结束队列 - if ($order_inquiry['inquiry_type'] == 1 || $order_inquiry['inquiry_type'] == 3){ - // 专家问诊-公益问诊 - $time = 1000 * 60 * 60 * 24; - }elseif($order_inquiry['inquiry_type'] == 2){ - // 快速问诊 - $time = 1000 * 60 * 60; + /** + * 获取订单结束周期 + * 疑难问诊为自己配置周期。 + */ + // 疑难问诊 + if ($order_inquiry['inquiry_type'] == 1 && $order_inquiry['inquiry_mode'] == 6){ + $params = array(); + $params['doctor_id'] = $order_inquiry['doctor_id']; + $params['inquiry_type'] = $order_inquiry['inquiry_type']; + $params['inquiry_mode'] = $order_inquiry['inquiry_mode']; + $doctor_inquiry_config_service = DoctorInquiryConfigService::getOne($params); + if(empty($doctor_inquiry_config_service)){ + Db::rollBack(); + return fail(HttpEnumCode::HTTP_ERROR, "接诊失败"); + } + + $time = $doctor_inquiry_config_service['service_period'] * 24 * 60 * 60; }else{ - // 购药 - $time = 1000 * 60 * 30; + $time = $system_inquiry_config['duration'] * 60; } + // 添加自动结束队列 $data = array(); $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; - $message = new AutoCompleteInquiryDelayDirectProducer($data); - $message->setDelayMs($time); + $message->setDelayMs(1000 * $time); $producer = $this->container->get(Producer::class); $res = $producer->produce($message); if (!$res) { @@ -1870,7 +1947,7 @@ class UserDoctorService extends BaseService // 发送IM消息-医生接诊 $imService = new ImService(); - $imService->doctorInquiry($order_inquiry,$user_info['user_id'],$order_inquiry['user_id']); + $imService->doctorInquiry($order_inquiry,$user_info['user_id'],$order_inquiry['user_id'],$time); // 发送IM消息-患者病例 $imService->patientCase($order_inquiry,$user_doctor['user_id'],$order_inquiry_case['disease_desc']); @@ -1885,6 +1962,413 @@ class UserDoctorService extends BaseService return success(); } + /** + * 获取医生问诊详情 + * @return array + */ + public function getDoctorInquiryInfo(): array + { + $doctor_id = $this->request->route('doctor_id'); + + $user_info = $this->request->getAttribute("userInfo") ?? []; + + if (empty($user_info)){ + return fail(HttpEnumCode::HTTP_SUCCESS, "请登录"); + } + + $result = array(); + $result['hospital'] = []; + $result['days'] = 0; + $result['doctor_inquiry_config'] = []; + $result['is_online'] = 0; + + $fields = [ + "doctor_id", + "user_id", + "user_name", + "iden_auth_status", + "multi_point_status", + "avatar", + "doctor_title", + "department_custom_id", + "department_custom_name", + "hospital_id", + "served_patients_num", + "praise_rate", + "avg_response_time", + "number_of_fans", + "be_good_at", + "brief_introduction", + ]; + + $params = array(); + $params['doctor_id'] = $doctor_id; + $params['status'] = 1; // 状态(0:禁用 1:正常 2:删除) + $params["iden_auth_status"] = 1;// 身份认证状态(0:未认证 1:认证通过 2:审核中 3:认证失败) + $user_doctor = UserDoctor::getOne($params, $fields); + if (empty($user_doctor)) { + return fail(HttpEnumCode::HTTP_SUCCESS, "医生错误"); + } + + $result = $user_doctor->toArray(); + + $result['doctor_title_name'] = empty($user_doctor['doctor_title']) ? "" : DoctorTitleCode::getMessage($user_doctor['doctor_title']); + + // 获取医生医院数据 + $fields = [ + 'hospital_id', + 'hospital_name', + 'hospital_level_name', + ]; + + $params = array(); + $params['hospital_id'] = $user_doctor['hospital_id']; + $hospital = Hospital::getOne($params, $fields); + if (!empty($hospital)) { + $result['hospital'] = $hospital; + } + + // 患者 + if ($user_info['user_type'] == 1){ + // 获取服务天数 + $params = array(); + $params['patient_id'] = $user_info['client_user_id']; + $params['doctor_id'] = $doctor_id; + $params['history_status'] = 1; + $patient_history_doctor = PatientHistoryInquiryModel::getOrderOne($params); + // 按照天来计算,当日为1,前一天为2 未服务过为0 + if (!empty($patient_history_doctor['created_at'])) { + $result['days'] = ceil((strtotime(date('Y-m-d', strtotime('+1 day'))) - strtotime($patient_history_doctor['created_at'])) / 86400); + } + + // 获取关注状态 + $params = array(); + $params['patient_id'] = $user_info['client_user_id']; + $params['doctor_id'] = $doctor_id; + $result['follow'] = PatientFollow::getExists($params); + } + + // 获取医生问诊配置-问诊购药 + $result['multi_point_enable'] = 0; + + // 获取问诊价格 + // 专家-公益 + $params = array(); + $params[] = ['doctor_id', '=', $doctor_id]; + $params[] = ['inquiry_mode', '=', 1];// 接诊方式(1:图文 2:视频 3:语音 4:电话 5:会员) + $doctor_inquiry_config = DoctorInquiryConfigModel::getInquiryConfigListByInquiryType($params,['*'],[1,3,4]); + if (!empty($doctor_inquiry_config)) { + foreach ($doctor_inquiry_config as &$value) { + // 获取医生当日的全部订单 + $params = array(); + $params[] = ['doctor_id', '=', $doctor_id]; + $params[] = ['inquiry_type', '=', $value['inquiry_type']]; + $params[] = ['inquiry_mode', '=', 1]; + $params[] = ['inquiry_refund_status', '=', 0]; + + // 获取当天开始时间 + $start_date = date('Y-m-d 00:00:00', time()); + + // 获取当天结束时间 + $end_date = date('Y-m-d 23:59:59', time()); + + $created_at = [$start_date, $end_date]; + + $value['order_inquiry_count'] = OrderInquiry::getDateCount($params,$created_at); + + // 获取系统问诊配置 + $fields = [ + 'system_inquiry_config_id', + 'times_number', + 'duration', + ]; + + $params = array(); + $params['inquiry_type'] = $value['inquiry_type']; + $params['inquiry_mode'] = $value['inquiry_mode']; + $system_inquiry_config = SystemInquiryConfig::getOne($params,$fields); + if (empty($system_inquiry_config)){ + return fail(); + } + + $value['times_number'] = $system_inquiry_config['times_number']; + $value['duration'] = $system_inquiry_config['duration']; + + if ($value['is_enable'] == 1 && $value['inquiry_type'] == 4 && $value['inquiry_mode'] == 1){ + $result['multi_point_enable'] = 1; + } + unset($system_inquiry_config); + } + $result['doctor_inquiry_config'] = $doctor_inquiry_config; + } + + // 获取医生已选择专长 + $UserDoctorService = new UserDoctorService(); + $result['doctor_expertise'] = $UserDoctorService->getDoctorSelectedExpertise($user_doctor['doctor_id']); + + // 好评率-超过5个已结束的订单后展示 + $result['praise_rate'] = floor($user_doctor['praise_rate'] * 0.05 * 100) / 100; + + // 响应时间-超过5个已结束的订单后展示 + $result['avg_response_time'] = floor($user_doctor['avg_response_time'] * 10) / 10; + + $params = array(); + $params['doctor_id'] = $user_doctor['doctor_id']; + $params['inquiry_status'] = 6; // 已结束 + $inquiry_order_count = OrderInquiry::getCount($params); + if (empty($inquiry_order_count) || $inquiry_order_count == 0) { + $result['is_display_score'] = false; + } else { + $result['is_display_score'] = true; + } + + // 头像 + $result['avatar'] = addAliyunOssWebsite($user_doctor['avatar']); + + // 获取用户数据 + $params = array(); + $params['user_id'] = $user_doctor['user_id']; + $user = User::getOne($params); + if (!empty($user)){ + $result['is_online'] = $user['is_online']; + } + + return success($result); + } + + /** + * 获取医生详情-问诊 + * @return array + */ + public function getDoctorInfoInquiry(): array + { + $doctor_id = $this->request->route('doctor_id'); + + $user_info = $this->request->getAttribute("userInfo") ?? []; + + if (empty($user_info)){ + return fail(HttpEnumCode::HTTP_SUCCESS, "请登录"); + } + + $result = array(); + $result['hospital'] = []; + $result['days'] = 0; + $result['doctor_inquiry_config'] = []; + $result['is_online'] = 0; + + $fields = [ + "doctor_id", + "user_id", + "user_name", + "iden_auth_status", + "multi_point_status", + "avatar", + "doctor_title", + "department_custom_id", + "department_custom_name", + "hospital_id", + "served_patients_num", + "praise_rate", + "avg_response_time", + "number_of_fans", + "be_good_at", + "brief_introduction", + ]; + + $params = array(); + $params['doctor_id'] = $doctor_id; + $params['status'] = 1; // 状态(0:禁用 1:正常 2:删除) + $params["iden_auth_status"] = 1;// 身份认证状态(0:未认证 1:认证通过 2:审核中 3:认证失败) + $user_doctor = UserDoctor::getOne($params, $fields); + if (empty($user_doctor)) { + return fail(HttpEnumCode::HTTP_SUCCESS, "医生错误"); + } + + $result = $user_doctor->toArray(); + + $result['doctor_title_name'] = empty($user_doctor['doctor_title']) ? "" : DoctorTitleCode::getMessage($user_doctor['doctor_title']); + + // 获取医生医院数据 + $fields = [ + 'hospital_id', + 'hospital_name', + 'hospital_level_name', + ]; + + $params = array(); + $params['hospital_id'] = $user_doctor['hospital_id']; + $hospital = Hospital::getOne($params, $fields); + if (!empty($hospital)) { + $result['hospital'] = $hospital; + } + + // 患者 + if ($user_info['user_type'] == 1){ + // 获取服务天数 + $params = array(); + $params['patient_id'] = $user_info['client_user_id']; + $params['doctor_id'] = $doctor_id; + $params['history_status'] = 1; + $patient_history_doctor = PatientHistoryInquiryModel::getOrderOne($params); + // 按照天来计算,当日为1,前一天为2 未服务过为0 + if (!empty($patient_history_doctor['created_at'])) { + $result['days'] = ceil((strtotime(date('Y-m-d', strtotime('+1 day'))) - strtotime($patient_history_doctor['created_at'])) / 86400); + } + + // 获取关注状态 + $params = array(); + $params['patient_id'] = $user_info['client_user_id']; + $params['doctor_id'] = $doctor_id; + $result['follow'] = PatientFollow::getExists($params); + } + + // 获取医生已选择专长 + $UserDoctorService = new UserDoctorService(); + $result['doctor_expertise'] = $UserDoctorService->getDoctorSelectedExpertise($user_doctor['doctor_id']); + + // 好评率-超过5个已结束的订单后展示 + $result['praise_rate'] = floor($user_doctor['praise_rate'] * 0.05 * 100) / 100; + + // 响应时间-超过5个已结束的订单后展示 + $result['avg_response_time'] = floor($user_doctor['avg_response_time'] * 10) / 10; + + $params = array(); + $params['doctor_id'] = $user_doctor['doctor_id']; + $params['inquiry_status'] = 6; // 已结束 + $inquiry_order_count = OrderInquiry::getCount($params); + if (empty($inquiry_order_count) || $inquiry_order_count == 0) { + $result['is_display_score'] = false; + } else { + $result['is_display_score'] = true; + } + + // 头像 + $result['avatar'] = addAliyunOssWebsite($user_doctor['avatar']); + + // 获取用户数据 + $params = array(); + $params['user_id'] = $user_doctor['user_id']; + $user = User::getOne($params); + if (!empty($user)){ + $result['is_online'] = $user['is_online']; + } + + // 处理可处方字段 + $userDoctorService = new UserDoctorService(); + $result['multi_point_enable'] = $userDoctorService->getDoctorMultiPointEnable($doctor_id); + + return success($result); + } + + /** + * 获取医生开启的服务 + * @return array + */ + public function getDoctorOpenInquiryService(): array + { + $doctor_id = $this->request->route('doctor_id'); + + $user_info = $this->request->getAttribute("userInfo") ?? []; + + if (empty($user_info)){ + return fail(HttpEnumCode::HTTP_SUCCESS, "请登录"); + } + + $fields = [ + "doctor_id", + "user_id", + "user_name", + "iden_auth_status", + "multi_point_status", + "avatar", + "doctor_title", + "department_custom_id", + "department_custom_name", + "hospital_id", + "served_patients_num", + "praise_rate", + "avg_response_time", + "number_of_fans", + "be_good_at", + "brief_introduction", + ]; + + $params = array(); + $params['doctor_id'] = $doctor_id; + $params['status'] = 1; // 状态(0:禁用 1:正常 2:删除) + $params["iden_auth_status"] = 1;// 身份认证状态(0:未认证 1:认证通过 2:审核中 3:认证失败) + $user_doctor = UserDoctor::getOne($params, $fields); + if (empty($user_doctor)) { + return fail(HttpEnumCode::HTTP_SUCCESS, "医生错误"); + } + + // 获取问诊配置 + $params = array(); + $params[] = ['doctor_id', '=', $doctor_id]; + $doctor_inquiry_config = DoctorInquiryConfigModel::getInquiryConfigListByInquiryType($params,['*'],[1,3,4]); + if (!empty($doctor_inquiry_config)) { + foreach ($doctor_inquiry_config as &$value) { + // 获取医生当日的全部订单 + $params = array(); + $params[] = ['doctor_id', '=', $doctor_id]; + $params[] = ['inquiry_type', '=', $value['inquiry_type']]; + $params[] = ['inquiry_mode', '=', 1]; + $params[] = ['inquiry_refund_status', '=', 0]; + + // 获取当天开始时间 + $start_date = date('Y-m-d 00:00:00', time()); + + // 获取当天结束时间 + $end_date = date('Y-m-d 23:59:59', time()); + + $created_at = [$start_date, $end_date]; + + $value['order_inquiry_count'] = OrderInquiry::getDateCount($params,$created_at); + + // 获取回合数以及问诊时间 + if ($value['inquiry_mode'] == 6){ + $params = array(); + $params['doctor_id'] = $doctor_id; + $params['inquiry_type'] = $value['inquiry_type']; + $params['inquiry_mode'] = $value['inquiry_mode']; + $doctor_inquiry_config_service = DoctorInquiryConfigService::getOne($params); + if (empty($doctor_inquiry_config_service)){ + return fail(); + } + + $value['times_number'] = $doctor_inquiry_config_service['service_rounds']; // 服务回合数(0表示不限次) + $value['duration'] = $doctor_inquiry_config_service['service_period']; // 服务周期(天,不存在0的情况) + $value['service_content'] = $doctor_inquiry_config_service['service_content'];// 服务内容 + $value['service_process'] = $doctor_inquiry_config_service['service_process'];// 服务流程 + + unset($doctor_inquiry_config_service); + }else{ + // 获取系统问诊配置 + $fields = [ + 'system_inquiry_config_id', + 'times_number', + 'duration', + ]; + + $params = array(); + $params['inquiry_type'] = $value['inquiry_type']; + $params['inquiry_mode'] = $value['inquiry_mode']; + $system_inquiry_config = SystemInquiryConfig::getOne($params,$fields); + if (empty($system_inquiry_config)){ + return fail(); + } + + $value['times_number'] = $system_inquiry_config['times_number'];// 沟通次数(0为不限制次数) + $value['duration'] = $system_inquiry_config['duration'];// 沟通时长(分钟,0为不限制时长) + + unset($system_inquiry_config); + } + } + } + + return success($doctor_inquiry_config->toArray()); + } + /** * 检测医生身份认证 * @param object|array $user_doctor 医生表数据 @@ -2268,4 +2752,37 @@ class UserDoctorService extends BaseService } + /** + * 获取医生是否可处方图标展示状态 + * @param string $doctor_id 医生id + * @param array|object $doctor_inquiry_configs 医生问诊配置 + * @return int + */ + public function getDoctorMultiPointEnable(string $doctor_id = "",array|object $doctor_inquiry_configs = []): int + { + $multi_point_enable = 0; // 是否开启问诊购药 + if (!empty($doctor_inquiry_configs)){ + foreach ($doctor_inquiry_configs as $doctor_inquiry_config ){ + if ($doctor_inquiry_config['inquiry_type'] == 4 && $doctor_inquiry_config['inquiry_mode'] == 1 && $doctor_inquiry_config['is_enable'] == 1){ + $multi_point_enable = 1; + } + } + } else { + if (empty($doctor_id)){ + return $multi_point_enable; + } + + $params = array(); + $params['doctor_id'] = $doctor_id; + $params['inquiry_type'] = 4; + $params['inquiry_mode'] = 1; + $params['is_enable'] = 1; + $result = DoctorInquiryConfig::getOne($params); + if (!empty($result)){ + $multi_point_enable = 1; // 是否开启问诊购药 + } + } + + return $multi_point_enable; + } } \ No newline at end of file diff --git a/app/Services/UserService.php b/app/Services/UserService.php index a1d8f9e..f3771cf 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -927,7 +927,7 @@ class UserService extends BaseService /** * 处理用户im登陆状态 - * @param array $data im消息体 + * @param array $msg_data im消息体 * { "CallbackCommand":"State.StateChange", "Info":{ @@ -1147,7 +1147,7 @@ class UserService extends BaseService return $result; } - if ($content['message_type'] == 4 || $content['message_type'] == 5){ + if ($content['message_type'] == 4 || $content['message_type'] == 5 || $content['message_type'] == 20){ // 4/5类型时不进行处理 $result['message'] = "成功"; $result['code'] = 1; diff --git a/app/Services/VideoService.php b/app/Services/VideoService.php new file mode 100644 index 0000000..b33eb0c --- /dev/null +++ b/app/Services/VideoService.php @@ -0,0 +1,296 @@ +request->getAttribute("userInfo") ?? []; + + $order_inquiry_id = $this->request->input('order_inquiry_id'); + $reservation_time = $this->request->input('reservation_time'); + + // 检测预约时间 + if (time() >= strtotime($reservation_time)) { + return fail(HttpEnumCode::HTTP_ERROR, "预约时间须大于当前时间"); + } + + // 获取问诊订单数据 + $params = array(); + $params['order_inquiry_id'] = $order_inquiry_id; + $params['doctor_id'] = $user_info['client_user_id']; + $order_inquiry = OrderInquiry::getOne($params); + if (empty($order_inquiry)) { + return fail(); + } + + if ($order_inquiry['inquiry_type'] != 1) { + return fail(); + } + + if ($order_inquiry['inquiry_mode'] != 2) { + return fail(HttpEnumCode::HTTP_ERROR, "订单类型错误"); + } + + // 检测订单状态 + if ($order_inquiry['inquiry_status'] != 4) { + return fail(HttpEnumCode::HTTP_ERROR, "订单状态错误"); + } + + // 获取系统问诊配置 + $params = array(); + $params['inquiry_type'] = $order_inquiry['inquiry_type']; + $params['inquiry_mode'] = $order_inquiry['inquiry_mode']; + $system_inquiry_config = SystemInquiryConfig::getOne($params); + if (empty($system_inquiry_config)) { + return fail(); + } + + // 问诊结束时间 + $complete_time = strtotime($order_inquiry['reception_time']) + $system_inquiry_config['duration'] * 60 - 10 * 60; + + // 检测问诊结束时间 预约时间不可超出视频问诊结束时间 + if (strtotime($reservation_time) >= $complete_time) { + return fail(HttpEnumCode::HTTP_ERROR, "预约时间不可超出视频问诊结束时间"); + } + + // 获取是否已经预约 + $is_reservation = false; + + $params = array(); + $params['order_inquiry_id'] = $order_inquiry_id; + $order_inquiry_video_reservation = OrderInquiryVideoReservation::getOne($params); + if (!empty($order_inquiry_video_reservation)) { + // 检测预约时间修改次数 + if ($order_inquiry_video_reservation['update_number'] >= 1) { + return fail(HttpEnumCode::HTTP_ERROR, "已无法设置/修改视频时间,可立即发起视频"); + } + + // 检测是否已开过视频 + $params = array(); + $params['order_inquiry_id'] = $order_inquiry_id; + $order_inquiry_video_record = OrderInquiryVideoRecord::getOne($params); + if (!empty($order_inquiry_video_record)) { + return fail(HttpEnumCode::HTTP_ERROR, "已开过视频,无需再修改预约时间"); + } + + $is_reservation = true; + } + + Db::beginTransaction(); + + try { + if (empty($order_inquiry_video_reservation)) { + // 获取用户-医生数据 + $params = array(); + $params['doctor_id'] = $order_inquiry['doctor_id']; + $user_doctor = UserDoctor::getOne($params); + if (empty($user_doctor)) { + Db::rollBack(); + return fail(HttpEnumCode::SERVER_ERROR, "设置失败"); + } + + // 创建视频预约数据 + $data = array(); + $data['patient_id'] = $order_inquiry['patient_id']; + $data['patient_user_id'] = $order_inquiry['user_id']; + $data['doctor_id'] = $order_inquiry['doctor_id']; + $data['doctor_user_id'] = $user_doctor['user_id']; + $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $data['room_id'] = substr($order_inquiry['doctor_id'], -5) . substr(time(), -4); + $data['reservation_time'] = $reservation_time; + $order_inquiry_video_reservation = OrderInquiryVideoReservation::addOrderInquiryVideoReservation($data); + if (empty($order_inquiry_video_reservation)) { + Db::rollBack(); + return fail(HttpEnumCode::SERVER_ERROR, "设置失败"); + } + } else { + // 修改预约时间 + $data = array(); + $data['reservation_time'] = $reservation_time; + $data['update_number'] = 1; + + $params = array(); + $params['reservation_id'] = $order_inquiry_video_reservation['reservation_id']; + $res = OrderInquiryVideoReservation::edit($params, $data); + if (!$res) { + Db::rollBack(); + return fail(HttpEnumCode::SERVER_ERROR, "设置失败"); + } + } + + Db::commit(); + } catch (\Throwable $e) { + Db::rollBack(); + Log::getInstance("InquiryService-addDoctorGiveInquiryOrder")->error($e->getMessage()); + return fail(HttpEnumCode::SERVER_ERROR, $e->getMessage()); + } + + // 发送消息 + try { + // 获取订单医生数据 + $params = array(); + $params['doctor_id'] = $order_inquiry['doctor_id']; + $user_doctor = UserDoctor::getOne($params); + if (empty($user_doctor)) { + return fail(HttpEnumCode::SERVER_ERROR, "设置失败"); + } + + // 获取订单用户数据 + $params = array(); + $params['user_id'] = $order_inquiry['user_id']; + $user = User::getOne($params); + if (empty($user)) { + return fail(HttpEnumCode::SERVER_ERROR, "设置失败"); + } + + // 发送im消息 + $imService = new ImService(); + + if (!$is_reservation) { + // 新增 + // 已成功预约视频问诊时间-医生 + $imService->addVideoReservationTimeToDoctor($order_inquiry, $user_doctor['user_id'], $order_inquiry['user_id'], $reservation_time); + + // 已成功预约视频问诊时间-患者 + $imService->addVideoReservationTimeToPatient($order_inquiry, $user_doctor['user_id'], $order_inquiry['user_id'], $reservation_time); + } else { + // 修改 + // 已成功修改视频问诊时间-医生 + $imService->modifyVideoReservationTimeToDoctor($order_inquiry, $user_doctor['user_id'], $order_inquiry['user_id'], $reservation_time); + + // 已成功修改视频问诊时间-患者 + $imService->modifyVideoReservationTimeToPatient($order_inquiry, $user_doctor['user_id'], $order_inquiry['user_id'], $reservation_time); + } + + // 患者-通知患者视频时间 + $sendSmsService = new SendSmsService($user['mobile']); + $sendSmsService->noticePatientVideoTime($user_doctor['user_name'], $reservation_time); + + // 增加延迟队列通知-视频问诊即将开始-时间大于5分钟 + $time = strtotime($reservation_time) - 5 * 60; + if ($time > time()) { + $data = array(); + $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $message = new SendVideoNoticeDelayDirectProducer($data); + $message->setDelayMs(1000 * (strtotime($reservation_time) - time())); + $producer = $this->container->get(Producer::class); + $res = $producer->produce($message); + if (!$res) { + return fail(HttpEnumCode::SERVER_ERROR, "设置失败"); + } + } + } catch (\Throwable $e) { + Log::getInstance("InquiryService-addDoctorGiveInquiryOrder")->error($e->getMessage()); + } + + $result = array(); + $result['order_inquiry_id'] = (string)$order_inquiry['order_inquiry_id']; // 订单主键id + $result['inquiry_no'] = (string)$order_inquiry['inquiry_no']; // 订单编号 + + return success($result); + } + + /** + * 创建音视频房间 + * @return array + */ + public function addVideoRoom(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + + $order_inquiry_id = $this->request->input('order_inquiry_id'); + + // 获取问诊订单数据 + $params = array(); + $params['order_inquiry_id'] = $order_inquiry_id; + $params['doctor_id'] = $user_info['client_user_id']; + $order_inquiry = OrderInquiry::getOne($params); + if (empty($order_inquiry)) { + return fail(); + } + + if ($order_inquiry['inquiry_type'] != 1) { + return fail(); + } + + if ($order_inquiry['inquiry_mode'] != 2) { + return fail(HttpEnumCode::HTTP_ERROR, "订单类型错误"); + } + + // 检测订单状态-问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + if ($order_inquiry['inquiry_status'] == 3) { + return fail(HttpEnumCode::HTTP_ERROR, "订单未接诊,无法发起视频"); + } + + if ($order_inquiry['inquiry_status'] == 5) { + return fail(HttpEnumCode::HTTP_ERROR, "订单已完成,无法发起视频"); + } + + if ($order_inquiry['inquiry_status'] == 6) { + return fail(HttpEnumCode::HTTP_ERROR, "订单已结束,无法发起视频"); + } + + if ($order_inquiry['inquiry_status'] == 7) { + return fail(HttpEnumCode::HTTP_ERROR, "订单已取消,无法发起视频"); + } + + $params = array(); + $params['order_inquiry_id'] = $order_inquiry_id; + $order_inquiry_video_reservation = OrderInquiryVideoReservation::getOne($params); + if (empty($order_inquiry_video_reservation)) { + return fail(HttpEnumCode::HTTP_ERROR, "您还没有和患者预约视频时间,无法发起视频"); + } + + if (empty($order_inquiry_video_reservation['room_id'])){ + // 视频房间创建错误,无房间号 + return fail(HttpEnumCode::SERVER_ERROR); + } + + Db::beginTransaction(); + + try { + // 增加视频记录 + $data = array(); + $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + $data['room_id'] = $order_inquiry_video_reservation['room_id']; + $data['video_status'] = 1; + $data['start_video_time'] = date('Y-m-d H:i:s', time()); + $order_inquiry_video_record = OrderInquiryVideoRecord::addOrderInquiryVideoRecord($data); + if (empty($order_inquiry_video_record)) { + Db::rollBack(); + return fail(HttpEnumCode::SERVER_ERROR, "发起视频失败"); + } + + Db::commit(); + } catch (\Throwable $e) { + Db::rollBack(); + Log::getInstance("VideoService-addVideoRoom")->error($e->getMessage()); + return fail(HttpEnumCode::SERVER_ERROR, $e->getMessage()); + } + + return success($order_inquiry_video_reservation['room_id']); + } +} \ No newline at end of file diff --git a/app/Utils/Auth.php b/app/Utils/Auth.php index 78d99a2..7eeffd9 100644 --- a/app/Utils/Auth.php +++ b/app/Utils/Auth.php @@ -39,6 +39,8 @@ class Auth "/test/refund" => "get", // 测试退款 "/test" => "get", // 测试 "/callback/detection" => "post", // 检测所结果回调 + "/callback/video/trtc" => "post", // 音视频回调 + "/callback/video/recording" => "post", // 音视频回调 ]; } diff --git a/app/Utils/PcreMatch.php b/app/Utils/PcreMatch.php index 47a995f..e848169 100644 --- a/app/Utils/PcreMatch.php +++ b/app/Utils/PcreMatch.php @@ -61,4 +61,22 @@ class PcreMatch return str_replace(config('alibaba.oss.custom_domain_name'),"",$path); } + + /** + * 验证邮箱是否有效 + * @param $email + * @return bool + */ + public static function validateEmail($email): bool + { + // 正则表达式 + $pattern = '/^[\w.%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/'; + + // 使用 preg_match 进行匹配 + if (preg_match($pattern, $email)) { + return true; // 有效的电子邮件地址 + } else { + return false; // 无效的电子邮件地址 + } + } } \ No newline at end of file diff --git a/config/config.php b/config/config.php index 835957d..0d539ff 100644 --- a/config/config.php +++ b/config/config.php @@ -90,10 +90,10 @@ return [ "busunessId" => "", ], 'im' =>[ // 腾讯im - "app_id" => env('IM_APPID','1400798221'), - "secret" => env('IM_SECRET','fc45ab469ca632a700166973d87b3a6f56a855cb92d7cffb54e4d37135c097da'), + "app_id" => env('IM_APPID','1600022752'), + "secret" => env('IM_SECRET','243f3b0276a04bf4b876bd7ebf8d74a6be0c8cf344f624b0ce936666f273accd'), "base_url" => env('IM_BASE_URL','https://console.tim.qq.com/'), - "token" => env('IM_TOKEN','NDc5MzExMDMxMDY2NDMxNDg5L'), + "token" => env('IM_TOKEN','NDc5MzExMDIYdusl2NDMxNDg5L'), ], 'ca' => [ // ca "offline" => [ @@ -128,4 +128,10 @@ return [ "secret" => env('TENCENT_MAP_SECRET', 'RDQBZ-SDQ6Z-GKRX5-TG7P5-R2LN5-BWFCH'), "key" => env('TENCENT_MAP_KEY', '6tZo4VootrcGOuYqRX9aoGdtAmuSNXd4') ], + 'video' =>[ // 腾讯im + "app_id" => env('TRTC_APPID','1600022752'), + "secret" => env('TRTC_SECRET','243f3b0276a04bf4b876bd7ebf8d74a6be0c8cf344f624b0ce936666f273accd'), + "base_url" => env('TRTC_BASE_URL','https://console.tim.qq.com/'), + "token" => env('TRTC_TOKEN','NDc5MzExMDIYdusl2NDMxNDg5L'), + ], ]; diff --git a/config/routes.php b/config/routes.php index d218763..a469f7b 100644 --- a/config/routes.php +++ b/config/routes.php @@ -16,6 +16,7 @@ use App\Controller\CallBackController; use App\Controller\DetectionController; use App\Controller\DoctorAccountController; use App\Controller\DoctorAuthController; +use App\Controller\DoctorInquiryConfigController; use App\Controller\IndexController; use App\Controller\InquiryController; use App\Controller\LoginController; @@ -33,6 +34,7 @@ use App\Controller\UserController; use App\Controller\UserDoctorController; use App\Controller\UserPatientController; use App\Controller\UserPharmacistController; +use App\Controller\VideoController; use App\Middleware\Rule\LockRequestMiddleware; use Hyperf\HttpServer\Router\Router; @@ -47,39 +49,75 @@ Router::addGroup('/doctor', function () { // 身份认证 Router::addGroup('/auth', function () { - // 获取实名认证信息 - Router::get('/real', [DoctorAuthController::class, 'getAuthReal']); + // 实名认证 + Router::addGroup('/real', function () { + // 获取实名认证信息 + Router::get('', [DoctorAuthController::class, 'getAuthReal']); - // 新增实名认证 - Router::post('/real', [DoctorAuthController::class, 'addAuthReal']); + // 新增实名认证 + Router::post('', [DoctorAuthController::class, 'addAuthReal']); + }); - // 获取身份认证信息 - Router::get('/iden', [DoctorAuthController::class, 'getAuthIden']); + // 身份认证 + Router::addGroup('/iden', function () { + // 获取身份认证信息 + Router::get('', [DoctorAuthController::class, 'getAuthIden']); - // 新增身份认证信息 - Router::post('/iden', [DoctorAuthController::class, 'addAuthIden'], - [ - 'middleware' => [LockRequestMiddleware::class] // 锁定重复请求 - ] - ); + // 新增身份认证信息 + Router::post('', [DoctorAuthController::class, 'addAuthIden'], + [ + 'middleware' => [LockRequestMiddleware::class] // 锁定重复请求 + ] + ); - // 获取多点执业认证信息 - Router::get('/multi', [DoctorAuthController::class, 'getAuthMulti']); + // 获取身份认证审核失败原因 + Router::get('/reason', [DoctorAuthController::class, 'getIdenAuthFailReason']); + }); - // 新增多点执业认证信息 - Router::post('/multi', [DoctorAuthController::class, 'addAuthMulti']); + // 多点认证 + Router::addGroup('/multi', function () { + // 获取多点执业认证信息 + Router::get('', [DoctorAuthController::class, 'getAuthMulti']); + + // 新增多点执业认证信息 + Router::post('', [DoctorAuthController::class, 'addAuthMulti']); + }); + + // 个人简介 + Router::addGroup('/introduction', function () { + // 获取个人简介 + Router::get('', [DoctorAuthController::class, 'getDoctorIntroduction']); + + // 修改个人简介 + Router::put('', [DoctorAuthController::class, 'putDoctorIntroduction']); + + // 获取个人简介审核失败原因 + Router::get('/reason', [DoctorAuthController::class, 'getDoctorIntroductionFailReason']); + }); }); // 问诊 Router::addGroup('/inquiry', function () { - // 获取医生问诊配置 - Router::get('/config', [UserDoctorController::class, 'getInquiryConfig']); + // 问诊配置 + Router::addGroup('/config', function () { + // 获取医生问诊配置 + Router::get('', [DoctorInquiryConfigController::class, 'getDoctorInquiryConfig']); - // 医生问诊开关 - Router::put('/open', [UserDoctorController::class, 'putInquiryOpen']); + // 修改医生问诊配置 + Router::put('', [DoctorInquiryConfigController::class, 'putDoctorInquiryConfig']); - // 修改医生问诊配置 - Router::put('/config', [UserDoctorController::class, 'putInquiryConfig']); + // 医生问诊开关 + Router::put('/open', [DoctorInquiryConfigController::class, 'putDoctorInquiryOpen']); + + // 获取医生问诊配置-疑难会诊-服务设置 + Router::get('/service', [DoctorInquiryConfigController::class, 'getInquiryServiceConfig']); + + // 新增医生问诊配置-疑难会诊-服务设置 + Router::post('/service', [DoctorInquiryConfigController::class, 'addInquiryServiceConfig']); + + // 修改医生问诊配置-疑难会诊-服务设置 + Router::put('/service/{config_service_id:\d+}', [DoctorInquiryConfigController::class, 'putInquiryServiceConfig']); + }); // 获取医生问诊消息列表 Router::get('/message', [UserDoctorController::class, 'getDoctorMessageList']); @@ -92,6 +130,18 @@ Router::addGroup('/doctor', function () { // 结束问诊会话列表 Router::get('/finish/message', [InquiryController::class, 'getDoctorFinishMessageList']); + + // 医生赠送沟通回合数 + Router::post('/give', [InquiryController::class, 'addDoctorGiveInquiryOrder']); + + // 视频 + Router::addGroup('/video', function () { + // 医生设置视频预约时间 + Router::post('/date', [VideoController::class, 'addVideoReservationDate']); + + // 创建音视频房间 + Router::post('/room', [VideoController::class, 'addVideoRoom']); + }); }); //银行卡 @@ -193,6 +243,7 @@ Router::addGroup('/doctor', function () { // 获取医生名片 Router::get('/card', [UserDoctorController::class, 'getDoctorInfoCard']); + // 个人简介 Router::addGroup('/brief', function () { // 获取医生个人简介数据 Router::get('', [UserDoctorController::class, 'getDoctorBrief']); @@ -306,9 +357,6 @@ Router::addGroup('/patient', function () { // 获取医生列表-问诊 Router::get('/inquiry', [PatientDoctorController::class, 'getInquiryDoctorList']); - // 获取医生详情-问诊 - Router::get('/{doctor_id:\d+}', [PatientDoctorController::class, 'getInquiryDoctorInfo']); - // 医生详情简介-详情中的简介-废弃 Router::get('/profile/{doctor_id:\d+}', [PatientDoctorController::class, 'getDoctorProfile']); @@ -566,6 +614,9 @@ Router::addGroup('/sign', function () { // 获取im签名数据 Router::get('/im', [SafeController::class, 'getImSign']); + + // 获取音视频签名数据 + Router::get('/video', [SafeController::class, 'getVideoSign']); }); // 基础数据 @@ -676,9 +727,18 @@ Router::addGroup('/callback', function () { }); }); - // im回调 + // im聊天回调 Router::post('/im', [CallBackController::class, 'imCallBack']); + // 音视频回调 + Router::addGroup('/video', function () { + // 房间与媒体 + Router::post('/trtc', [CallBackController::class, 'videoTrtcCallBack']); + + // 云端录制 + Router::post('/recording', [CallBackController::class, 'videoRecordingCallBack']); + }); + // 处方平台物流回调 Router::post('/platform/logistics', [CallBackController::class, 'platformLogisticsCallBack']); @@ -745,7 +805,7 @@ Router::addGroup('/test', function () { Router::get('', [TestController::class, 'test_17']); // - Router::get('/uninquiry', [TestController::class, 'uninquiry']); +// Router::get('/uninquiry', [TestController::class, 'uninquiry']); // 模拟退款 // Router::get('/refund', [TestController::class, 'refund']); @@ -784,13 +844,31 @@ Router::addGroup('/message', function () { // 问诊订单 Router::addGroup('/inquiry', function () { // 获取问诊订单消息内页基础数据 - Router::get('/message/basic/{order_inquiry_id:\d+}', [InquiryController::class, 'getInquiryMessageBasic']); +// Router::get('/message/basic/{order_inquiry_id:\d+}', [InquiryController::class, 'getInquiryMessageBasic']); // 结束问诊 Router::put('/finish/{order_inquiry_id:\d+}', [InquiryController::class, 'putFinishInquiry']); // 获取患者最后一条问诊订单id Router::get('/last', [InquiryController::class, 'getPatientLastInquiryId']); + + // 获取视频问诊消息内页基础数据 +// Router::put('/message/{order_inquiry_id:\d+}', [InquiryController::class, 'putFinishInquiry']); +}); + +// 聊天 +Router::addGroup('/im', function () { + // 问诊订单 + Router::addGroup('/inquiry', function () { + // 问诊订单 + Router::addGroup('/basic', function () { + // 获取问诊订单消息内页基础数据 + Router::get('/{order_inquiry_id:\d+}', [InquiryController::class, 'getInquiryMessageBasic']); + + // 获取视频问诊消息内页基础数据 + Router::get('/video/{order_inquiry_id:\d+}', [InquiryController::class, 'getInquiryVideoMessageBasic']); + }); + }); }); // 获取弹窗数据 @@ -812,4 +890,16 @@ Router::addGroup('/pathography', function () { // 删除家庭成员病情记录 Router::delete('/{pathography_id:\d+}', [PatientPathographyController::class, 'deleteFamilyPathography']); +}); + +// 医生数据 +Router::addGroup('/doctor', function () { + // 详情 + Router::addGroup('/info', function () { + // 获取医生详情-问诊 + Router::get('/inquiry/{doctor_id:\d+}', [UserDoctorController::class, 'getDoctorInfoInquiry']); + }); + + // 获取医生开启的服务列表 + Router::get('/inquiry/service/{doctor_id:\d+}', [UserDoctorController::class, 'getDoctorOpenInquiryService']); }); \ No newline at end of file diff --git a/extend/Ca/msyh.ttf b/extend/Ca/msyh.ttf deleted file mode 100755 index b4456b2..0000000 Binary files a/extend/Ca/msyh.ttf and /dev/null differ diff --git a/extend/RegulatoryPlatform/regulatoryPlatform.php b/extend/RegulatoryPlatform/regulatoryPlatform.php index 1d25f32..952bfa9 100644 --- a/extend/RegulatoryPlatform/regulatoryPlatform.php +++ b/extend/RegulatoryPlatform/regulatoryPlatform.php @@ -80,7 +80,15 @@ class regulatoryPlatform throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); } - $this->redis->set("regulatory_platform_access_token", $data['accessToken'], 60 * 60 * 24 * 6); + // 默认为6天 + $expires_in = 60 * 60 * 24 * 6; + if (!empty($data['expiresIn'])) { + if ($data['expiresIn'] > 100){ + $expires_in = $data['expiresIn']; + } + } + + $this->redis->set("regulatory_platform_access_token", $data['accessToken'],$expires_in); return $data['accessToken']; } catch (GuzzleException $e) { @@ -156,7 +164,6 @@ class regulatoryPlatform ]; $response = $this->httpRequest($this->api_url . '/wjw/upload/uploadFurtherConsult', $option); - dump($response); if (isset($response['status'])) { if ($response['status'] != 0) { if (!empty($response['message'])) { @@ -216,7 +223,7 @@ class regulatoryPlatform /** * 请求封装 * @param string $path - * @param array $option + * @param array $arg * @return array * @throws GuzzleException */ @@ -229,7 +236,7 @@ class regulatoryPlatform $arg = array_merge($arg, $option); } - Log::getInstance()->info(json_encode($arg,JSON_UNESCAPED_UNICODE)); + Log::getInstance("regulatoryPlatform-httpRequest")->info(json_encode($arg,JSON_UNESCAPED_UNICODE)); $response = $this->client->post($path, $arg); if ($response->getStatusCode() != '200') { @@ -238,7 +245,7 @@ class regulatoryPlatform } $body = json_decode($response->getBody(), true); - Log::getInstance()->info(json_encode($body,JSON_UNESCAPED_UNICODE)); + Log::getInstance("regulatoryPlatform-httpRequest")->info(json_encode($body,JSON_UNESCAPED_UNICODE)); if (empty($body)) { // 返回值为空 throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); diff --git a/extend/TencentVideo/Base.php b/extend/TencentVideo/Base.php new file mode 100644 index 0000000..c47050f --- /dev/null +++ b/extend/TencentVideo/Base.php @@ -0,0 +1,111 @@ +config = config("video"); + + if (empty($this->config)) { + throw new BusinessException("系统配置错误", HttpEnumCode::SERVER_ERROR); + } + } + + /** + * 获取用户签名 + * @param string $user_id + * @return string + */ + protected function getUserSign(string $user_id = ""): string + { + try { + $TLSSigAPIv2 = new TLSSigAPIv2($this->config['app_id'], $this->config['secret']); + + if (empty($user_id)){ + $user_sign = $TLSSigAPIv2->genUserSig($this->identifier); + }else{ + $user_sign = $TLSSigAPIv2->genUserSig($user_id); + } + + if (empty($user_sign)) { + throw new BusinessException("获取im用户签名失败"); + } + + return $user_sign; + } catch (\Exception $e) { + throw new BusinessException($e->getMessage()); + } + } + + /** + * 组合请求参数 + * @return string + */ + protected function buildRequestParams(): string + { + $result = array(); + $result['sdkappid'] = $this->config['app_id']; + $result['identifier'] = $this->identifier; + $result['usersig'] = $this->getUserSign(); + $result['random'] = mt_rand(0, 4294967295); + $result['contenttype'] = "json"; + + return http_build_query($result); + } + + /** + * 封装请求 + * @param string $path + * @param array $option + * @return array + * @throws GuzzleException + */ + protected function postRequest(string $path, array $option = []): array + { + $factory = new HandlerStackFactory(); + $stack = $factory->create(); + + $client = make(Client::class, [ + 'config' => [ + 'handler' => $stack, + 'timeout' => 10, + 'verify' => false, + ], + ]); + $response = $client->post($path, $option); + + if ($response->getStatusCode() != '200'){ + // 请求失败 + throw new BusinessException($response->getBody()->getContents()); + } + + $content = json_decode($response->getBody(),true); + + if (empty($content)){ + throw new BusinessException("请求失败"); + } + + if ($content['ErrorCode'] != 0){ + throw new BusinessException($content['ErrorInfo']); + } + return $content; + } + + + + +} \ No newline at end of file diff --git a/extend/TencentVideo/Safe.php b/extend/TencentVideo/Safe.php new file mode 100644 index 0000000..f969aa3 --- /dev/null +++ b/extend/TencentVideo/Safe.php @@ -0,0 +1,43 @@ +__genSig( $userid, $expire, '', false ); + } + + /** + *【功能说明】 + * 用于签发 TRTC 进房参数中可选的 PrivateMapKey 权限票据。 + * PrivateMapKey 需要跟 UserSig 一起使用,但 PrivateMapKey 比 UserSig 有更强的权限控制能力: + * - UserSig 只能控制某个 UserID 有无使用 TRTC 服务的权限,只要 UserSig 正确,其对应的 UserID 可以进出任意房间。 + * - PrivateMapKey 则是将 UserID 的权限控制的更加严格,包括能不能进入某个房间,能不能在该房间里上行音视频等等。 + * 如果要开启 PrivateMapKey 严格权限位校验,需要在【实时音视频控制台】=>【应用管理】=>【应用信息】中打开“启动权限密钥”开关。 + * + *【参数说明】 + * @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。 + * @param expire - PrivateMapKey 票据的过期时间,单位是秒,比如 86400 生成的 PrivateMapKey 票据在一天后就无法再使用了。 + * @param roomid - 房间号,用于指定该 userid 可以进入的房间号 + * @param privilegeMap - 权限位,使用了一个字节中的 8 个比特位,分别代表八个具体的功能权限开关: + * - 第 1 位:0000 0001 = 1,创建房间的权限 + * - 第 2 位:0000 0010 = 2,加入房间的权限 + * - 第 3 位:0000 0100 = 4,发送语音的权限 + * - 第 4 位:0000 1000 = 8,接收语音的权限 + * - 第 5 位:0001 0000 = 16,发送视频的权限 + * - 第 6 位:0010 0000 = 32,接收视频的权限 + * - 第 7 位:0100 0000 = 64,发送辅路(也就是屏幕分享)视频的权限 + * - 第 8 位:1000 0000 = 200,接收辅路(也就是屏幕分享)视频的权限 + * - privilegeMap == 1111 1111 == 255 代表该 userid 在该 roomid 房间内的所有功能权限。 + * - privilegeMap == 0010 1010 == 42 代表该 userid 拥有加入房间和接收音视频数据的权限,但不具备其他权限。 + */ + + /** + * Function: + * Used to issue PrivateMapKey that is optional for room entry. + * PrivateMapKey must be used together with UserSig but with more powerful permission control capabilities. + * - UserSig can only control whether a UserID has permission to use the TRTC service. As long as the UserSig is correct, the user with the corresponding UserID can enter or leave any room. + * - PrivateMapKey specifies more stringent permissions for a UserID, including whether the UserID can be used to enter a specific room and perform audio/video upstreaming in the room. + * To enable stringent PrivateMapKey permission bit verification, you need to enable permission key in TRTC console > Application Management > Application Info. + * + * Parameter description: + * userid - User ID. The value can be up to 32 bytes in length and contain letters (a-z and A-Z), digits (0-9), underscores (_), and hyphens (-). + * roomid - ID of the room to which the specified UserID can enter. + * expire - PrivateMapKey expiration time, in seconds. For example, 86400 indicates that the generated PrivateMapKey will expire one day after being generated. + * privilegeMap - Permission bits. Eight bits in the same byte are used as the permission switches of eight specific features: + * - Bit 1: 0000 0001 = 1, permission for room creation + * - Bit 2: 0000 0010 = 2, permission for room entry + * - Bit 3: 0000 0100 = 4, permission for audio sending + * - Bit 4: 0000 1000 = 8, permission for audio receiving + * - Bit 5: 0001 0000 = 16, permission for video sending + * - Bit 6: 0010 0000 = 32, permission for video receiving + * - Bit 7: 0100 0000 = 64, permission for substream video sending (screen sharing) + * - Bit 8: 1000 0000 = 200, permission for substream video receiving (screen sharing) + * - privilegeMap == 1111 1111 == 255: Indicates that the UserID has all feature permissions of the room specified by roomid. + * - privilegeMap == 0010 1010 == 42: Indicates that the UserID has only the permissions to enter the room and receive audio/video data. + */ + + public function genPrivateMapKey( $userid, $expire, $roomid, $privilegeMap ) { + $userbuf = $this->__genUserBuf( $userid, $roomid, $expire, $privilegeMap, 0, '' ); + return $this->__genSig( $userid, $expire, $userbuf, true ); + } + /** + *【功能说明】 + * 用于签发 TRTC 进房参数中可选的 PrivateMapKey 权限票据。 + * PrivateMapKey 需要跟 UserSig 一起使用,但 PrivateMapKey 比 UserSig 有更强的权限控制能力: + * - UserSig 只能控制某个 UserID 有无使用 TRTC 服务的权限,只要 UserSig 正确,其对应的 UserID 可以进出任意房间。 + * - PrivateMapKey 则是将 UserID 的权限控制的更加严格,包括能不能进入某个房间,能不能在该房间里上行音视频等等。 + * 如果要开启 PrivateMapKey 严格权限位校验,需要在【实时音视频控制台】=>【应用管理】=>【应用信息】中打开“启动权限密钥”开关。 + * + *【参数说明】 + * @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。 + * @param expire - PrivateMapKey 票据的过期时间,单位是秒,比如 86400 生成的 PrivateMapKey 票据在一天后就无法再使用了。 + * @param roomstr - 房间号,用于指定该 userid 可以进入的房间号 + * @param privilegeMap - 权限位,使用了一个字节中的 8 个比特位,分别代表八个具体的功能权限开关: + * - 第 1 位:0000 0001 = 1,创建房间的权限 + * - 第 2 位:0000 0010 = 2,加入房间的权限 + * - 第 3 位:0000 0100 = 4,发送语音的权限 + * - 第 4 位:0000 1000 = 8,接收语音的权限 + * - 第 5 位:0001 0000 = 16,发送视频的权限 + * - 第 6 位:0010 0000 = 32,接收视频的权限 + * - 第 7 位:0100 0000 = 64,发送辅路(也就是屏幕分享)视频的权限 + * - 第 8 位:1000 0000 = 200,接收辅路(也就是屏幕分享)视频的权限 + * - privilegeMap == 1111 1111 == 255 代表该 userid 在该 roomid 房间内的所有功能权限。 + * - privilegeMap == 0010 1010 == 42 代表该 userid 拥有加入房间和接收音视频数据的权限,但不具备其他权限。 + */ + + /** + * Function: + * Used to issue PrivateMapKey that is optional for room entry. + * PrivateMapKey must be used together with UserSig but with more powerful permission control capabilities. + * - UserSig can only control whether a UserID has permission to use the TRTC service. As long as the UserSig is correct, the user with the corresponding UserID can enter or leave any room. + * - PrivateMapKey specifies more stringent permissions for a UserID, including whether the UserID can be used to enter a specific room and perform audio/video upstreaming in the room. + * To enable stringent PrivateMapKey permission bit verification, you need to enable permission key in TRTC console > Application Management > Application Info. + * + * Parameter description: + * @param userid - User ID. The value can be up to 32 bytes in length and contain letters (a-z and A-Z), digits (0-9), underscores (_), and hyphens (-). + * @param roomstr - ID of the room to which the specified UserID can enter. + * @param expire - PrivateMapKey expiration time, in seconds. For example, 86400 indicates that the generated PrivateMapKey will expire one day after being generated. + * @param privilegeMap - Permission bits. Eight bits in the same byte are used as the permission switches of eight specific features: + * - Bit 1: 0000 0001 = 1, permission for room creation + * - Bit 2: 0000 0010 = 2, permission for room entry + * - Bit 3: 0000 0100 = 4, permission for audio sending + * - Bit 4: 0000 1000 = 8, permission for audio receiving + * - Bit 5: 0001 0000 = 16, permission for video sending + * - Bit 6: 0010 0000 = 32, permission for video receiving + * - Bit 7: 0100 0000 = 64, permission for substream video sending (screen sharing) + * - Bit 8: 1000 0000 = 200, permission for substream video receiving (screen sharing) + * - privilegeMap == 1111 1111 == 255: Indicates that the UserID has all feature permissions of the room specified by roomid. + * - privilegeMap == 0010 1010 == 42: Indicates that the UserID has only the permissions to enter the room and receive audio/video data. + */ + + public function genPrivateMapKeyWithStringRoomID( $userid, $expire, $roomstr, $privilegeMap ) { + $userbuf = $this->__genUserBuf( $userid, 0, $expire, $privilegeMap, 0, $roomstr ); + return $this->__genSig( $userid, $expire, $userbuf, true ); + } + + public function __construct( $sdkappid, $key ) { + $this->sdkappid = $sdkappid; + $this->key = $key; + } + + /** + * 用于 url 的 base64 encode + * '+' => '*', '/' => '-', '=' => '_' + * @param string $string 需要编码的数据 + * @return string 编码后的base64串,失败返回false + * @throws \Exception + */ + + /** + * base64 encode for url + * '+' => '*', '/' => '-', '=' => '_' + * @param string $string data to be encoded + * @return string The encoded base64 string, returns false on failure + * @throws \Exception + */ + private function base64_url_encode( $string ) { + static $replace = Array( '+' => '*', '/' => '-', '=' => '_' ); + $base64 = base64_encode( $string ); + if ( $base64 === false ) { + throw new \Exception( 'base64_encode error' ); + } + return str_replace( array_keys( $replace ), array_values( $replace ), $base64 ); + } + + /** + * 用于 url 的 base64 decode + * '+' => '*', '/' => '-', '=' => '_' + * @param string $base64 需要解码的base64串 + * @return string 解码后的数据,失败返回false + * @throws \Exception + */ + + /** + * base64 decode for url + * '+' => '*', '/' => '-', '=' => '_' + * @param string $base64 base64 string to be decoded + * @return string Decoded data, return false on failure + * @throws \Exception + */ + private function base64_url_decode( $base64 ) { + static $replace = Array( '+' => '*', '/' => '-', '=' => '_' ); + $string = str_replace( array_values( $replace ), array_keys( $replace ), $base64 ); + $result = base64_decode( $string ); + if ( $result == false ) { + throw new \Exception( 'base64_url_decode error' ); + } + return $result; + } + /** + * TRTC业务进房权限加密串使用用户定义的userbuf + * @brief 生成 userbuf + * @param account 用户名 + * @param dwSdkappid sdkappid + * @param dwAuthID 数字房间号 + * @param dwExpTime 过期时间:该权限加密串的过期时间. 过期时间 = now+dwExpTime + * @param dwPrivilegeMap 用户权限,255表示所有权限 + * @param dwAccountType 用户类型, 默认为0 + * @param roomStr 字符串房间号 + * @return userbuf string 返回的userbuf + */ + + /** + * User-defined userbuf is used for the encrypted string of TRTC service entry permission + * @brief generate userbuf + * @param account username + * @param dwSdkappid sdkappid + * @param dwAuthID digital room number + * @param dwExpTime Expiration time: The expiration time of the encrypted string of this permission. Expiration time = now+dwExpTime + * @param dwPrivilegeMap User permissions, 255 means all permissions + * @param dwAccountType User type, default is 0 + * @param roomStr String room number + * @return userbuf string returned userbuf + */ + + private function __genUserBuf( $account, $dwAuthID, $dwExpTime, $dwPrivilegeMap, $dwAccountType,$roomStr ) { + + //cVer unsigned char/1 版本号,填0 + if($roomStr == '') + $userbuf = pack( 'C1', '0' ); + else + $userbuf = pack( 'C1', '1' ); + + $userbuf .= pack( 'n', strlen( $account ) ); + //wAccountLen unsigned short /2 第三方自己的帐号长度 + $userbuf .= pack( 'a'.strlen( $account ), $account ); + //buffAccount wAccountLen 第三方自己的帐号字符 + $userbuf .= pack( 'N', $this->sdkappid ); + //dwSdkAppid unsigned int/4 sdkappid + $userbuf .= pack( 'N', $dwAuthID ); + //dwAuthId unsigned int/4 群组号码/音视频房间号 + $expire = $dwExpTime + time(); + $userbuf .= pack( 'N', $expire ); + //dwExpTime unsigned int/4 过期时间 (当前时间 + 有效期(单位:秒,建议300秒)) + $userbuf .= pack( 'N', $dwPrivilegeMap ); + //dwPrivilegeMap unsigned int/4 权限位 + $userbuf .= pack( 'N', $dwAccountType ); + //dwAccountType unsigned int/4 + if($roomStr != '') + { + $userbuf .= pack( 'n', strlen( $roomStr ) ); + //roomStrLen unsigned short /2 字符串房间号长度 + $userbuf .= pack( 'a'.strlen( $roomStr ), $roomStr ); + //roomStr roomStrLen 字符串房间号 + } + return $userbuf; + } + /** + * 使用 hmac sha256 生成 sig 字段内容,经过 base64 编码 + * @param $identifier 用户名,utf-8 编码 + * @param $curr_time 当前生成 sig 的 unix 时间戳 + * @param $expire 有效期,单位秒 + * @param $base64_userbuf base64 编码后的 userbuf + * @param $userbuf_enabled 是否开启 userbuf + * @return string base64 后的 sig + */ + + /** + * Use hmac sha256 to generate sig field content, base64 encoded + * @param $identifier Username, utf-8 encoded + * @param $curr_time The unix timestamp of the current generated sig + * @param $expire Validity period, in seconds + * @param $base64_userbuf base64 encoded userbuf + * @param $userbuf_enabled 是No enable userbuf + * @return string sig after base64 + */ + private function hmacsha256( $identifier, $curr_time, $expire, $base64_userbuf, $userbuf_enabled ) { + $content_to_be_signed = 'TLS.identifier:' . $identifier . "\n" + . 'TLS.sdkappid:' . $this->sdkappid . "\n" + . 'TLS.time:' . $curr_time . "\n" + . 'TLS.expire:' . $expire . "\n"; + if ( true == $userbuf_enabled ) { + $content_to_be_signed .= 'TLS.userbuf:' . $base64_userbuf . "\n"; + } + return base64_encode( hash_hmac( 'sha256', $content_to_be_signed, $this->key, true ) ); + } + + /** + * 生成签名。 + * + * @param $identifier 用户账号 + * @param int $expire 过期时间,单位秒,默认 180 天 + * @param $userbuf base64 编码后的 userbuf + * @param $userbuf_enabled 是否开启 userbuf + * @return string 签名字符串 + * @throws \Exception + */ + + /** + * Generate signature. + * + * @param $identifier user account + * @param int $expire Expiration time, in seconds, default 180 days + * @param $userbuf base64 encoded userbuf + * @param $userbuf_enabled Whether to enable userbuf + * @return string signature string + * @throws \Exception + */ + private function __genSig( $identifier, $expire, $userbuf, $userbuf_enabled ) { + $curr_time = time(); + $sig_array = Array( + 'TLS.ver' => '2.0', + 'TLS.identifier' => strval( $identifier ), + 'TLS.sdkappid' => intval( $this->sdkappid ), + 'TLS.expire' => intval( $expire ), + 'TLS.time' => intval( $curr_time ) + ); + + $base64_userbuf = ''; + if ( true == $userbuf_enabled ) { + $base64_userbuf = base64_encode( $userbuf ); + $sig_array['TLS.userbuf'] = strval( $base64_userbuf ); + } + + $sig_array['TLS.sig'] = $this->hmacsha256( $identifier, $curr_time, $expire, $base64_userbuf, $userbuf_enabled ); + if ( $sig_array['TLS.sig'] === false ) { + throw new \Exception( 'base64_encode error' ); + } + $json_str_sig = json_encode( $sig_array ); + if ( $json_str_sig === false ) { + throw new \Exception( 'json_encode error' ); + } + $compressed = gzcompress( $json_str_sig ); + if ( $compressed === false ) { + throw new \Exception( 'gzcompress error' ); + } + return $this->base64_url_encode( $compressed ); + } + + /** + * 验证签名。 + * + * @param string $sig 签名内容 + * @param string $identifier 需要验证用户名,utf-8 编码 + * @param int $init_time 返回的生成时间,unix 时间戳 + * @param int $expire_time 返回的有效期,单位秒 + * @param string $userbuf 返回的用户数据 + * @param string $error_msg 失败时的错误信息 + * @return boolean 验证是否成功 + * @throws \Exception + */ + + /** + * Verify signature. + * + * @param string $sig Signature content + * @param string $identifier Need to authenticate user name, utf-8 encoding + * @param int $init_time Returned generation time, unix timestamp + * @param int $expire_time Return the validity period, in seconds + * @param string $userbuf returned user data + * @param string $error_msg error message on failure + * @return boolean Verify success + * @throws \Exception + */ + + private function __verifySig( $sig, $identifier, &$init_time, &$expire_time, &$userbuf, &$error_msg ) { + try { + $error_msg = ''; + $compressed_sig = $this->base64_url_decode( $sig ); + $pre_level = error_reporting( E_ERROR ); + $uncompressed_sig = gzuncompress( $compressed_sig ); + error_reporting( $pre_level ); + if ( $uncompressed_sig === false ) { + throw new \Exception( 'gzuncompress error' ); + } + $sig_doc = json_decode( $uncompressed_sig ); + if ( $sig_doc == false ) { + throw new \Exception( 'json_decode error' ); + } + $sig_doc = ( array )$sig_doc; + if ( $sig_doc['TLS.identifier'] !== $identifier ) { + throw new \Exception( "identifier dosen't match" ); + } + if ( $sig_doc['TLS.sdkappid'] != $this->sdkappid ) { + throw new \Exception( "sdkappid dosen't match" ); + } + $sig = $sig_doc['TLS.sig']; + if ( $sig == false ) { + throw new \Exception( 'sig field is missing' ); + } + + $init_time = $sig_doc['TLS.time']; + $expire_time = $sig_doc['TLS.expire']; + + $curr_time = time(); + if ( $curr_time > $init_time+$expire_time ) { + throw new \Exception( 'sig expired' ); + } + + $userbuf_enabled = false; + $base64_userbuf = ''; + if ( isset( $sig_doc['TLS.userbuf'] ) ) { + $base64_userbuf = $sig_doc['TLS.userbuf']; + $userbuf = base64_decode( $base64_userbuf ); + $userbuf_enabled = true; + } + $sigCalculated = $this->hmacsha256( $identifier, $init_time, $expire_time, $base64_userbuf, $userbuf_enabled ); + + if ( $sig != $sigCalculated ) { + throw new \Exception( 'verify failed' ); + } + + return true; + } catch ( \Exception $ex ) { + $error_msg = $ex->getMessage(); + return false; + } + } + + /** + * 带 userbuf 验证签名。 + * + * @param string $sig 签名内容 + * @param string $identifier 需要验证用户名,utf-8 编码 + * @param int $init_time 返回的生成时间,unix 时间戳 + * @param int $expire_time 返回的有效期,单位秒 + * @param string $error_msg 失败时的错误信息 + * @return boolean 验证是否成功 + * @throws \Exception + */ + + /** + * Verify signature with userbuf. + * + * @param string $sig Signature content + * @param string $identifier Need to authenticate user name, utf-8 encoding + * @param int $init_time Returned generation time, unix timestamp + * @param int $expire_time Return the validity period, in seconds + * @param string $error_msg error message on failure + * @return boolean Verify success + * @throws \Exception + */ + public function verifySig( $sig, $identifier, &$init_time, &$expire_time, &$error_msg ) { + $userbuf = ''; + return $this->__verifySig( $sig, $identifier, $init_time, $expire_time, $userbuf, $error_msg ); + } + + /** + * 验证签名 + * @param string $sig 签名内容 + * @param string $identifier 需要验证用户名,utf-8 编码 + * @param int $init_time 返回的生成时间,unix 时间戳 + * @param int $expire_time 返回的有效期,单位秒 + * @param string $userbuf 返回的用户数据 + * @param string $error_msg 失败时的错误信息 + * @return boolean 验证是否成功 + * @throws \Exception + */ + + /** + * Verify signature + * @param string $sig Signature content + * @param string $identifier Need to authenticate user name, utf-8 encoding + * @param int $init_time Returned generation time, unix timestamp + * @param int $expire_time Return the validity period, in seconds + * @param string $userbuf returned user data + * @param string $error_msg error message on failure + * @return boolean Verify success + * @throws \Exception + */ + public function verifySigWithUserBuf( $sig, $identifier, &$init_time, &$expire_time, &$userbuf, &$error_msg ) { + return $this->__verifySig( $sig, $identifier, $init_time, $expire_time, $userbuf, $error_msg ); + } +} \ No newline at end of file diff --git a/extend/Wechat/Wechat.php b/extend/Wechat/Wechat.php index d7dd1d7..edefd57 100644 --- a/extend/Wechat/Wechat.php +++ b/extend/Wechat/Wechat.php @@ -4,15 +4,10 @@ namespace Extend\Wechat; use App\Constants\HttpEnumCode; use App\Exception\BusinessException; -use App\Factory\CacheFactory; -use App\Factory\ProdRedisFactory; use EasyWeChat\Kernel\Exceptions\BadResponseException; use EasyWeChat\Kernel\Exceptions\InvalidArgumentException; use EasyWeChat\Kernel\HttpClient\AccessTokenAwareClient; use EasyWeChat\MiniApp\Application; -use Hyperf\Cache\Cache; -use Hyperf\Redis\Redis; -//use Hyperf\Utils\ApplicationContext; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; use Psr\SimpleCache\CacheInterface; @@ -22,7 +17,6 @@ use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface; use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Hyperf\Context\ApplicationContext; -use Hyperf\Guzzle\CoroutineHandler; /**