上一章讲了后台部署部分
https://blog.csdn.net/weixin_41987365/article/details/129047493?spm=1001.2014.3001.5502
这一回讲后端接口部分,直接贴代码了,相信大家都看得懂
<?php
namespace app\api\controller;
use app\api\enum\Communication;
use app\common\controller\Api;
use app\api\service\Token;
use app\Request;
use think\exception\HttpException;
use app\api\enum\User as UserEnum;
use app\api\model\User as UserModel;
use app\api\model\Communication as CommunicationModel;
use app\api\enum\Communication as CommunicationEnum;
use app\api\service\Token as TokenService;
use app\common\controller\JsonResult;
use think\cache\driver\Redis;
use think\facade\Cache;
use think\facade\Config;
use think\Controller;
// require_once '/vendor/GatewayWork/vendor/workerman/gateway-worker/src/Lib/Gateway.php';
// use GatewayWorker\Lib\Gateway;
use GatewayClient\Gateway;
// require_once __DIR__."/Protocols/GatewayProtocol.php";
// require_once __DIR__."/Lib/Gateway.php";
class Chat extends Controller
{
/**
* 根据用户id查询用户姓名
*/
public function getIdName($uid){
$res = UserModel::getIdName($uid);
return $res;
}
/**
* 根据用户id获取聊天双方头像信息
*/
public function getHeadImg(){
if (request()->isPost()){
$res = UserModel::getHeadImg(input('post.'));
return JsonResult::jsonSuccess($res,"ok",200);
}
throw new HttpException(404,"非法请求");
}
/**
* 通过id获取单个用户昵称
*/
public function getNickName(){
if (request()->isPost()){
$res = UserModel::getNickName(input('post.toid'));
return JsonResult::jsonSuccess($res,"ok",200);
}
throw new HttpException(404,"非法请求");
}
/**
* 通过聊天双方id获取聊天记录
*/
public function messageLoad(){
if (request()->isPost()){
$res = CommunicationModel::messageLoad(input('post.'));
return JsonResult::jsonSuccess($res,"ok",200);
}
throw new HttpException(404,"非法请求");
}
/**
* 上传图片,返回图片地址
*/
public function uploadImg(){
if (request()->isPost()){
//获取表单上传文件
$file = request()->file('image');
$suffix = substr(strrchr($file->getOriginalName(), "."), 1); // 文件后缀
if(!in_array($suffix, config('upload.suffix_arr.image'))){
throw new HttpException(404,"请上传格式为'".json(',',['jpg','jpeg','png','gif'])."'的文件");
}
if($file->getSize() > config('upload.size_arr.image')){ // 最大上传10M
throw new HttpException(404,"上传的文件大小不能超过10M");
}
//上传文件到本地服务器
$filename = \think\facade\Filesystem::disk('public')->putFile('', $file);
if ($filename){
// 上传成功 路径存入数据库
$name = str_replace("\\","/",'/uploads/'.$filename);
$data = [
'content' => config('upload.suffix_http').$name ,
'fromid' => input('fromid'),
'toid' => input('toid'),
'fromname' => $this->getIdName(input('fromid')),
'toname' => $this->getIdName(input('toid')),
'time' => time(),
// 'isread' => input('online') == 1 ? Communication::read : Communication::uread,
'isread' => Communication::uread,
'type' => CommunicationEnum::image
];
$insert = CommunicationModel::insert($data);
if($insert){
return show(config('status.success'),"ok",['img_name'=>config('upload.suffix_http').$name],200);
}
throw new HttpException(404,"发送失败,图片路径保存失败!");
}else{
throw new HttpException(404,"文件上传失败");
}
}
throw new HttpException(404,"非法请求");
}
/**
* 根据uid获取当前用户聊天列表
*/
public function getIdList(){
if(request()->post()){
// $token = request()->header('token');
// TokenService::verifyToken($token);
$res = CommunicationModel::getIdList(input('post.id'));
$allNoRead = CommunicationModel::getCountAllNoRead(input('post.id'));
$data=[
'list'=>$res,
'allNoRead'=>$allNoRead
];
if (sizeof($res) > 0) {
return JsonResult::jsonSuccess($data,"ok",200);
} else {
throw new HttpException(200, "当前没有对话列表");
}
}
throw new HttpException(404,"非法请求");
}
/**
* 通过消息id标记当前消息已读
*/
public function isRead(){
if(request()->post()){
// $token = request()->header('token');
// TokenService::verifyToken($token);
$res = CommunicationModel::isRead(input('post.'));
return JsonResult::jsonSuccess($res,"ok",200);;
// if ($res > 0) {
// return show(config('status.success'), "ok", $res, 200);
// } else {
// throw new HttpException(200, "标记已读失败");
//}
}
throw new HttpException(404,"非法请求");
}
public function bind(){
$message =input('post.');
//客户端发送的数据
// $message_data = json_decode($message);
// if(!$message_data){
// return false;
// }
$client_id = $message['client_id'];
$userId = $message['userid'];
if(!$userId){
return false;
}
// $cid = Gateway::getClientIdByUid($userId);
// if ($cid) return show('200','用户已经绑定',$cid);
// 验证client_id合法性
if (!Gateway::isOnline($client_id)) return JsonResult::jsonFailed('','client_id错误',400);
// 验证当前客户端是否已经绑定
$uid = Gateway::getUidByClientId($client_id);
if ($uid) return JsonResult::jsonFailed($uid,'已经绑定',400);
// 直接绑定
Gateway::bindUid($client_id,$userId);
// 返回成功
return JsonResult::jsonSuccess(['type'=>'bind','status'=>true],"绑定成功",200);
}
public function send(){
// 1. 验证数据是否合法
// 2. 组织数据
$message = input('post.');
$data = $this->resdata($message);
$to_id = $data['to_id'];
$datas = [
'fromid' => $message['fromid'],
'fromname' => $this->getIdName($message['fromid']),
'toid' => $message['toid'],
'toname' => $this->getIdName($message['toid']),
'content' => $message['data'],
'time' => time(),
'isread' => CommunicationEnum::uread,
'type' => UserEnum::type
];
// 3. 验证对方用户是否在线
if (Gateway::isUidOnline($to_id)) {
// 直接发送
Gateway::sendToUid($to_id,json_encode($data));
// 写入数据库
CommunicationModel::add($datas);
// 返回发送成功
return JsonResult::jsonSuccess(['在线,发送成功'],'ok',200);
}else{
// 写入数据库
CommunicationModel::add($datas);
return JsonResult::jsonSuccess(['对方离线,发送成功'],'ok',200);
}
// else{
// // 不在线,写入消息队列
// // 获取之前消息
// // $redis = new Redis(Config::get('userchat_'.$to_id));
// $redis = new Redis(Config::get('cache.stores.redis'));
// $save_data = $redis->get('userchat_'.$to_id);
// if (!$save_data || !is_array($save_data)) $save_data = [];
// $save_data[] = $datas;
// // 写入数据库
// // 写入消息队列(含id)
// $redis->set('userchat_'.$to_id,$save_data);
// return show(400,'ok',$redis->get('userchat_'.$to_id));
// }
}
// 组织数据
public function resdata($request){
return [
'to_id'=>$request['toid'],
'from_id'=>$request['fromid'],
'data'=>$this->checkWords($request['data']),
'user_pic'=> UserModel::getHeadOne($request['fromid']),
'user_name'=>UserModel::getNickName($request['fromid']),
'type'=>$request['type'],
'time'=>time()
];
}
}
而在events.php里,基本不做任何修改,只需要在连接成功时,返回client_id
class Events
{
/**
* 当客户端连接时触发
* 如果业务不需此回调可以删除onConnect
*
* @param int $client_id 连接id
*/
public static function onConnect($client_id)
{
// 向当前client_id发送数据
$data=[
'type'=>'bind',
'client_id'=>$client_id
];
Gateway::sendToClient($client_id,json_encode($data));
}
/**
* 当客户端发来消息时触发
* @param int $client_id 连接id
* @param mixed $message 具体消息
*/
public static function onMessage($client_id, $message)
{
}
/**
* 当用户断开连接时触发
* @param int $client_id 连接id
*/
public static function onClose($client_id)
{
}