Files
xk-api-yii/member/modules/v1/controllers/ImController.php

473 lines
19 KiB
PHP
Raw Normal View History

2024-09-19 11:32:39 +08:00
<?php
namespace member\modules\v1\controllers;
use common\enums\ImMessageSendTypeEnum;
use common\enums\ImSessionStatusEnum;
use common\enums\ImSessionTypeEnum;
use common\enums\OrderAcceptEnum;
use common\enums\SystemNoticeTypeEnum;
use common\forms\ImMessageForm;
use common\helpers\ArrayHelper;
use common\helpers\FuncHelper;
use common\models\ImMessageSession;
use common\models\ImMessageSessionOrder;
use common\models\LeadInfo;
use common\models\Order;
use common\core\BaseAppController;
use common\enums\UserRoleEnum;
use common\models\ImMessage;
use common\models\ServiceUser;
use common\models\SystemNotice;
use common\models\User;
use yii\base\Exception;
/**
* @doc-module Im
*/
class ImController extends BaseAppController
{
public function beforeAction($action)
{
$parent = parent::beforeAction($action); // TODO: Change the autogenerated stub
return $parent;
}
/**
* @doc-name 会话列表
* @doc-return mixed @Lead{id-int-会话id,ImMessageSession{type},name-string-名称,avatar-string-头像,noread_count-int-未读数量,@Last{created_at-int-上次消息时间,created_at_format-string-格式化后的时间,content-string-上次消息}} 导医会话
* @doc-return mixed @Doc{id-int-会话id,ImMessageSession{type},name-string-名称,avatar-string-头像,depart-string-科室,noread_count-int-未读数量,@Last{created_at-int-上次消息时间,created_at_format-string-格式化后的时间,content-string-上次消息}} 医生会话
*/
public function actionSessionList()
{
//导医始终排在最上边 -
//导医用的是最新的会话不管结束未结束给导医发送消息也可以传递to_id和ims_id,不过后台会根据导医会话的状态重新创建会话并进行接入
$leadSessions = ImMessageSession::find()->where([
'user_id' => \Yii::$app->user->identity->id,
'type' => ImSessionTypeEnum::USER_LEAD,
'is_delete' => 0
])->with('serviceUser')->orderBy('id desc')->one();
$leadSessions = $leadSessions ? ArrayHelper::toArray($leadSessions,[
ImMessageSession::class => [
'id',
'type',
'name' => function(){
return '导医消息';
},
'avatar' => 'serviceUser.leadInfo.avatar',
'noread_count' => function($model){
$count = ImMessage::find()->where([
'ims_id' => $model->id,
'read_status' => 0,
'type' => ImMessageSendTypeEnum::SERVICE_SEND,
'is_delete' => 0
])->count();
return $count;
},
'last' => function($model){
$message = ImMessage::find()->where([
'ims_id' => $model->id,
'is_delete' => 0,
])->orderBy('id desc')->one();
if($message){
return [
'created_at' => $message['created_at'],
'created_at_format' => FuncHelper::time_tran($message['created_at']),
'content' => $message['content'],
];
}else{
return [];
}
}
]
]) : [];
//最新的消息排在最上边,不管是谁发送的,不管已读未读
$last = ImMessage::find()->where([
'is_delete' => 0,
])->addSelect('ims_id,MAX(id) as id,max(created_at) as created_at')->groupBy('ims_id')->orderBy('id desc');
$docSessions = ImMessageSession::find()->alias('ims')->select([
'ims.*',
])->addSelect('l.id as last_id,l.created_at as last_time')->where([
'ims.user_id' => \Yii::$app->user->identity->id,
'ims.type' => UserRoleEnum::DOCTOR,
'ims.is_delete' => 0
])->joinWith(['order' => function($q){
$q->alias('o')->andWhere(['<>','o.accept_status',OrderAcceptEnum::NO]);
}])->leftJoin('(' . $last->createCommand()->getRawSql() . ') l', 'ims.id = l.ims_id')
->with('serviceUser')
->orderBy('l.created_at desc,ims.id desc')
->all();
$docSessions = count($docSessions) > 0 ? ArrayHelper::toArray($docSessions,[
ImMessageSession::class => [
'id',
'type',
'name' => 'serviceUser.docInfo.name',
'avatar' => 'serviceUser.docInfo.avatar',
'depart' => 'serviceUser.docInfo.depart.name',
'noread_count' => function($model){
$count = ImMessage::find()->where([
'ims_id' => $model->id,
'read_status' => 0,
'type' => ImMessageSendTypeEnum::SERVICE_SEND,
'is_delete' => 0
])->count();
return $count;
},
'last' => function($model){
$message = ImMessage::findOne($model->last_id);
if($message){
return [
'created_at' => $model->last_time,
'created_at_format' => FuncHelper::time_tran($model->last_time),
'content' => $message->content
];
}else{
return [];
}
}
]
]) : [];
return [
'lead' => $leadSessions,
'doc' => $docSessions
];
}
/**
* @doc-name 清除未读
*/
public function actionClearNoRead()
{
$t=\Yii::$app->db->beginTransaction();
try {
ImMessage::updateAll(['read_status'=>1],[
'user_id' => \Yii::$app->user->identity->id,
'type' => ImMessageSendTypeEnum::SERVICE_SEND,
'read_status' => 0,
'is_delete' => 0
]);
SystemNotice::updateAll(['read_status'=>1],[
'user_id' => \Yii::$app->user->identity->id,
'base_type' =>SystemNoticeTypeEnum::REMINDER,
'scene_type' => 1,
'read_status' => 0,
]);
$t->commit();
return ['清除成功'];
}catch (\Exception $e){
$t->rollBack();
throw $e;
}
}
/**
* @doc-name 会话消息记录
* @doc-param int ims_id 会话id
* @doc-param int page 页码 1 optional
* @doc-param int page_size 每页条数 20 optional
* @doc-return mixed @Session{ImMessageSession{*,@User-mixed-用户信息{name-string-名称,avatar-string-头像},@ServiceUser-mixed-服务人员信息{name-string-名称,avator-string-头像}}} 会话信息
* @doc-return mixed @List{ImMessage{*,@User-mixed-用户信息{name-string-名称,avatar-string-头像},@ServiceUser-mixed-服务人员信息{name-string-名称,avator-string-头像}}} 消息记录
* @doc-return mixed @Pagination{total_count-int-总数量,page_count-int-总页数,current_page-int-当前页,per_page-int-每页条数} 分页数据
*/
public function actionMessageList()
{
$post = \Yii::$app->request->post();
$this->requestValidate($post,[
['ims_id','required']
]);
$imMessageSession = ImMessageSession::find()->with('user','serviceUser')->where([
'id' => $post['ims_id'],
'user_id' => \Yii::$app->user->identity->id,
'is_delete' => 0
])->with('order')->one();
$session = $imMessageSession ? ArrayHelper::toArray($imMessageSession,[
ImMessageSession::class => [
'id','user_id','service_id','type','status','created_at',
'user','order',
'serviceUser' => function($model){
switch($model->type) {
case ImSessionTypeEnum::USER_USER:
$serviceUser = User::findOne($model->service_id);
return [
'name' => $serviceUser->nickname,
'avatar' => $serviceUser->avatarurl,
];
break;
case ImSessionTypeEnum::USER_DOC:
$serviceUser = ServiceUser::find()->where([
'id' => $model->service_id
])->with('docInfo')->one();
return [
'name' => $serviceUser->docInfo->name,
'avatar' => $serviceUser->docInfo->avatar,
];
case ImSessionTypeEnum::USER_LEAD:
$serviceUser = ServiceUser::find()->where([
'id' => $model->service_id
])->with('leadInfo')->one();
return [
'name' => $serviceUser->leadInfo->name,
'avatar' => $serviceUser->leadInfo->avatar,
];
case ImSessionTypeEnum::DOC_SERV:
case ImSessionTypeEnum::DRUG_SERV:
case ImSessionTypeEnum::LEAD_SERV:
//这三种情况member下暂时不会有
break;
}
},
],
User::class => [
'name'=>'nickname','avatar'=>'avatarurl'
],
Order::class => [
'id',
'auto_over_time',
'image_limit_status',
'left_number',
'status' => function($model){
return Order::status_info($model);
},
'accept_status' => function($model){
return Order::accept_info($model);
},
]
]) : [];
$this->extend_result['session'] = $session;
$query = ImMessage::find()->where([
'ims_id' => $post['ims_id'],
'user_id' => \Yii::$app->user->identity->id,
'is_delete' => 0
])->with('user','imSession')->orderBy('id desc');
$this->field = [
ImMessage::class => [
'id','user_id','service_id','content','read_status','type','created_at',
'user',
'serviceUser' => function($model){
switch($model->imSession->type) {
case ImSessionTypeEnum::USER_USER:
$serviceUser = User::findOne($model->service_id);
return [
'name' => $serviceUser->nickname,
'avatar' => $serviceUser->avatarurl,
];
case ImSessionTypeEnum::USER_DOC:
$serviceUser = ServiceUser::find()->where([
'id' => $model->service_id
])->with('docInfo')->one();
return [
'name' => $serviceUser->docInfo->name,
'avatar' => $serviceUser->docInfo->avatar,
];
case ImSessionTypeEnum::USER_LEAD:
$serviceUser = ServiceUser::find()->where([
'id' => $model->service_id
])->with('leadInfo')->one();
return [
'name' => $serviceUser->leadInfo->name,
'avatar' => $serviceUser->leadInfo->avatar,
];
case ImSessionTypeEnum::DOC_SERV:
case ImSessionTypeEnum::DRUG_SERV:
case ImSessionTypeEnum::LEAD_SERV:
//这三种情况member下暂时不会有
break;
}
},
],
User::class => [
'name'=>'nickname','avatar'=>'avatarurl'
],
];
return $this->create($query,$post);
}
/**
* @doc-name 用户端发送消息
* @doc-desc session_type是会话的类型直接取用会话的类型导医第一次可能没有会话id,会话id传递0会话类型直接传递3
* @doc-param int ims_id 会话id,跟导医第一次可能没有会话id,传递0
* @doc-param int session_type 会话类型1跟医生的会话3跟导医的会话
* @doc-param json content 消息内容
* @doc-return int image_limit_status 会话类型1会返回是否限制回复条数1限制0不限制
* @doc-return int left_number 会话类型1会返回剩余条数,限制状态下为0表示回复条数不足不限制状态下为0表示无限制
*/
public function actionMessageSend()
{
//用戶端发送消息
$post = \Yii::$app->request->post();
$this->requestValidate($post,[
[['ims_id','session_type'],'required'],
['session_type','in','range'=>[1,3]],
['content','required','message'=>'消息内容不能为空']
]);
$form = new ImMessageForm();
$form->attributes = $post;
$form->from_id = \Yii::$app->user->identity->id;
switch($post['session_type'])
{
case ImSessionTypeEnum::USER_LEAD:
//导医用的是最新的会话不管结束未结束给导医发送消息也可以传递ims_id,不过后台会根据导医会话的状态重新创建会话并进行接入操作
$query = ImMessageSession::find()->where([
'user_id' => \Yii::$app->user->identity->id,//id 32
'type' => $post['session_type'],
'is_delete' => 0,
'status'=> ImSessionStatusEnum::ING
]);
if($post['ims_id']){
$query->andWhere([
'id' => $post['ims_id']
]);
}
$ims= $query->one();
$lead_id=LeadInfo::getLastLeadUserId();//空闲导医
if(!$ims){ //不要判断!$post['ims_id']否则会添加一堆的会话
$ims = new ImMessageSession();
$ims->user_id = \Yii::$app->user->identity->id;
$ims->type = $post['session_type'];
$ims->saveOrFail();
}
$form->ims_id = $ims->id;
$form->to_id = $ims->service_id;
$form->sendMessage();
return [];
case ImSessionTypeEnum::USER_DOC:
$image_limit_status = 0;
$left_number = 0;
$ims = ImMessageSession::find()->where([
'id' => $post['ims_id'],
'is_delete' => 0
])->with('order')->one();
if(!$ims || !$ims->order){
throw new Exception('会话不存在或者会话订单不存在');
}
$form->to_id = $ims->service_id;
$order = $ims->order;
//检查订单状态
if($order->accept_status == OrderAcceptEnum::WAIT_ACCEPT){
//待接诊状态 - 可以补充回答
$form->sendMessage();
}elseif($order->accept_status == OrderAcceptEnum::ACCEPTING ){
//已接诊状态 - 发送消息 - 扣除相应的条数
$ts = \Yii::$app->db->beginTransaction();
try {
$order = Order::findOne($ims->order->id);
if($order->image_limit_status && $order->left_number <=0){
throw new Exception('回复条数不足');
}
$form->sendMessage();
if($order->image_limit_status){
$order->updateCounters(['left_number' => -1]);
}
$image_limit_status = $order->image_limit_status;
$left_number = $order->left_number;
$ts->commit();
}catch (\Exception $exception){
$ts->rollBack();
throw $exception;
}
}else{
//其他情况-拒绝
throw new Exception('发送失败:订单非待接诊和接诊状态,无法发送消息');
}
return [
'image_limit_status' => $image_limit_status,
'left_number' => $left_number,
];
}
}
/**
* @doc-name 结束会话
* @doc-param int ims_id 会话id
* @doc-param int service_id 服务端id
*/
public function actionOverSession()
{
$post= \Yii::$app->request->post();
$this->requestValidate($post,[
[ ['ims_id','service_id'],'required' ]
]);
$imMessageSession= ImMessageSession::find()->where([
'id'=>$post['ims_id'],
'user_id'=>\Yii::$app->user->identity->getId(),
'service_id'=>$post['service_id'],
'status'=>0
])->one();
if (!$imMessageSession)throw new \yii\db\Exception('聊天消息会话不存在或已结束');
$order_id=ImMessageSessionOrder::find()->select('order_id')->where([
'ims_id'=>$post['ims_id'],
])->column();
$order= Order::find()->where([
'id'=>$order_id,
'user_id'=>\Yii::$app->user->identity->getId(),
'su_id'=>$post['service_id']
])->one();
if (!$order)throw new \yii\db\Exception('订单不存在');
$t=\Yii::$app->db->beginTransaction();
try {
Order::updateAll(['accept_status'=>OrderAcceptEnum::OVER],[
'id'=>$order_id,
'user_id'=>\Yii::$app->user->identity->getId(),
'su_id'=>$post['service_id']
]);
ImMessageSession::updateAll(
['status'=>10],
['id'=>$post['ims_id'],
'user_id'=>\Yii::$app->user->identity->getId(),
'service_id'=>$post['service_id']]);
$t->commit();
}catch (\Exception $e){
$t->rollBack();
throw $e;
}
return ['会话已结束'];
}
}