user->identity->role) { case UserRoleEnum::DOCTOR: $this->types = [ImSessionTypeEnum::USER_DOC]; break; case UserRoleEnum::DRUG: $this->types = [ImSessionTypeEnum::DRUG_SERV]; break; case UserRoleEnum::LEADER: //用户-导师 $this->types = [ImSessionTypeEnum::USER_LEAD];//导医的列表只获取跟用户的聊天,跟客服的聊天单独 break; case UserRoleEnum::SERVICE: //医生-客服,导医-客服,药师-客服 $this->types = [ImSessionTypeEnum::DOC_SERV,ImSessionTypeEnum::LEAD_SERV,ImSessionTypeEnum::DRUG_SERV]; break; default: throw new Exception('参数异常'); break; } return $parent; } /** * 医生和客服 */ /** * 药师和客服 */ /** * 标记已读 */ /** * @doc-name 结束会话 * @doc-param int ims_id 会话id * @doc-param int user_id 用户id */ public function actionOverSession() { $ims_id = \Yii::$app->request->post('ims_id'); $user_id = \Yii::$app->request->post('user_id'); if (!$ims_id)throw new \yii\db\Exception('会话ims_id不能为空'); if (!$user_id)throw new \yii\db\Exception('用户id不能为空'); $imMessageSession= ImMessageSession::find()->where([ 'id'=>$ims_id, 'user_id'=>$user_id, 'service_id'=>\Yii::$app->user->identity->getId(), 'status'=>0 ])->one(); if (!$imMessageSession)throw new \yii\db\Exception('聊天消息会话不存在或已结束'); ImMessageSession::updateAll(['status'=>10], ['id'=>$ims_id, 'user_id'=>$user_id, 'service_id'=>\Yii::$app->user->identity->getId()]); return ['会话已结束']; } /** * @doc-name 导医客服会话列表 * @doc-param string keyword 客户名称或者聊天记录 * @doc-return mixed ImMessageSession{id,type,@User{name-string-名称,avatar-string-头像},noread_count-int-未读数量,@Last{created_at-int-时间,created_at_format-string-格式化时间,content-string-内容}} 会话列表 */ public function actionSessionList() { $post = \Yii::$app->request->post(); $keyword = ArrayHelper::getValue($post,'keyword',''); switch(\Yii::$app->user->identity->role) { case UserRoleEnum::LEADER: //用户-导医 $types = [ImSessionTypeEnum::USER_LEAD]; if($keyword){ $id_arr = User::find()->where(['like','nickname',$keyword])->select('id')->column(); $ims_id_arr = ImMessageSession::find()->where([ 'service_id' => \Yii::$app->user->identity->id, 'user_id' => $id_arr, 'type' => $types, 'status' => ImSessionStatusEnum::ING,//这边只查进行中的 'is_delete' => 0 ])->addSelect('id')->column(); //查询到所有符合的用户昵称的会话 //查询到符合内容的会话,这里的id就是满足查询条件的会话的id - 跟上边是or的关系 $query1 = ImMessage::find()->where([ 'service_id' => \Yii::$app->user->identity->id, 'is_delete' => 0, ]) ->andWhere([ 'or', ['like','content',$keyword], ['ims_id'=>$ims_id_arr] ]) ->addSelect('ims_id,MAX(id) as id,max(created_at) as created_at')->groupBy('ims_id')->orderBy('id desc'); }else{ //最新的消息排在最上边,不管是谁发送的,不管已读未读 $query1 = 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'); } break; case UserRoleEnum::SERVICE: //医生-客服,导医-客服,药师-客服 $types = [ImSessionTypeEnum::DOC_SERV,ImSessionTypeEnum::LEAD_SERV,ImSessionTypeEnum::DRUG_SERV]; if($keyword){ //查询用户昵称 $su_id_arr1 = DoctorInfo::find()->where(['like','name',$keyword])->select('su_id')->column(); $su_id_arr2 = LeadInfo::find()->where(['like','name',$keyword])->select('su_id')->column(); $su_id_arr3 = PharmacistrInfo::find()->where(['like','name',$keyword])->select('su_id')->column(); $su_id_arr = array_merge($su_id_arr1,$su_id_arr2,$su_id_arr3); $ims_id_arr = ImMessageSession::find()->where([ 'service_id' => \Yii::$app->user->identity->id, 'user_id' => $su_id_arr, 'type' => $types, 'status' => ImSessionStatusEnum::ING,//这边只查进行中的 'is_delete' => 0 ])->addSelect('id')->column(); //查询到所有符合的用户昵称的会话 //查询到符合内容的会话,这里的id就是满足查询条件的会话的id - 跟上边是or的关系 $query1 = ImMessage::find()->where([ 'service_id' => \Yii::$app->user->identity->id, 'is_delete' => 0, ])->andWhere([ 'or', ['like','content',$keyword], ['ims_id'=>$ims_id_arr] ])->addSelect('ims_id,MAX(id) as id,max(created_at) as created_at')->groupBy('ims_id')->orderBy('id desc'); }else{ //最新的消息排在最上边,不管是谁发送的,不管已读未读 $query1 = 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'); } break; default: throw new Exception('参数异常'); break; } $sessions_query = ImMessageSession::find()->alias('ims')->select([ 'ims.*', ])->addSelect('l.id as last_id,l.created_at as last_time')->where([ 'ims.service_id' => \Yii::$app->user->identity->id, 'ims.type' => $types, 'ims.status' => ImSessionStatusEnum::ING,//这边只查进行中的 'ims.is_delete' => 0 ]); if($keyword){ $sessions_query->innerJoin('(' . $query1->createCommand()->getRawSql() . ') l', 'ims.id = l.ims_id'); }else{ $sessions_query->leftJoin('(' . $query1->createCommand()->getRawSql() . ') l', 'ims.id = l.ims_id'); }; $sessions = $sessions_query->orderBy('l.created_at desc,ims.id desc')->all(); return count($sessions) ? ArrayHelper::toArray($sessions,[ ImMessageSession::class => [ 'id', 'type', 'user' => function($model){ switch($model->type) { case ImSessionTypeEnum::USER_USER: case ImSessionTypeEnum::USER_DOC: case ImSessionTypeEnum::USER_LEAD: $user = User::findOne($model->user_id); return [ 'name' => $user->nickname, 'avatar' => $user->avatarurl, ]; break; case ImSessionTypeEnum::DOC_SERV: return [ 'name' => $model->serviceUserByUserId->docInfo->name, 'avatar' => $model->serviceUserByUserId->docInfo->name, ]; break; case ImSessionTypeEnum::DRUG_SERV: return [ 'name' => $model->serviceUserByUserId->drugInfo->name, 'avatar' => $model->serviceUserByUserId->drugInfo->avatar, ]; break; case ImSessionTypeEnum::LEAD_SERV: return [ 'name' => $model->serviceUserByUserId->leadInfo->name, 'avatar' => $model->serviceUserByUserId->leadInfo->avatar, ]; break; } }, 'noread_count' => function($model){ $count = ImMessage::find()->where([ 'ims_id' => $model->id, 'read_status' => 0, 'type' => ImMessageSendTypeEnum::USER_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 []; } } ] ]) : []; } /** * @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'], 'service_id' => \Yii::$app->user->identity->id, ])->with('order')->one(); $session = $imMessageSession ? ArrayHelper::toArray($imMessageSession,[ ImMessageSession::class => [ 'id','user_id','service_id','type','status','created_at', 'order', 'user' => function($model){ switch($model->type) { // case ImSessionTypeEnum::USER_USER: case ImSessionTypeEnum::USER_DOC: case ImSessionTypeEnum::USER_LEAD: return [ 'name' => $model->user->nickname, 'avatar' => $model->user->avatarurl, ]; break; case ImSessionTypeEnum::DOC_SERV: return [ 'name' => $model->serviceUserByUserId->docInfo->name, 'avatar' => $model->serviceUserByUserId->docInfo->avatar, ]; break; case ImSessionTypeEnum::DRUG_SERV: return [ 'name' => $model->serviceUserByUserId->drugInfo->name, 'avatar' => $model->serviceUserByUserId->drugInfo->avatar, ]; break; case ImSessionTypeEnum::LEAD_SERV: return [ 'name' => $model->serviceUserByUserId->leadInfo->name, 'avatar' => $model->serviceUserByUserId->leadInfo->avatar, ]; break; } }, 'serviceUser' => function($model){ switch($model->type) { // case ImSessionTypeEnum::USER_USER: case ImSessionTypeEnum::USER_DOC: return [ 'name' => $model->serviceUser->docInfo->name, 'avatar' => $model->serviceUser->docInfo->avatar, ]; break; case ImSessionTypeEnum::USER_LEAD: return [ 'name' => $model->serviceUser->leadInfo->name, 'avatar' => $model->serviceUser->leadInfo->avatar, ]; break; case ImSessionTypeEnum::DOC_SERV: case ImSessionTypeEnum::DRUG_SERV: case ImSessionTypeEnum::LEAD_SERV: return [ 'name' => $model->serviceUser->servInfo->name, 'avatar' => $model->serviceUser->servInfo->avatar, ]; break; } } ], 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'], 'service_id' => \Yii::$app->user->identity->id, 'is_delete' => 0 ])->with('imSession','user','serviceUser')->orderBy('id desc'); $this->field = [ ImMessage::class => [ 'id','user_id','service_id','content','read_status','type','created_at', 'user' => function($model){ switch($model->imSession->type) { // case ImSessionTypeEnum::USER_USER: case ImSessionTypeEnum::USER_DOC: case ImSessionTypeEnum::USER_LEAD: return [ 'name' => $model->user->nickname, 'avatar' => $model->user->avatarurl, ]; break; case ImSessionTypeEnum::DOC_SERV: return [ 'name' => $model->serviceUserByUserId->docInfo->name, 'avatar' => $model->serviceUserByUserId->docInfo->avatar, ]; break; case ImSessionTypeEnum::DRUG_SERV: return [ 'name' => $model->serviceUserByUserId->drugInfo->name, 'avatar' => $model->serviceUserByUserId->drugInfo->avatar, ]; break; case ImSessionTypeEnum::LEAD_SERV: return [ 'name' => $model->serviceUserByUserId->leadInfo->name, 'avatar' => $model->serviceUserByUserId->leadInfo->avatar, ]; break; } }, 'serviceUser' => function($model){ switch($model->imSession->type) { // case ImSessionTypeEnum::USER_USER: case ImSessionTypeEnum::USER_DOC: return [ 'name' => $model->serviceUser->docInfo->name, 'avatar' => $model->serviceUser->docInfo->avatar, ]; break; case ImSessionTypeEnum::USER_LEAD: return [ 'name' => $model->serviceUser->leadInfo->name, 'avatar' => $model->serviceUser->leadInfo->avatar, ]; break; case ImSessionTypeEnum::DOC_SERV: case ImSessionTypeEnum::DRUG_SERV: case ImSessionTypeEnum::LEAD_SERV: return [ 'name' => $model->serviceUser->servInfo->name, 'avatar' => $model->serviceUser->servInfo->avatar, ]; break; } } ], ]; return $this->create($query,$post); } /** * @doc-name 待接入会话列表 * @doc-return mixed ImMessageSession{id,@User{name,avatar},@Last{content-string-消息内容,created_at-int-消息时间,created_at_format-string-格式后的时间}} 待接入会话列表 */ public function actionWaitInList() { //这个就按最新的待接入会话在最上边 $query = ImMessageSession::find()->where([ 'service_id' => 0, 'type' => $this->types, 'status' => ImSessionStatusEnum::ING ])->orderBy('id desc'); $sessions = $query->with('user','serviceUser')->all(); return count($sessions) ? ArrayHelper::toArray($sessions,[ ImMessageSession::class => [ 'id' => 'id', 'user' => function($model){ switch($model->type) { case ImSessionTypeEnum::USER_USER: case ImSessionTypeEnum::USER_DOC: case ImSessionTypeEnum::USER_LEAD: return [ 'name' => $model->user->nickname, 'avatar' => $model->user->avatarurl, ]; break; case ImSessionTypeEnum::DOC_SERV: return [ 'name' => $model->serviceUserByUserId->docInfo->name, 'avatar' => $model->serviceUserByUserId->docInfo->avatar, ]; break; case ImSessionTypeEnum::DRUG_SERV: return [ 'name' => $model->serviceUserByUserId->drugInfo->name, 'avatar' => $model->serviceUserByUserId->drugInfo->avatar, ]; break; case ImSessionTypeEnum::LEAD_SERV: return [ 'name' => $model->serviceUserByUserId->leadInfo->name, 'avatar' => $model->serviceUserByUserId->leadInfo->avatar, ]; break; } }, 'last' => function($model){ $message = ImMessage::find()->where([ 'ims_id' => $model->id, 'user_id' => $model->user_id, 'is_delete' => 0 ])->orderBy('id desc')->one(); if($message){ return [ 'content' => $message->content, 'created_at' => $message->created_at, 'created_at_format' => FuncHelper::time_tran($message->created_at) ]; }else{ return []; } } ] ]) : []; } /** * @doc-name 接入会话 * @doc-param ims_id 会话id */ public function actionSessionIn() { $post = \Yii::$app->request->post(); $this->requestValidate($post,[ ['ims_id','required'] ]); $model = ImMessageSession::find()->where([ 'id' => $post['ims_id'], 'type' => $this->types, 'service_id' => 0, 'status' => ImSessionStatusEnum::ING ])->one(); if(!$model){ throw new Exception('待接入会话不存在'); } $count = ImMessageSession::updateAll(['service_id'=>\Yii::$app->user->identity->id,'in_time'=>time()],[ 'id' => $post['ims_id'], 'type' => $this->types, 'service_id' => 0, 'status' => ImSessionStatusEnum::ING ]); if(!$count){ throw new Exception('接入失败'); } ImMessage::updateAll(['service_id'=>\Yii::$app->user->identity->id],[ 'ims_id' => $post['ims_id'] ]); //这里可以给用户发一个已接入的提醒 //这里进行接入的消息发送 $form = new ImMessageForm(); $form->sessionIn($post['ims_id'],0,\Yii::$app->user->identity->role,[ 'type' => 'session-in' //定义的类型是接入 ]); return []; } /** * @doc-name 服务端发送消息 * @doc-desc session_type直接传递用会话返回的会话类型,如果是医生药师导医端和客服的会话,第一次可能没有会话id,则直接会话id=0,会话类型当前角色+4客服 = 567,否则直接传递会话id和会话类型,客服现在只能接入医生药师导医的会话,所以会有会话id和session_type * @doc-param int ims_id 会话id * @doc-param int session_type 会话类型1医生发给用户3导医发给用户5医生和客服会话6药师和客服7导医和客服 * @doc-param json content 消息内容 */ public function actionMessageSend() { //服务端发送消息 $post = \Yii::$app->request->post(); $this->requestValidate($post,[ [['ims_id','session_type'],'required'], ['content','required','message'=>'消息内容不能为空'] ]); $form = new ImMessageForm(); $form->attributes = $post; $form->from_id = \Yii::$app->user->identity->id; switch($post['session_type']) { case ImSessionTypeEnum::USER_DOC: //医生给用户发消息 $form->type = ImMessageSendTypeEnum::SERVICE_SEND; $ims = ImMessageSession::find()->where([ 'id' => $post['ims_id'], 'is_delete' => 0 ])->with('order')->one(); if(!$ims || !$ims->order){ throw new Exception('会话不存在或者会话订单不存在'); } $order = $ims->order; $form->to_id = $ims->user_id; if($order->accept_status == OrderAcceptEnum::ACCEPTING ){ $form->sendMessage(); }else{ //其他情况-拒绝 throw new Exception('发送失败:订单非接诊状态,无法发送消息'); } return []; break; case ImSessionTypeEnum::USER_LEAD: //导医给用户发消息 - 如果已经结束,则不能再发送 - 在下一步有判断 $form->type = ImMessageSendTypeEnum::SERVICE_SEND; $ims = ImMessageSession::find()->where([ 'id' => $post['ims_id'], 'service_id' => \Yii::$app->user->identity->id, 'type' => $post['session_type'], 'is_delete' => 0, 'status' => ImSessionStatusEnum::ING ])->one(); if(!$ims){ throw new Exception('会话不存在'); } $form->to_id = $ims->user_id; $form->sendMessage(); break; case ImSessionTypeEnum::DOC_SERV://有可能是医生给客服发,也可能是客服给医生发 - 取决于当前的角色 if(\Yii::$app->user->identity->role == UserRoleEnum::DOCTOR){//医生给客服发,当前医生相当于user_id,客服相当与service_id $form->type = ImMessageSendTypeEnum::USER_SEND; $query = ImMessageSession::find()->where([ 'user_id' => \Yii::$app->user->identity->id, 'type' => $post['session_type'], 'is_delete' => 0, 'status' => ImSessionStatusEnum::ING ]); if($post['ims_id']){ $query->andWhere([ 'id' => $post['ims_id'] ]); } $ims = $query->one(); if(!$ims){ $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(); }elseif(\Yii::$app->user->identity->role == UserRoleEnum::SERVICE){//客服给医生发 $form->type = ImMessageSendTypeEnum::SERVICE_SEND; $ims = ImMessageSession::find()->where([ 'id' => $post['ims_id'], 'service_id' => \Yii::$app->user->identity->id, 'type' => $post['session_type'], 'is_delete' => 0, 'status' => ImSessionStatusEnum::ING ])->one(); $form->to_id = $ims->user_id; $form->sendMessage(); }else{ throw new Exception('客户端传递参数错误'); } break; case ImSessionTypeEnum::LEAD_SERV://有可能是导医给客服发,也可能是客服给导医发 if(\Yii::$app->user->identity->role == UserRoleEnum::LEADER){//导师给客服发,当前导师相当于user_id,客服相当与service_id $form->type = ImMessageSendTypeEnum::USER_SEND; $query = ImMessageSession::find()->where([ 'user_id' => \Yii::$app->user->identity->id, 'type' => $post['session_type'], 'is_delete' => 0, 'status' => ImSessionStatusEnum::ING ]); if($post['ims_id']){ $query->andWhere([ 'id' => $post['ims_id'] ]); } $ims = $query->one(); if(!$ims){ $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(); }elseif(\Yii::$app->user->identity->role == UserRoleEnum::SERVICE){//客服给导师发 $form->type = ImMessageSendTypeEnum::SERVICE_SEND; $ims = ImMessageSession::find()->where([ 'id' => $post['ims_id'], 'service_id' => \Yii::$app->user->identity->id, 'type' => $post['session_type'], 'is_delete' => 0, 'status' => ImSessionStatusEnum::ING ])->one(); $form->to_id = $ims->user_id; $form->sendMessage(); }else{ throw new Exception('客户端传递参数错误'); } break; case ImSessionTypeEnum::DRUG_SERV://有可能是药师给客服发,也可能是客服给药师发 if(\Yii::$app->user->identity->role == UserRoleEnum::DRUG){//药师给客服发 $form->type = ImMessageSendTypeEnum::USER_SEND; $query = ImMessageSession::find()->where([ 'user_id' => \Yii::$app->user->identity->id, 'type' => $post['session_type'], 'is_delete' => 0, 'status' => ImSessionStatusEnum::ING ]); if($post['ims_id']){ $query->andWhere([ 'id' => $post['ims_id'] ]); } $ims = $query->one(); if(!$ims){ $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(); }elseif(\Yii::$app->user->identity->role == UserRoleEnum::SERVICE){//客服给药师发 $form->type = ImMessageSendTypeEnum::SERVICE_SEND; $ims = ImMessageSession::find()->where([ 'id' => $post['ims_id'], 'service_id' => \Yii::$app->user->identity->id, 'type' => $post['session_type'], 'is_delete' => 0, 'status' => ImSessionStatusEnum::ING ])->one(); $form->to_id = $ims->user_id; $form->sendMessage(); }else{ throw new Exception('客户端传递参数错误'); } break; } return []; } }