初始化代码

This commit is contained in:
2025-12-22 14:32:54 +08:00
parent e27ab90d9f
commit d02b31a8b9
1459 changed files with 240973 additions and 0 deletions

212
app/im/TLSSigAPIv2.php Normal file
View File

@@ -0,0 +1,212 @@
<?php
namespace Tencent;
if (version_compare(PHP_VERSION, '5.1.2') < 0) {
trigger_error('need php 5.1.2 or newer', E_USER_ERROR);
}
class TLSSigAPIv2 {
private $key = false;
private $sdkappid = 0;
public function __construct($sdkappid, $key) {
$this->sdkappid = $sdkappid;
$this->key = $key;
}
/**
* 用于 url 的 base64 encode
* '+' => '*', '/' => '-', '=' => '_'
* @param string $string 需要编码的数据
* @return string 编码后的base64串失败返回false
* @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
*/
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;
}
/**
* 使用 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
*/
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
*/
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 $identifier 用户账号
* @param int $expire 过期时间,单位秒,默认 180 天
* @return string 签名字符串
* @throws \Exception
*/
public function genSig($identifier, $expire=86400*180) {
return $this->__genSig($identifier, $expire, '', false);
}
/**
* 带 userbuf 生成签名。
* @param $identifier 用户账号
* @param int $expire 过期时间,单位秒,默认 180 天
* @param string $userbuf 用户数据
* @return string 签名字符串
* @throws \Exception
*/
public function genSigWithUserBuf($identifier, $expire, $userbuf) {
return $this->__genSig($identifier, $expire, $userbuf, true);
}
/**
* 验证签名。
*
* @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
*/
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
*/
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
*/
public function verifySigWithUserBuf($sig, $identifier, &$init_time, &$expire_time, &$userbuf, &$error_msg) {
return $this->__verifySig($sig, $identifier, $init_time, $expire_time, $userbuf, $error_msg);
}
}

112
app/im/common.php Normal file
View File

@@ -0,0 +1,112 @@
<?php
// 这是系统自动生成的im应用公共文件
use app\im\model\ImUser;
use app\im\model\ImChat;
//获取用户缓存
function getCacheUser($user_id ,$uniacid = '7777')
{
$key = 'longbing_card_user_' . $user_id;
if(!hasCache($key ,$uniacid)) return null;
return getCache($key ,$uniacid);
}
//设置用户缓存数据
function setCacheUser($user_id ,$value ,$uniacid = '7777')
{
$key = 'longbing_card_user_' . $user_id;
return setCache ( $key, $value, 3600, $uniacid);
}
//获取用户信息
function getUser($user_id ,$uniacid ='7777')
{
//判断缓存是否存在
$user = getCacheUser($user_id ,$uniacid);
if(!empty($user)) return $user;
//生成查询类
$user_model = new ImUser();
//获取数据
$user = $user_model->getUser(['id' => $user_id ,'uniacid' => $uniacid]);
if(empty($user)) return null;
setCacheUser($user_id ,$user ,3600,$uniacid);
return $user;
}
////返回数据处理
//function getWxApiReturnData($result)
//{
// if(isset($result['data']['page'])) $result['data']['current_page'] = $result['data']['page'];unset($result['data']['page']);
// if(isset($result['data']['page_count'])) $result['data']['current_page'] = $result['data']['page_count'];unset($result['data']['page_count']);
// if(isset($result['data']['total'])) $result['data']['current_page'] = $result['data']['total'];unset($result['data']['total']);
// if(isset($result['data']['total_page'])) $result['data']['current_page'] = $result['data']['total_page'];unset($result['data']['total_page']);
// return $result;
//}
//获取chat
function longbingGetChatById($chat_id ,$uniacid)
{
//设置key
$key = 'longbing_card_chat_new_' . $chat_id;
//从缓存中获取数据
$chat = getCache($key ,$uniacid);
//判断缓存数据是否存在
if(empty($chat))
{
//生成chat操作模型
$chat_model = new ImChat();
//获取数据
$chat = $chat_model->getChatById($chat_id);
if(!empty($chat)) setCache($key ,$chat ,$uniacid);
}
return $chat;
}
//获取chat
function longbingGetChat($user_id ,$customer_id ,$uniacid = 7777 ,$is_create = true)
{
//判断用户和客户是否是同一人
if(empty($user_id) || empty($customer_id) || in_array($user_id, [$customer_id])) return false;
//查找数据
$chat_model = new ImChat();
$chat = $chat_model->getChat($user_id ,$customer_id ,$uniacid);
if(isset($chat['id'])){
$key = 'longbing_card_chat_new_' . $chat['id'];
setCache($key ,$chat ,$uniacid);
}
//如果数据不存在
if(empty($chat) && $is_create){
//判断用户是否存在
$user = longbingGetUser($user_id ,$uniacid);
if(empty($user)) return false;
//判断客户是否存在
$customer = longbingGetUser($customer_id ,$uniacid);
if(empty($customer)) return false;
//生成chat数据
$chat_data = array(
'user_id' => $user_id,
'target_id' => $customer_id,
'uniacid' => $uniacid
);
if($chat_model->createChat($chat_data)){
$chat = longbingGetChat($user_id ,$customer_id ,$uniacid);
}
}
if(isset($chat['chat_id'])) $chat['id'] = $chat['chat_id'];
return $chat;
}
/**
* 腾讯聊天签名方法
*
* @param $sdkappid
* @param $key
* @param $user_id
* @return mixed
* @author shuixian
* @DataTime: 2019/12/10 11:29
*/
function longbing_publics_tim_genSig($sdkappid, $key,$user_id){
require_once 'TLSSigAPIv2.php';
$TLSSigAPIv2 = new \Tencent\TLSSigAPIv2($sdkappid, $key);
return $TLSSigAPIv2->genSig($user_id);
}

View File

@@ -0,0 +1,50 @@
<?php
// +----------------------------------------------------------------------
// | Longbing [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright Chengdu longbing Technology Co., Ltd.
// +----------------------------------------------------------------------
// | Website http://longbing.org/
// +----------------------------------------------------------------------
// | Sales manager: +86-13558882532 / +86-13330887474
// | Technical support: +86-15680635005
// | After-sale service: +86-17361005938
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\im\controller;
class BaseMessage
{
/**
* @param $server
* @param $client_id
* @param $action
* @param bool $status
* @param string $message
* @param array $data
* @功能说明:发送消息方式
* @author jingshuixian
* @DataTime: 2020/1/13 13:53
*/
public function sendServerMsg($server, $client_id , $action , $status = true, $message = '' , $data = []){
$dataStr = json_encode(
[
'action' => $action ,
'status' => $status ,
'message'=> $message ,
'data' => $data,
'time' => time()
]
);
$server->push($client_id , $dataStr) ;
}
}

178
app/im/controller/Car.php Normal file
View File

@@ -0,0 +1,178 @@
<?php
//include 'crc.php';
//include 'net.php';
//打印十六进制(可以不用)
function println($bytes) {
for($i=0;$i<count($bytes);$i++)
{
printf("%02X ", $bytes[$i]);
}
printf(".");
}
//这里开始
//$net = new net();
$socket = listen('0.0.0.0', 50000);
while(true) {
$cs = accept($socket);
printf($cs);
while($cs) {
try{
$ret = recv_bytes($cs, 1024);
abc($ret);
//println($ret);
}
catch (Exception $e)
{
close();
printf('cs close');
break;
}
}
}
close();
function listen($ip, $port)
{
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, $ip, $port);
$ex = socket_listen($socket, 4);
//socket_bind($this->socket, '127.0.0.1', $port) or die("socket_bind() fail:" . socket_strerror(socket_last_error()) . "/n");
//$ex = socket_listen($this->socket, 4) or die("socket_listen() fail:" . socket_strerror(socket_last_error()) . "/n");
// return $ex;
return $socket;
}
//abc处理读取到的卡4字节
function abc($ret)
{
$len = $ret[4];
if($len < 14)
{
//printf('无效数据');
return ;
}
//
$count = $ret[9];
$count = ($count - 3) / 4;
//
for($i=0; $i<$count; $i++)
{
$idx = 10 + ($i * 4);
$card = sprintf("%02X%02X%02X%02X", $ret[$idx+0], $ret[$idx+1], $ret[$idx+2], $ret[$idx+3]);//这是获取到的卡数据(按文档意思可能会读到多张卡,处理这个$card就可以了
$card = sprintf("%02X%02X%02X", $ret[$idx+0], $ret[$idx+1], $ret[$idx+2]);//这是获取到的卡数据(按文档意思可能会读到多张卡,处理这个$card就可以了
printf('card['.$i.']>>'.$card.' | ');
// $post_data['data'] = 'card['.$i.']>>'.$card.' | ';
$card_id = $card;
$card = 'card['.$i.']>>'.$card.' | ';
$url = 'https://car.cncnconnect.com/massage/admin/Tcp/getInfo?card_id='.$card_id.'&time='.msectime();
$a = file_get_contents($url);
// printf(json_encode($a));
}
}
function msectime() {
list($msec,$sec) = explode(' ', microtime());
$msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
return $msectime;
}
function crulGetData($url, $post, $method, $header=1){
// $this->_errno = NULL;
// $this->_error = NULL;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if($post != NULL)
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true);
curl_setopt($ch, CURLOPT_AUTOREFERER,true);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
if($header)
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-type: application/json',
)
);
$result = curl_exec($ch);
return $result;
}
function accept($socket)
{
return socket_accept($socket);
}
function close()
{
if($this->socket == 0) return;
socket_close($this->socket);
$this->socket = 0;
}
function recv_bytes($cs, $len = 1024)
{
$ret = recv($cs, $len);
$bytes = string_to_bytes($ret);
return $bytes;
}
function recv($cs, $len = 1024)
{
$ret = socket_read($cs, $len) or die("/n");
return $ret;
}
function string_to_bytes($str)
{
$bytes = array();
for($i=0; $i<strlen($str); $i++)
{
$bytes[] = ord($str[$i]);
}
return $bytes;
}
?>

624
app/im/controller/Im.php Normal file
View File

@@ -0,0 +1,624 @@
<?php
namespace app\im\controller;
use app\ApiRest;
use app\Common\service\LongbingUserInfoService;
use app\im\model\ImMessageFriend;
use app\im\service\ImMessageFriendService;
use app\im\service\ImService;
use longbingcore\tools\LongbingDefault;
use longbingcore\tools\LongbingTime;
use think\App;
use think\Request;
use app\im\model\ImChart;
use app\im\model\ImChat;
use app\im\model\ImMessage;
use app\im\model\ImUser;
use app\im\model\ImMyReply;
use app\im\model\ImReplyType;
use app\card\model\UserInfo;
use app\card\model\UserPhone;
use app\im\model\ImClient;
class Im extends ApiRest
{
public $user_id = null;
public $user = null;
public function __construct(App $app) {
parent::__construct($app);
$this->user_id = $this->getUserId();
$this->user = $this->getUserInfo();
}
//获取客户列表
public function listCustomer()
{
//获取参数列表
$param = $this->_param;
//获取用户列表
$user_id = $this->user_id;
//判断用户是否存在
if(empty($user_id)) return $this->error('not login ,please login again.');
//生成分页信息
$page_config = array(
'page' => 1,
'page_count' => 10
);
//获取分页信息
if(isset($param['page']) && $param['page'] > 0) $page_config['page'] = $param['page'];
if(isset($param['page_count']) && $param['page_count'] > 0) $page_config['page_count'] = $param['page_count'];
//生成查询模型
$chat_model = new ImChat();
//生成消息查询模型
$message_model = new ImMessage();
//生成用户查询模型
// $user_model = new ImUser();
//生成查询
$page_config['total'] = $chat_model->listChatCount($user_id ,$this->_uniacid );
$chats = $chat_model->listChat($user_id ,$this->_uniacid ,$page_config);
$data = [];
if(!empty($chats))
{
foreach($chats as $key => $value)
{
//获取客户信息
$customer_id = null;
if(!in_array($value['user_id'], [$user_id])) $customer_id = $value['user_id'];
if(!in_array($value['target_id'], [$user_id])) $customer_id = $value['target_id'];
if(empty($customer_id)) continue;
//获取客户信息
// $value['customer'] = $user_model->getUser(['id' => $customer_id]);
$customer = longbingGetUser($customer_id ,$this->_uniacid);
if(!empty($customer['is_staff']))
{
$customer_info = longbingGetUserInfo($customer_id ,$this->_uniacid);
if(isset($customer_info['is_staff']) && !empty($customer_info['is_staff']))
{
if(!empty($customer_info['avatar'])) {
$customer_info = transImagesOne($customer_info ,['avatar'] ,$this->_uniacid);
}
//是员工 就用员工头像 By.jingshuixian
//if(!empty($customer_info['avatar'])) $customer['avatarUrl'] = $customer_info['avatar'];
}
}
$value['customer'] = $customer;
if(empty($value['customer'])) continue;
//获取最后一条消息
$lastmessage = $message_model->lastMessage(['chat_id' => $value['id']]);
//如果最后一条消息是图片
if(isset($lastmessage['message_type']) && !in_array($lastmessage['message_type'], ['text' ])) $lastmessage['content'] = lang($lastmessage['message_type']);
$value['lastmessage'] = $lastmessage;
//获取未读消息总数
$not_rear_message_count = $message_model->listMessageCount(['chat_id' => $value['id'] ,'user_id' => $customer_id ,'target_id' => $user_id ,'status' => 1]);
//未读消息总数
$value['not_read_message_count'] = $not_rear_message_count;
//获取时间
if(isset($value['update_time']) && !empty($value['update_time'])) $value['time'] = date('Y-m-d H:i:s', $value['update_time']);
//判断用户是否存在头像
if(!isset($value['customer']['avatarUrl']) || empty($value['customer']['avatarUrl'])) $value['customer']['avatarUrl'] = $this->defaultImage['avatar'];
//判断客户是否是员工
if(isset($value['customer']['is_staff']) && !empty($value['customer']['is_staff']))
{
//获取员工信息
$user_info = longbingGetUserInfo($customer_id ,$this->_uniacid);
if(isset($user_info['is_staff']) && !empty($user_info['is_staff']) && isset($user_info['name']) && !empty($user_info['name'])){
$value['customer']['nickName'] = $user_info['name'];
}
}
$data[] = $value;
}
}
$page_config['total_page'] = (int)($page_config['total'] / $page_config['page_count']);
if(($page_config['total'] % $page_config['page_count']) > 0) $page_config['total_page'] = $page_config['total_page'] + 1;
$result = $page_config;
$result['data'] = $data;
//总计未读数
$result['unReadMessageCount'] = ImService::getUnReadMessageCount($this->user_id);
//数据处理
return $this->success($result);
}
/**
* @author jingshuixian
* @DataTime: 2020/1/16 15:58
* @功能说明:新版获取用户列表信息
*/
public function listCustomerV2(){
//获取参数列表
$param = $this->_param;
//获取用户列表
$user_id = $this->user_id;
//判断用户是否存在
if(empty($user_id)) return $this->error('not login ,please login again.');
//初始化朋友列表,兼容老数据
ImMessageFriendService::initOldFriendList($this->_uniacid , $user_id) ;
$result = ImMessageFriendService::getFriendList($this->_uniacid , $user_id , $param['page_count'] ) ;
//总计未读数
$result['unReadMessageCount'] = ImService::getUnReadMessageCount($this->user_id);
//数据处理
return $this->success($result);
}
//获取未读消息列表
public function listNotReadMessage()
{
//获取参数
$param = $this->_param;
$user_id = $this->user_id;
if(!isset($param['chat_id']) || !isset($param['target_id'])) return $this->error(lang('not chat id ,please check param'));
if(isset($param['target_id']) && !isset($param['chat_id']) && !empty($param['target_id']))
{
//获取chat数据
$chat = longbingGetChat($user_id ,$param['target_id'] ,$this->_uniacid);
if(isset($chat['id'])) $param['chat_id'] = $chat['id'];
}
//判断chat_id参数是否存在
if(!isset($param['chat_id'])) return $this->error('not chat id ,please check param');
//if(!isset($param['user_id'])) return $this->error('not user id ,please check param');
$chat_id = $param['chat_id'];
//获取客户关系
$chat = longbingGetChatById($chat_id ,$this->_uniacid);
//判断数据是否存在
if(empty($chat)) return $this->error('not the chat ,please check chat id');
$customer_id = $chat['user_id'];
if(in_array($customer_id, [$this->user_id])) $customer_id = $chat['target_id'];
$user_id = $this->user_id;
//生成查询模型
$message_model = new ImMessage();
//查询数据
$messages = $message_model->listNotReadMessage(['chat_id' => $chat_id ,'target_id' => $user_id]);
$result['data'] = [];
if(!empty($page_config['total'])){
foreach($messages as $key => $val)
{
if(isset($val['create_time']) && !empty($val['create_time'])) $val['time'] = date('Y-m-d H:i:s', $val['create_time']);
$result['data'][] = $val;
}
}
if(isset($this->user['qr_path'])) $this->user = transImagesOne ( $this->user, ['qr_path'] );
$result['user'] = $this->user;
$customer = getUser($customer_id ,$this->_uniacid);
if(isset($customer['qr_path'])) $customer = transImagesOne ( $customer, ['qr_path'] );
$result['customer'] = $customer;
return $this->success($result);
}
//获取消息列表
public function listMessage()
{
$user = longbingGetUser($this->user_id ,$this->_uniacid);
//获取参数
$param = $this->_param;
$chat_id = null;
$customer_id = null;
$chat = null;
//判断参数是否存在
if(isset($param['chat_id'])) $chat_id = $param['chat_id'];
if(isset($param['customer_id'])) $customer_id = $param['customer_id'];
if(empty($chat_id) && empty($customer_id)) $this->error(lang('not customer id,please check param'));
//参数处理(兼容处理)
$result = [];
if(!empty($chat_id))
{
$chat = longbingGetChatById($chat_id ,$this->_uniacid);
}
else{
$chat = longbingGetChat($this->user_id ,$customer_id ,$this->_uniacid ,true);
}
//生成分页信息
$page_config = array(
'page' => 1,
'page_count' => 20
);
//获取分页信息
if(isset($param['page']) && $param['page'] > 0) $page_config['page'] = $param['page'];
if(isset($param['page_count']) && $param['page_count'] > 0) $page_config['page_count'] = $param['page_count'];
if(!empty($chat))
{
$customer_id = $chat['user_id'];
if(empty($chat_id)) $chat_id = $chat['chat_id'];
if(in_array($customer_id, [$this->user_id])) $customer_id = $chat['target_id'];
//生成消息查询模型
$message_model = new ImMessage();
//获取查询总数
$page_config['total'] = $message_model->listMessageCount(['chat_id' => $chat_id]);
//生成分页数据
$page_config['total_page'] = (int)($page_config['total'] / $page_config['page_count']);
if(($page_config['total'] % $page_config['page_count']) > 0) $page_config['total_page'] = $page_config['total_page'] + 1;
//生成返回数据
}else{
$page_config['total'] = 0;
$page_config['total_page'] = 0;
}
$result = $page_config;
$result['data'] = [];
//获取客户信息
$customer = longbingGetUser($customer_id ,$this->_uniacid);
if(empty($customer)) return $this->error(lang('user not exist.'));
//获取头像
if(isset($customer['avatarUrl'])) {
$customer = transImagesOne ( $customer, ['avatarUrl'] ,$this->_uniacid);
}else{
$customer['avatarUrl'] = $this->defaultImage['avatarUrl'];
}
//判断客户是否是员工
if(!empty($customer['is_staff']))
{
$customer_info = longbingGetUserInfo($customer_id ,$this->_uniacid);
if(isset($customer_info['is_staff']) && !empty($customer_info['is_staff']))
{
if(!empty($customer_info['avatar'])) {
$customer_info = transImagesOne($customer_info ,['avatar'] ,$this->_uniacid);
}
if(!empty($customer_info['avatar'])) $customer['avatarUrl'] = $customer_info['avatar'];
}
}
//获取客户电话号码和微信号码
$customer['wechat'] = null;
$phone = null;
$user_info_model = new UserInfo();
//获取微信和电话号码
$user_info = $user_info_model->getUserPhone($customer_id ,$this->_uniacid);
if(isset($user_info['phone']) && !empty($user_info['phone'])) $phone = $user_info['phone'];
if(isset($user_info['wechat']) && !empty($user_info['wechat'])) $customer['wechat'] = $user_info['wechat'];
if(empty($phone)){
$user_phone_model = new UserPhone();
$user_phone = $user_phone_model->getUserPhone($customer_id ,$this->_uniacid);
if(isset($user_phone['phone']) && !empty($user_phone['phone'])) $phone = $user_phone['phone'];
}
//判断聊天者是否是客户
$customer['is_customer'] = false;
$collection_model = new ImClient();
if(!empty($collection_model->isCustomer($this->user_id , $customer_id ,$this->_uniacid))) $customer['is_customer'] = true;
//判断客户是否是员工
if(isset($customer['is_staff']) && !empty($customer['is_staff']))
{
$customer_info = longbingGetUserInfo($customer_id ,$this->_uniacid);
if(isset($customer_info['is_staff']) && !empty($customer_info['is_staff']) && isset($customer_info['name']) && !empty($customer_info['name'])){
$customer['nickName'] = $customer_info['name'];
//生成第一条默认返回数据
$result['data'][] = array(
'chat_id' => $chat['id'],
'user_id' => $customer_id,
'target_id' => $this->user_id,
'status' => 2,
'uniacid' => $this->_uniacid,
'message_type' => 'welcome',
'content' => lang('Hello, I am ') . $customer['nickName'] . lang(', May I help you? Please contact me!')
);
}
}
$customer['phone'] = $phone;
if(!empty($page_config['total'])){
$msgwhere[] = ['chat_id','=',$chat_id];
//自己发送的
$msgwhere[] = ['is_show','<>',2];
$msgwhere[] = ['user_id','=',$this->getUserId()];
$msgwhere[] = ['deleted','=',0];
$whereT[] = ['deleted','=',0];
//自己接受的
$whereT[] = ['target_id','=',$this->getUserId()];
$whereT[] = ['target_is_show','<>',2];
$whereT[] = ['chat_id','=',$chat_id];
foreach($message_model->listMessageV2($msgwhere ,$page_config,$whereT) as $key => $val)
{
if(isset($val['create_time']) && !empty($val['create_time'])) $val['time'] = date('Y-m-d H:i:s', $val['create_time']);
$result['data'][] = $val;
}
//dump($this->getUserId(),$chat['user_id'],$msgwhere,$result['data']);exit;
}
// if(isset($this->user['qr_path'])) $this->user = transImagesOne ( $this->user, ['qr_path'] );
//判断用户是否是员工
if(!empty($user['is_staff']))
{
$user_info = longbingGetUserInfo($this->user_id ,$this->_uniacid);
if(isset($user_info['is_staff']) && !empty($user_info['is_staff']))
{
if(!empty($user_info['avatar'])) {
$user_info = transImagesOne($user_info ,['avatar'] ,$this->_uniacid);
}
if(!empty($user_info['avatar'])) $user['avatarUrl'] = $user_info['avatar'];
}
}
//默认头像处理
//没有头像就给一个默认头像
$customer['avatarUrl'] = empty($customer['avatarUrl']) ? LongbingDefault::$avatarImgUrl : $customer['avatarUrl'];
$user['avatarUrl'] = empty($user['avatarUrl']) ? LongbingDefault::$avatarImgUrl : $user['avatarUrl'];
$result['user'] = $user;
$result['customer'] = $customer;
//阅读所有消息
$result['readMessageNumber'] = ImService::readMessage($this->_uniacid ,$this->user_id , $customer_id);
return $this->success($result);
}
//标记已读消息
public function readMessage()
{
$param = $this->_param ;
$message_model = new ImMessage();
$count = 0 ;
if ( isset($param['id']) ) {
$id = $param['id'] ;
$message = $message_model->find($id);
if($message){
ImService::readMessage($this->_uniacid ,$this->user_id , $message['user_id'] ) ;
}
}
return $this->success(['count' => $count ] );
}
//获取常用话术
public function listReply()
{
//获取用户信息
$user_id = $this->user_id;
//生成话术分类查询模型
$reply_type_model = new ImReplyType();
//生成快速回复话术查询模型
$reply_model = new ImMyReply();
//获取自定义话术
$my_replys = $reply_model->listReply(['uniacid' => $this->_uniacid ,'user_id' => $user_id ,'status' => 1]);
$result[] = ['title' => lang('my reply') , 'data' => $my_replys ,'is_myself' => true];
//获取types
$types = $reply_type_model->listAllType(['uniacid' => $this->_uniacid ,'status' => 1]);
foreach($types as $type)
{
$data['title'] = $type['title'];
$data['data'] = $reply_model->listReply(['uniacid' => $this->_uniacid ,'user_id' => 0 ,'status' => 1 ,'type' => $type['id']]);
$data['is_myself'] = false;
$result[] = $data;
}
return $this->success($result);
}
//创建和更新常用话术
public function addReply()
{
//获取参数
$input = $this->_input;
$param = $this->_param;
if(!isset($input['content'])) return $this->error('content is not exist ,please check .');
$is_create = true;
if(isset($input['id']) && !empty($input['id'])) $is_create = false;
//获取用户信息
$user_id = $this->user_id;
//生成快速回复话术查询模型
$my_reply_model = new ImMyReply();
if($is_create)
{
//创建
$result = $my_reply_model->createReply(['uniacid' => $this->_uniacid ,'status' => 1 ,'content' => $input['content'] ,'user_id' => $user_id]);
}else{
//修改
$result = $my_reply_model->updateReply(['id' =>$param['id'] , 'uniacid' => $this->_uniacid ,'user_id' => $user_id] ,['content' => $input['content']]);
}
//获取自定义话术
return $this->success($result);
}
//删除常用话术
public function delReply()
{
$param = $this->_param;
$user_id = $this->user_id;
if(!isset($param['id'])) return $this->error('reoly id is not exist ,please check .');
//生成快速回复话术查询模型
$my_reply_model = new ImMyReply();
//删除话术
$result = $my_reply_model->deleteReply(['id' =>$param['id'] ,'uniacid' => $this->_uniacid ,'user_id' => $user_id]);
return $this->success($result);
}
/**
* 腾讯IM签名
*
* @author shuixian
* @DataTime: 2019/12/10 11:30
*/
public function getTimUserSig(){
//需要远程获取和加密
$sdkappid = 1400288706 ;
$key = 'd31548b81e57bf823e12d240e4cce237e09f666bdff3fc325eb4bc386e62832d' ;
$user_id = $this->_param['user_id'];
$userSig = longbing_publics_tim_genSig($sdkappid , $key , $user_id );
$result = ['user_id'=>$user_id , 'userSig' => $userSig] ;
return $this->success($result);
}
/**
* 保存聊天信息
*
* @return \think\Response
* @author shuixian
* @DataTime: 2019/12/11 9:29
*/
public function sendMessage(){
//获取参数列表
//{type: "text", content: "456789", target_id: 14, uniacid: "8890", user_id: 20} //发消息
//{"action":"getUnReadMessageCount","status":true,"message":"","data":{"count":2}} // 获取未读消息树
$param = $this->_param;
//获取房间ID
$chat_id = ImService::getChatId($this->_uniacid , $this->user_id, $param['target_id']);
//还需要校验参数合法新
$value['message_type'] = $param['message_type'];
$value['chat_id'] = $chat_id;//需要获取和判断
$value['user_id'] = $this->user_id;
$value['target_id'] = $param['target_id']; //需要判断接收用户的合法性
$value['content'] = $param['content'];
$value['status'] = 1;
$value['uniacid'] = $this->_uniacid;
$value['create_time'] = time();
$value['update_time'] = time();
$value['is_show'] = 1;
$result = ImService::addMessage($value);
if($result){
$value['id'] = $result ;
ImService::sendImMessageTmpl($this->_uniacid , $value['user_id'] , $value['target_id']) ;
return $this->success( $value );
}else{
$this->error('');
}
}
/**
* @author jingshuixian
* @DataTime: 2020/1/15 13:13
* @功能说明:获取目标客户发送的消息数量
*/
public function getCustomerUnReadMessageCount(){
$param = $this->_param ;
$user_id = $this->user_id;
$target_id = 0 ;
$count = 0 ;
if (isset($param['target_id'])) {
$target_id = $param['target_id'];
$count = ImService::getUnReadMessageCountByUserIdAndTargetId( $target_id , $user_id);
}
$data[] = ['action'=> 'getCustomerUnReadMessageCount' , 'data' => ['count' => $count, 'user_id' => $user_id , 'target_id' => $target_id ] ] ;
$data[] = ['action' => 'getUnReadMessageCount' , 'data' => ['count' => ImService::getUnReadMessageCount($user_id) ] ] ;
$message_model = new ImMessage();
$messageList = $message_model->where( [ ['user_id' , '=' ,$target_id ] ,[ 'target_id' , '=' , $user_id ] , ['status', '=' , 1]] )->select();
foreach ($messageList as $item ){
$data[] = ['action' => 'getNewMessage' , 'data' => $item ] ;
}
$key = 'message'.$user_id.'-'.$target_id;
//获取撤回消息
$cancel_msg = getCache($key,$this->_uniacid);
$data[] = ['action' => 'getCancelMessage' , 'data' => $cancel_msg ] ;
setCache($key,[],0,$this->_uniacid);
return $this->success( $data ) ;
}
/**
* @author chenniang
* @DataTime: 2021-05-26 17:33
* @功能说明:修改消息状态 1都可见 2删除对方可见 撤回都不可见
*/
public function updateMsgStatus(){
$input = $this->_input;
$message_model = new ImMessage();
$info = $message_model->where(['id'=>$input['id']])->find()->toArray();
//撤回只有送人课操作
if($input['is_show']==-1){
$update['is_show'] = -1;
if($info['target_is_show']==1){
$update['target_is_show'] = -1;
}
}
//删除
if($input['is_show']==2){
//判断我是否是发送者
if($info['user_id']==$this->getUserId()){
$update['is_show'] = 2;
}else{
$update['target_is_show'] = 2;
}
}
$res = $message_model->where(['id'=>$input['id']])->update($update);
$data = $message_model->where(['id'=>$input['id']])->find();
if(!empty($data)){
$data = $data->toArray();
$key = 'message'.$data['target_id'].'-'.$data['user_id'];
setCache($key,$data,0,$this->_uniacid);
}
return $this->success( $res ) ;
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace app\im\controller;
class Index
{
public function index()
{
return '您好!这是一个[im]示例应用';
}
}

View File

@@ -0,0 +1,594 @@
<?php
namespace app\im\controller;
use think\App;
use app\ApiRest;
use app\BaseController;
use app\im\model\ImUser;
use app\im\model\ImChat;
use app\im\model\ImMessage;
use think\Exception;
class MessageHandler
{
protected $connect_name = 'longbing_im_connect_';
protected $chat_name = 'longbing_chat_';
protected $uniacid_wss = 'wss';
// public function __construct ()
// {
//
// }
//登陆
public function login($server ,$client_id ,$data)
{
//获取参数
$value = [];
if(isset($data['data'])) $value = $data['data'];
if(empty($value)) return ;
$user_id = null;
$uniacid = '7777';
if(isset($value['user_id'])) $user_id = $value['user_id'];
if(isset($value['uniacid'])) $uniacid = $value['uniacid'];
if(empty($user_id) || empty($uniacid)) return ;
//获取用户信息
$user = $this->getUser($user_id ,$uniacid);
//判断用户是否存在
if(empty($user)) {
return $server->push($client_id ,json_encode(['action' => 'login' ,'status' => false ,'message'=> lang('login error') ,'data' =>[]]));
}
//设置用户连接数据
$user['client_id'] = $client_id;
$cache_user = $this->setCacheUser($user_id ,$user ,$uniacid);
//设置用户连接
$cache_connect = $this->setConnect($client_id ,['user_id' => $user_id ,'uniacid' => $uniacid]);
//判断缓存是否插入成功
if(empty($cache_user) || empty($cache_connect)) $server->push($client_id ,json_encode(lang('login error')));
//返回登陆成功
$server->push($client_id ,json_encode(['action' => 'login' ,'status' => true ,'message'=> 'login success.' ,'data' =>$user]));
}
//检查登录
public function checkLogin($client_id ,$data = [])
{
$result = false;
//获取连接信息
$connect = $this->getConnect($client_id);
//如果没有登录
if(empty($connect) || !isset($connect['user_id']) || !isset($connect['uniacid']))
{
$user_id = null;
$uniacid = '7777';
//判断用户id是否存在
if(!isset($data['user_id'])) return $result;
//获取用户id
$user_id = $data['user_id'];
//获取uniacid
if(isset($data['uniacid'])) $uniacid = $data['uniacid'];
//获取用户数据
$user = $this->getUser($user_id ,$uniacid);
//判断用书是否存在
if(empty($user)) return $result;
//设置用户连接数据
$user['client_id'] = $client_id;
$cache_user = $this->setCacheUser($user_id ,$user ,$uniacid);
//设置用户连接
$cache_connect = $this->setConnect($client_id ,['user_id' => $user_id ,'uniacid' => $uniacid]);
//判断缓存是否插入成功
if(!empty($cache_user) && !empty($cache_connect)) $result = true;
}else{
$result = true;
}
return $result;
}
//退出
public function logout($client_id)
{
$this->delConnect($client_id);
}
//发送消息
public function sendMessage($server ,$client_id ,$data)
{
//登录检查
if(!$this->checkLogin($client_id ,$data['data'])){
$server->push($client_id ,json_encode(['action' => 'login' ,'status' => false ,'message'=> 'login error ,please check login param.' ,'data' =>[]]));
return;
}
//获取用户是否登录
$connect = $this->getConnect($client_id);
$user = null;
if(empty($connect) || !isset($connect['user_id']) || !isset($connect['uniacid']))
{
return;
}else{
$user = $this->getUser($connect['user_id'] ,$connect['uniacid']);
}
//判断用户是否存在
if(empty($user)) return ;
//判断连接是否正确
if(!isset($user['client_id']) || !in_array($user['client_id'], [$client_id]))
{
$user['client_id'] = $client_id;
$this->setCacheUser($connect['user_id'], $user ,'ws');
}
//检查消息
$value['message_type'] = 'text';
$value['status'] = 1;
$value['user_id'] = $connect['user_id'];
$value['uniacid'] = $connect['uniacid'];
$value['create_time'] = time();
if(isset($data['data'])){
$data = $data['data'];
}else{
return;
}
//判断接受者是否存在
if(isset($data['target_id'])) {
$value['target_id'] = $data['target_id'];
}else{
return ;
}
//判断数据类型是否存在
if(isset($data['type'])) $value['message_type'] = $data['type'];
//判断状态是否存在
if(isset($data['status'])) $value['status'] = $data['status'];
//判断发送者是否存在
if(isset($data['user_id'])) $value['user_id'] = $data['user_id'];
//判断uniacid是否存在
if(isset($data['uniacid'])) $value['uniacid'] = $data['uniacid'];
if(isset($data['chat_id']))
{
$value['chat_id'] = $data['chat_id'];
}else{
// $data = $this->getChat($value['user_id'], $value['target_id'] ,$data['uniacid']);
$value['chat_id'] = $this->getChatId($value['user_id'], $value['target_id'] ,$data['uniacid'] ,true);
//$server->push($client_id , json_encode($value ,true));die;
}
//判断发送消息是否存在
if(isset($data['content'])) {
$value['content'] = $data['content'];
}else{
return ;
}
//检查数据(防止伪造数据的存在)
$target = $this->getUser($value['target_id'] ,$value['uniacid']);
//判断用户是否存在
if(empty($target)) return;
//存储数据
// $push_data = array(
// 'action' => 'addMessage',
// 'event' => 'asyncAddMessage',
// 'message' => $value
// );
// $i = 1000000;
// while($i>0)
// {
// publisher(json_encode($push_data ,true));
// $i = $i -1;
// }
// publisher(json_encode($push_data ,true));
$resultAddMsg = false ;
//随机模拟发送消息失败情况
/*mt_srand();
$demoError = mt_rand(0, 1);
if($demoError){
if(isset($value['chat_id']) && !empty($value['chat_id'])) $resultAddMsg = asyncAddMessage($value);
}*/
if(isset($value['chat_id']) && !empty($value['chat_id'])) $resultAddMsg = asyncAddMessage($value);
//By.jingshuixian 如果消息存储失败,直接返回
if(!$resultAddMsg){
$server->push($client_id ,json_encode(['action' => 'sendMessage' ,'status' => $resultAddMsg,'data' => $value] ,true));
return false ;
}
//判断用户是否登录
if(isset($target['client_id'])) {
$value['time'] = date('Y-m-d H:i:s', time());
try{
$server->push($target['client_id'] , json_encode(['action' => 'getNewMessage' ,'status' => $resultAddMsg , 'data' => $value] ,true));
}catch (Exception $e){
//echo "$server->push error" ;
}
//向消息接受者发送未读消息数量
//$this->getCustomerUnReadMessageCount($server ,$target['client_id'] ,['target_id' => $data['user_id']]);
$this->getCustomer($server ,$target['client_id'] ,['data' => ['user_id' => $value['target_id'] ,'target_id' => $value['user_id'] ,'uniacid' => $value['uniacid']]]);
$this->getCustomerUnReadMessageCount($server ,$target['client_id'] ,['data' => ['user_id' => $value['target_id'] ,'target_id' => $value['user_id'] ,'uniacid' => $value['uniacid']]]);
$this->getUnReadMessageCount($server ,$target['client_id'] ,['data' => ['user_id' => $value['target_id'] ,'target_id' => $value['user_id'] ,'uniacid' => $value['uniacid']]]);
}else{
//发送服务通知
// $push_data = array(
// 'action' => 'sendMessageWxServiceNotice',
// 'event' => 'longbingSendMessageWxServiceNotice',
// 'message' => $value
// );
// publisher(json_encode($push_data ,true));
longbingSendMessageWxServiceNotice($value);
}
$value['status'] = 1;
$value['creat_time'] = time();
$value['time'] = date('Y-m-d H:i:s', time());
$server->push($client_id ,json_encode(['action' => 'sendMessage' ,'status' => $resultAddMsg,'data' => $value] ,true));
//存储数据
// $push_data = array(
// 'action' => 'addMessage',
// 'event' => 'asyncAddMessage',
// 'message' => $value
// );
// publisher(json_encode($push_data ,true) ,1000);
//发送用户总的未读数据获取用户
}
//获取用户缓存
function getCacheUser($user_id ,$uniacid = '7777')
{
$key = 'longbing_ws_card_user_' . $user_id;
if(!hasCache($key ,$uniacid)) return null;
return getCache($key ,$uniacid);
}
//设置用户缓存数据
function setCacheUser($user_id ,$value ,$uniacid = '7777')
{
$key = 'longbing_ws_card_user_' . $user_id;
return setCache ( $key, $value, 3600, $uniacid);
}
//获取用户信息
function getUser($user_id ,$uniacid ='7777')
{
//判断缓存是否存在
$user = $this->getCacheUser($user_id ,$uniacid);
if(!empty($user)) return $user;
// //生成查询类
// $user_model = new ImUser();
// //获取数据
// $user = $user_model->getUser(['id' => $user_id ,'uniacid' => $uniacid]);
$user = longbingGetUser($user_id ,$uniacid);
if(empty($user)) return null;
$this->setCacheUser($user_id ,$user ,$uniacid);
return $user;
}
//获取当前连接状态
function getConnect($client_id ,$uniacid = 'ws')
{
$key = $this->connect_name . $client_id;
$connect = getCache($key ,$uniacid);
return $connect;
}
//设置连接状态
function setConnect($client_id ,$value , $uniacid = 'ws')
{
$key = $this->connect_name . $client_id;
return setCache ( $key, $value, 3600, $uniacid);
}
//注销连接
function delConnect($client_id ,$uniacid = 'ws')
{
$key = $this->connect_name . $client_id;
$connect = $this->getConnect($client_id ,$uniacid);
if(empty($connect) || !isset($connect['user_id']) || !isset($connect['uniacid'])) return false;
$user = $this->getUser($connect['user_id'] ,$connect['uniacid']);
if(isset($user['client_id'])){
unset($user['client_id']);
$this->setCacheUser($connect['user_id'],$user, $connect['uniacid']);
}
delCache($key ,$uniacid);
}
//获取所有chat
function getChats($user_id ,$uniacid = '7777' ,$is_update = false)
{
// $key = $this->chat_name . $user_id;
// $chats = [];
// //判断是否更新
// if($is_update)
// {
// $chat_model = new ImChat();
// $chats_data = $chat_model->listChatAll($user_id ,$uniacid);
// foreach($chats_data as $chat)
// {
// if(!isset($chat['chat_id']) || !isset($chat['user_id']) || !isset($chat['target_id'])) continue;
// $customer_id = $chat['user_id'];
// if(!in_array($chat['user_id'], [$user_id])) $customer_id = $chat['target_id'];
// $chats[$customer_id] = $chat['chat_id'];
// }
// if(!empty($chats)) $this->setChat($user_id ,$chats ,$uniacid);
// }else{
// if(hasCache($key ,$uniacid)){
// $chats = getCache($key ,$uniacid);
// }else{
// $chats = $this->getChats($user_id ,$uniacid ,true);
// }
// }
// return $chats;
$key = $this->chat_name . $user_id;
$chats = [];
if(hasCache($key ,$uniacid)){
$chats = getCache($key ,$uniacid);
}
return $chats;
}
//获取用户与客户的chat
function getChatId($user_id ,$customer_id ,$uniacid ,$is_create = false)
{
// //获取chats
// $chats = $this->getChats($user_id ,$uniacid);
// $chat_id = null;
// //判断数据是否存在
// if(!isset($chats[$customer_id])){
// $this->createChat(['user_id' => $user_id ,'target_id' => $customer_id ,'uniacid' => $uniacid ,'create_time' => time()]);
// $chat_id = $this->getChatId($user_id ,$customer_id ,$uniacid);
// }else{
// $chat_id = $this->getChats($user_id ,$uniacid)[$customer_id];
// }
// //返回数据
// return $chat_id;
//获取chats
$chats = $this->getChats($user_id ,$uniacid);
$chat_id = null;
//判断数据是否存在
if(!isset($chats[$customer_id])){
//从数据库中查询数据
$chat = $this->getChat($user_id, $customer_id ,$uniacid);
if(empty($chat))
{
if(!empty($is_create)){
$chat_id = $this->createChat(['user_id' => $user_id ,'target_id' => $customer_id ,'uniacid' => $uniacid ,'create_time' => time()]);
// $chat_id = $this->getChatId($user_id ,$customer_id ,$uniacid);
}
}else{
$chats[$customer_id] = $chat['chat_id'];
$this->setChat($user_id, $chats ,$uniacid);
}
}else{
$chat_id = $this->getChats($user_id ,$uniacid)[$customer_id];
}
//返回数据
return $chat_id;
}
//获取chat
function getChat($user_id ,$customer_id ,$uniacid = '7777')
{
$chat_model = new ImChat();
$chat = $chat_model->getChat($user_id ,$customer_id ,$uniacid);
return $chat;
}
//设置Chat
function setChat($user_id ,$value ,$uniacid ='7777')
{
$key = $this->chat_name . $user_id;
return setCache($key, $value, 60, $uniacid);
}
//创建Chat
function createChat($data)
{
$chat_model = new ImChat();
$result = $chat_model->createChat($data);
//$this->getChats($data['user_id'] ,$data['uniacid'] ,true);
return $result;
}
//获取客户列表
function listCustomer($data)
{
//获取参数列表
$param = $this->$data;
//获取用户列表
$user_id = $param['user_id'];
//判断用户是否存在
if(empty($user_id)) return $this->error('not login ,please login again.');
//生成分页信息
$page_config = array(
'page' => 1,
'page_count' => 10
);
//获取分页信息
if(isset($param['page']) && $param['page'] > 0) $page_config['page'] = $param['page'];
if(isset($param['page_count']) && $param['page_count'] > 0) $page_config['page_count'] = $param['page_count'];
//生成查询模型
$chat_model = new ImChat();
//生成消息查询模型
$message_model = new ImMessage();
//生成用户查询模型
// $user_model = new ImUser();
//生成查询
$page_config['total'] = $chat_model->listChatCount($user_id);
$chats = $chat_model->listChat($user_id ,$page_config);
if(!empty($chats))
{
foreach($chats as $key => $value)
{
$lastmessage = $message_model->lastMessage(['chat_id' => $value['id']]);
$value['lastmessage'] = $lastmessage;
$customer_id = null;
if(!in_array($value['user_id'], [$user_id])) $customer_id = $value['user_id'];
if(!in_array($value['target_id'], [$user_id])) $customer_id = $value['target_id'];
// $value['customer'] = $user_model->getUser(['id' => $customer_id]);
$value['customer'] = longbingGetUser($customer_id ,$value['uniacid']);
$chats[$key] = $value;
}
}
$page_config['total_page'] = (int)($page_config['total'] / $page_config['page_count']);
if(($page_config['total'] % $page_config['page_count']) > 0) $page_config['total_page'] = $page_config['total_page'] + 1;
$result = $page_config;
$result['chats'] = $chats;
return $this->success($result);
}
//获取未读消息总数
public function getUnReadMessageCount($server ,$client_id ,$data)
{
//登录检查
if(!$this->checkLogin($client_id ,$data['data'])){
$server->push($client_id ,json_encode(['action' => 'login' ,'status' => false ,'message'=> 'login error ,please check login param.' ,'data' =>[]]));
return;
}
//获取用户是否登录
$connect = $this->getConnect($client_id);
$user = null;
if(empty($connect) || !isset($connect['user_id']) || !isset($connect['uniacid']))
{
return;
}else{
$user = $this->getUser($connect['user_id'] ,$connect['uniacid']);
}
//判断用户是否存在
if(empty($user)) return ;
//判断连接是否正确
if(!isset($user['client_id']) || !in_array($user['client_id'], [$client_id]))
{
$user['client_id'] = $client_id;
$this->setCacheUser($connect['user_id'], $user ,'ws');
}
//获取未读消息总数
$message_model = new ImMessage();
// $server->push($client_id ,json_encode($user));
$count = $message_model->listMessageCount(['target_id' => $user['id'] ,'status' => 1]);
// $count = $message_model->listMessageCount(['status' => 1]);
$server->push($client_id ,json_encode(['action' => 'getUnReadMessageCount' ,'status' => true ,'message'=> '' ,'data' =>['count' => $count]]));
return;
}
//获取用户未读消息数
public function getCustomerUnReadMessageCount($server ,$client_id ,$data)
{
//登录检查
if(!$this->checkLogin($client_id ,$data['data'])){
$server->push($client_id ,json_encode(['action' => 'login' ,'status' => false ,'message'=> 'login error ,please check login param.' ,'data' =>[]]));
return;
}
if(!isset($data['data']['target_id'])) return;
$customer_id = $data['data']['target_id'];
//获取用户是否登录
$connect = $this->getConnect($client_id);
$user = null;
if(empty($connect) || !isset($connect['user_id']) || !isset($connect['uniacid']))
{
return;
}else{
$user = $this->getUser($connect['user_id'] ,$connect['uniacid']);
}
//判断用户是否存在
if(empty($user)) return ;
//判断连接是否正确
if(!isset($user['client_id']) || !in_array($user['client_id'], [$client_id]))
{
$user['client_id'] = $client_id;
$this->setCacheUser($connect['user_id'], $user ,'ws');
}
//获取未读消息总数
$message_model = new ImMessage();
$chat_id = $this->getChatId($user['id'] ,$customer_id ,$user['uniacid'] ,true);
if(empty($chat_id)) return;
$count = $message_model->listMessageCount(['user_id' => $customer_id,'target_id' => $user['id'] ,'status' => 1]);
// $count = $message_model->listMessageCount(['status' => 1]);
$server->push($client_id ,json_encode(['action' => 'getCustomerUnReadMessageCount' ,'status' => true ,'message'=> '' ,'data' =>['count' => $count ,'target_id' => $customer_id ,'user_id' => $user['id']]]));
return;
}
//获取客户信息
public function getCustomer($server ,$client_id ,$data)
{
//登录检查
if(!$this->checkLogin($client_id ,$data['data'])){
$server->push($client_id ,json_encode(['action' => 'login' ,'status' => false ,'message'=> 'login error ,please check login param.' ,'data' =>[]]));
return;
}
if(!isset($data['data'])) return;
if(!isset($data['data']['user_id'])) return;
if(!isset($data['data']['target_id'])) return;
if(!isset($data['data']['uniacid'])) return;
$user_id = $data['data']['user_id'];
$customer_id = $data['data']['target_id'];
$uniacid = $data['data']['uniacid'];
//生成关系操作类
$chat_model = new ImChat();
//获取chat_id
$chat_id = $this->getChatId($user_id ,$customer_id ,$uniacid ,true);
if(empty($chat_id)) return;
//获取数据
$chat = $chat_model->getChatById($chat_id);
if(empty($chat)) return;
//获取客户信息
$customer = $this->getUser($customer_id ,$uniacid);
$chat['customer'] = $customer;
$chat['time'] = date('Y-m-d H:i:s', time());
if(isset($chat['update'])) $chat['time'] = date('Y-m-d H:i:s', $chat['update']);
$message_model = new ImMessage();
//获取最后一条消息
$last_message = $message_model->lastMessage(['chat_id' => $chat_id]);
$chat['lastmessage'] = $last_message;
//获取未读客户数据数量
$not_rear_message_count = $message_model->listMessageCount(['chat_id' => $chat_id ,'user_id' => $customer_id ,'target_id' =>$user_id ,'status' => 1]);
$chat['not_read_message_count'] = $not_rear_message_count;
//返回数据
$server->push($client_id ,json_encode(['action' => 'getCustomer' ,'status' => true ,'data' => $chat ,'message' => ''] ,true));
}
//检查链接是否正常
public function checkWs($server ,$client_id ,$data)
{
if(!isset($data['data']['check']) || !in_array($data['data']['check'], ['78346+SJDHFA.longbing'])) return ;
// $server->push($client_id ,json_encode(['action' => 'checkWs' ,'status' => true ,'message'=> '' ,'data' =>['check' => '78346+SJDHFA.longbing']]));
$server->push($client_id ,json_encode(['action' => 'checkWs' ,'status' => true ,'message' => '' ,'data' => ['check' => '78346+SJDHFA.longbing']]));
}
//标记消息已读
public function readMessage($server ,$client_id ,$data)
{
//登录检查
if(!$this->checkLogin($client_id ,$data['data'])){
$server->push($client_id ,json_encode(['action' => 'login' ,'status' => false ,'message'=> 'login error ,please check login param.' ,'data' =>[]]));
return;
}
//获取用户是否登录
$connect = $this->getConnect($client_id);
$user = null;
if(empty($connect) || !isset($connect['user_id']) || !isset($connect['uniacid']))
{
return;
}else{
$user = $this->getUser($connect['user_id'] ,$connect['uniacid']);
}
//判断用户是否存在
if(empty($user)) return ;
//判断连接是否正确
if(!isset($user['client_id']) || !in_array($user['client_id'], [$client_id]))
{
$user['client_id'] = $client_id;
$this->setCacheUser($connect['user_id'], $user ,'ws');
}
if(!isset($data['data']['target_id'])) return ;
$target_id = $data['data']['target_id'];
if(isset($data['data']['uniacid'])) $uniacid = $data['data']['uniacid'];
if(isset($user['uniacid'])) $uniacid = $user['uniacid'];
$user_id = $user['id'];
$chat_id = $this->getChatId($user_id, $target_id ,$uniacid , true);
if(empty($chat_id)) return;
//设置已读数据
$message_model = new ImMessage();
$message_model->readMessage(['chat_id' => $chat_id ,'user_id' => $target_id ,'target_id' => $user_id ,'deleted' => 0]);
//发数据给自己
$this->getCustomer($server ,$client_id ,['data' => ['user_id' => $user_id ,'target_id' => $target_id,'uniacid' => $uniacid]]);
//
$this->getUnReadMessageCount($server ,$client_id ,['data' => ['user_id' => $user_id,'target_id' => $target_id ,'uniacid' => $uniacid]]);
}
}

View File

@@ -0,0 +1,220 @@
<?php
namespace app\im\controller;
use app\Common\LongbingServiceNotice;
use app\Common\service\LongbingUserInfoService;
use app\im\service\ImService;
use longbingcore\tools\LongbingStr;
use longbingcore\tools\LongbingTime;
use think\App;
class MessageHandlerV2 extends BaseMessage
{
//连接客户端ID
protected $connect_name = 'longbing_im_connect_';
//链接对应的用户ID
protected $connect_user_name = 'longbing_im_connect_user';
//房间ID
protected $chat_name = 'longbing_chat_';
protected $uniacid_wss = 'wss';
protected $noLogin = ['code' => 401, 'error' => '请登录系统!'] ;
//发送消息
public function sendMessage($server ,$client_id ,$data)
{
//检查登录
$user_id = $this->checkLogin($server ,$client_id ,$data);
if(!$user_id){
return $this->sendLogin($server , $client_id ) ;
}
$uniacid = $data['data']['uniacid'];
$target_id = $data['data']['target_id']; //接收消息用户id
$content = $data['data']['content'];
if( isset($data['data']['id']) && $data['data']['id'] > 0 ) { //
$message = $data['data'] ;
$message_type = $data['data']['message_type'];
}else{
$chat_id = ImService::getChatId($uniacid, $user_id, $target_id);
$message_type = $data['data']['type'];
$message['message_type'] = $message_type; //
$message['status'] = 1; //消息状态 1=>未读消息 2=>已读 3=>已撤销 4=>已删除
$message['user_id'] = $user_id; //发送消息用户id
$message['target_id'] = $target_id; //接收消息用户id
$message['content'] = $content; // 消息内容
$message['uniacid'] = $uniacid; //平台ID
$message['chat_id'] = $chat_id; // 房间ID
$message['create_time'] = time();
$message['update_time'] = time();
ImService::addMessage($message);
}
$pushTargetClientId = intval( $this->getClientIdByUserId($target_id) ) ;
//客户在线
if($pushTargetClientId){
$this->sendServerMsg($server , $pushTargetClientId , 'getNewMessage' ,true,'', $message );
$this->getUnReadMessageCount($server , $pushTargetClientId , ['data'=>['user_id' => $target_id ] ] );
$this->getCustomerUnReadMessageCount($server , $pushTargetClientId , ['data'=>['user_id' => $target_id ,'target_id' => $user_id ] ] );
}else{
//发送服务通知给客户
//员工姓名,必须为中文,不能带有数字和符号
//$name = LongbingUserInfoService::getNameByUserId($user_id);
//ImService::sendTmplMsg($uniacid,$target_id,[ $name , '有未读私信' , LongbingTime::getChinaNowTime()] , 'pages/user/home' );
}
$this->sendServerMsg($server , $client_id , 'sendMessage' ,true,'', $message );
$this->getUnReadMessageCount($server , $client_id , ['data'=>['user_id' => $user_id ] ] );
//给员工发通知消息
//$note = new LongbingServiceNotice($uniacid);
//$note->sendImMessageServiceNoticeToStaff($target_id , $content) ;
}
//获取未读消息总数
public function getUnReadMessageCount($server ,$client_id ,$data)
{
$user_id = $data['data']['user_id'] ;
$count = ImService::getUnReadMessageCount($user_id);
$this->sendServerMsg($server ,$client_id , 'getUnReadMessageCount' , true,'', ['count' => $count ] ) ;
}
//查询目标客户,给我发送的消息数量
public function getCustomerUnReadMessageCount($server ,$client_id ,$data)
{
if (isset($data['data']['target_id']) && isset($data['data']['user_id'])) {
$user_id = $data['data']['user_id'];
$target_id = $data['data']['target_id'];
$count = ImService::getUnReadMessageCountByUserIdAndTargetId( $target_id , $user_id);
$this->sendServerMsg($server, $client_id, 'getCustomerUnReadMessageCount', true, '', ['count' => $count, 'user_id' => $user_id , 'target_id' => $target_id ]);
}
}
//登陆
public function login($server ,$client_id ,$data)
{
//登录失败
$user_id = $this->checkLogin($server ,$client_id ,$data);
if(!$user_id){
return $this->sendLogin($server , $client_id ) ;
}
$this->updateClentAndUserIdCache($client_id , $user_id);
$this->sendServerMsg($server ,$client_id , 'login' , true ) ;
//用户登录成功,给客户发未读消息数量
$this->getUnReadMessageCount($server , $client_id , ['data'=>['user_id' => $user_id ] ] );
}
//检查登录
public function checkLogin( $server ,$client_id ,$data ){
if(isset($data['data']['token'])){
$token = $data['data']['token'];
$uniacid = $data['data']['uniacid'] ;
$user = getCache($token , $uniacid );
if(empty($user)){
return false ;
}
return $user['id'] ;
}else{
echo json_encode($data);
}
return false ;
}
//发送登录提示消息信息
public function sendLogin( $server ,$client_id ){
$this->sendServerMsg($server, $client_id ,'login',false,'',$this->noLogin);
}
//更新缓存客户和用户ID
public function updateClentAndUserIdCache($client_id , $user_id){
//缓存客户端对应的用户ID
$key = $this->connect_name . $client_id;
setCache ( $key, $user_id, 3600, $this->uniacid_wss );
//缓存用户登录对应的客户端ID
$key = $this->connect_user_name . $user_id;
setCache ( $key, $client_id, 3600, $this->uniacid_wss );
}
//根据用户ID获取 $client_id
public function getClientIdByUserId($userId){
$key = $this->connect_user_name . $userId;
$client_id = getCache( $key , $this->uniacid_wss ) ;
return $client_id;
}
//退出
public function logout($client_id)
{
$key = $this->connect_name . $client_id;
$user_id = getCache( $key , $this->uniacid_wss ) ;
//删除客户对应的用户ID
delCache($key ,$this->uniacid_wss);
//删除用户对应的客户ID
$key = $this->connect_user_name . $user_id;
delCache($key ,$this->uniacid_wss);
}
//检查链接是否正常
public function checkWs($server ,$client_id ,$data)
{
//检查登录
$user_id = $this->checkLogin($server ,$client_id ,$data);
if(!$user_id){
return $this->sendLogin($server , $client_id ) ;
}
$this->updateClentAndUserIdCache($client_id , $user_id) ;
$this->sendServerMsg($server, $client_id ,'checkWsOk');
}
}

View File

@@ -0,0 +1,147 @@
<?php
namespace app\im\controller;
use app\im\controller\MessageHander;
//use think\swoole\Websocket as websocket;
use Swoole\Http\Server as HttpServer;
use Swoole\Websocket\Server as WebsocketServer;
use think\App;
use think\Route;
use think\swoole\command\Server as ServerCommand;
use think\swoole\facade\Server;
use think\swoole\websocket\socketio\Controller;
use think\swoole\websocket\socketio\Middleware;
use think\facade\Config;
//推送服务器
class PushServer extends \think\Service
{
private static $instance;
private static $server;
private $config;
//处理消息对象
private $messageHandler;
protected $isWebsocket = false;
public function __construct()
{
// parent::__construct();
//创建websocket对象
// self::$server = new swoole_websocket_server("0.0.0.0", 8006);
// self::$server = $server::$server;
// self::$server = new websocket("0.0.0.0", 8006);
$this->init();
$this->register();
//设置
// self::initServer();
//注册事件
//连接客户端
self::$server->on("open" ,[$this , "onOpen"]);
//发送消息
self::$server->on('message' ,[$this ,'onMessage']);
//关闭连接
self::$server->on('close' ,[$this ,'onClose']);
//异步
self::$server->on('task' ,[$this ,'onTask']);
//启动时运行
self::$server->on('workerStart' ,[$this ,'onWorkerStart']);
}
//获取
public static function getInstance()
{
if(!self::$instance instanceof self)
{
self::$instance = new self();
}
return self::$instance;
}
protected function init()
{
$this->config = Config::get('swoole');
}
public function register()
{
$this->isWebsocket = Config::get('swoole.websocket.enabled');
$this->createSwooleServer();
}
public function boot(Route $route)
{
$this->commands(ServerCommand::class);
if ($this->isWebsocket) {
$route->group(function () use ($route) {
$route->get('socket.io/', '@upgrade');
$route->post('socket.io/', '@reject');
})->prefix(Controller::class)->middleware(Middleware::class);
}
}
/**
* Create swoole server.
*/
protected function createSwooleServer()
{
$server = $this->isWebsocket ? WebsocketServer::class : HttpServer::class;
$config = $this->config;
$host = Config::get('swoole.server.host');
$port = Config::get('swoole.server.port');
$socketType = Config::get('swoole.server.socket_type', SWOOLE_SOCK_TCP);
$mode = Config::get('swoole.server.mode', SWOOLE_PROCESS);
self::$server = new $server($host, $port, $mode, $socketType);
$options = Config::get('swoole.server.options');
self::$server->set($options);
}
//启动服务器
public function start()
{
self::$server->start();
}
//客户端连接上后执行的方法
public function onOpen($server ,$req)
{
self::$server->push($req->fd ,json_encode(['action' => 'connect' ,'status' => true ,'data' => [] ,'message' => 'connect success.'] ,true));
}
//客户端连接上后执行的方法
public function onMessage($server ,$frame)
{
self::$server->reload();//重新加载代码
$data = json_decode($frame->data ,true);
$result = null;
if(method_exists($this->messageHandler, $data['action']))
{
$result = call_user_func([$this->messageHandler, $data['action']] ,self::$server ,$frame->fd ,$data);
}
}
//异步
public function onTask($server ,$frame)
{
}
//关闭连接
public function onClose($server ,$fd)
{
call_user_func([$this->messageHandler, 'logout'] ,$fd);
}
//onWorkerStart
public function onWorkerStart()
{
// 加载框架里面的文件
require __DIR__ . '/../../../vendor/autoload.php';
$http = ( new App() )->http;
$response = $http->run();
$this->messageHandler = new MessageHandlerV2();
}
//发送消息
public function sendMessage($fd ,$data){
self::$server->push($fd ,$data);
}
}

612
app/im/controller/Some.php Normal file
View File

@@ -0,0 +1,612 @@
<?php
namespace app\im\controller;
use app\card\model\UserInfo;
use app\material\model\BrochureIm;
use app\material\model\ImVideo;
use app\shop\model\IndexUser;
use Redis;
use think\facade\Cache;
use think\facade\Config;
class Some {
public $redis;
public function __construct() {
$host = Config::get('cache.stores.redis.host');
$port = Config::get('cache.stores.redis.port');
$password = Config::get('cache.stores.redis.password');
if(empty($this->redis)||$this->redis->ping()!=true){
$this->redis = new Redis();
$this->redis->connect($host,$port);
if(!empty($password)){
$this->redis->auth($password); //设置密码
}
// $connect_status = $this->redis->ping();
// if($connect_status != "+PONG")
// if($connect_status != true)
// {
// $this->redis->connect($host,$port);
//
// if(!empty($password)){
//
// $this->redis->auth($password); //设置密码
// }
//
// }
}
}
/**
* @param $ws
* @param $request
* @功能说明:建立连接回调(智能物料)
* @author chenniang
* @DataTime: 2021-07-02 18:17
*/
public function mOnOpen($data,$fd) {
$room_key = $data['room_key'];
$uid = !empty($data['user_id'])?$data['user_id']:0;
$target_id= !empty($data['target_id'])?$data['target_id']:0;
$uniacid = !empty($data['uniacid'])?$data['uniacid']:0;
//是否是群主
$leader =!empty($data['presenter'])?$data['presenter']:0;
//1是文件 2是宣传册
$type = !empty($data['type'])?$data['type']:1;
//加入房间域
$this->redis->hset($room_key,$uid,$fd);
//加入组集合
$this->redis->sadd('group', $room_key);
//如果是群主
if($leader==1){
$key = $room_key.'-leader';
//群主
$this->redis->set($key,$uid,86400);
}
$bIm_model = new BrochureIm();
$dis = [
'user_id' => $uid,
'room_key' => $room_key,
'brochure_id' => $target_id,
'type' => $type,
];
$find = $bIm_model->dataInfo($dis);
$room_status = $bIm_model->where(['room_key'=>$room_key,'leader'=>1])->value('status');
$room_status = !empty($room_status)?$room_status:1;
if(empty($find)){
$key = $room_key.'-leader';
//群主
$user_id = $this->redis->get($key);
$user_info = new UserInfo();
$user_id = !empty($user_id)?$user_id:0;
$company_id = $user_info->where(['fans_id'=>$user_id])->value('company_id');
$insert = [
'uniacid' => $uniacid,
'user_id' => $uid,
'room_key' => $room_key,
'brochure_id' => $target_id,
'leader' => $leader,
'type' => $type,
'company_id' => !empty($company_id)?$company_id:0,
'status' => $room_status
];
$bIm_model->dataAdd($insert);
}else{
$bIm_model->dataUpdate($dis,['status'=>$room_status]);
}
}
/**
* @param $ws
* @param $frame
* @功能说明:接受消息回调(智能物料)
* @author chenniang
* @DataTime: 2021-07-02 18:17
*/
public function mOnMessage($ws, $data,$fd) {
$room_key = $data['data']['room_key'];
//获取房间
$room = $this->redis->hGetAll($room_key);
if(!empty($room)){
foreach ($room as $k => $vv) {
//投递消息
$ws->push($vv, json_encode($data));
}
}
}
/**
* @param $ws
* @param $data
* @param $fd
* @功能说明:保存音频
* @author chenniang
* @DataTime: 2021-08-10 17:25
*/
public function addVideo($ws, $data,$fd){
$room_key = $data['data']['room_key'];
$uniacid = !empty($data['data']['uniacid'])?$data['data']['uniacid']:0;
$video = FILE_UPLOAD_PATH.$data['data']['video'];
if(!empty($data['data']['video'])){
$im_video_model = new ImVideo();
$insert = [
'uniacid' => $uniacid,
'room_key' => $room_key,
'video' => $video,
];
$im_video_model->dataAdd($insert);
}
}
/**
* @param $ws
* @param $frame
* @功能说明:接受消息回调(智能物料)
* @author chenniang
* @DataTime: 2021-07-02 18:17
*/
public function onLogin($ws, $data,$fd) {
$room_key = $data['data']['room_key'];
// $room_key = '20210802093606035000000350';
//获取房间
$room = $this->redis->hgetall($room_key);
if(!empty($room)){
$user_model = new IndexUser();
$bIm_model = new BrochureIm();
$user_id = array_keys($room);
$key = $room_key.'-leader';
//获取群组的用户id
$leader_id = $this->redis->get($key);
if(!empty($leader_id)){
$user_key = array_search($leader_id,$user_id);
if(is_numeric($user_key)&&array_key_exists($user_key,$user_id)){
unset($user_id[$user_key]);
}
}
$user = $user_model->where('id','in',$user_id)->field('nickName,avatarUrl')->select()->toArray();
$list['data']['user'] = $user;
$list['action'] = $data['action'];
$list['data']['room_key'] = $room_key;
$list['data']['count'] = count($user_id);
$dis = [
'room_key' => $room_key,
'leader' => 1
];
//演示状态
$list['data']['is_start'] = $bIm_model->where($dis)->value('status');
foreach ($room as $k => $vv) {
//投递消息
$ws->push($vv, json_encode($list));
}
}
}
/**
* @author chenniang
* @DataTime: 2021-07-28 16:50
* @功能说明:开始演示
*/
public function startAction($ws, $data,$fd){
$room_key = $data['data']['room_key'];
$bIm_model = new BrochureIm();
$dis = [
'room_key' => $room_key,
// 'leader' => 1
];
//修改演示状态
$bIm_model->dataUpdate($dis,['status'=>2]);
$bIm_model->dataUpdate(['room_key'=>$room_key],['time_long'=>0,'update_time'=>time()]);
$room = $this->redis->hGetAll($room_key);
$list['data']['is_start'] = 2;
$list['data']['room_key'] = $room_key;
$list['action'] = $data['action'];
if(!empty($room)){
foreach ($room as $k=>$vv){
//投递消息
$ws->push($vv, json_encode($list));
}
}
}
/**
* @param $serv
* @param $task_id
* @param $worker_id
* @param $data
* @功能说明:完成异步任务回调
* @author chenniang
* @DataTime: 2021-07-02 18:17
*/
public function onTask($serv, $task_id, $worker_id, $data) {
//返回字符串给worker进程——>触发onFinish
return "success";
}
/**
* @param $serv
* @param $task_id
* @param $data
* @功能说明:完成任务投递回调
* @author chenniang
* @DataTime: 2021-07-02 18:16
*/
public function onFinish($serv, $task_id, $data) {
//task_worker进程将任务处理结果发送给worker进程
echo "完成任务{$task_id}投递 处理结果:{$data}";
}
/**
* @param $ws
* @param $fd
* @功能说明:关闭连接回调
* @author chenniang
* @DataTime: 2021-07-02 18:16
*/
public function onClose($ws, $fd) {
//退出并删除多余的分组fd
$group = $this->redis->sMembers('group');
foreach ($group as $v) {
$fangjian = $this->redis->hgetall($v);
foreach ($fangjian as $k => $vv) {
if ($fd == $vv) {
$this->redis->hdel($v, $vv);
}
}
}
// echo "{$fd}关闭了连接1";
}
/**
* @param $ws
* @param $fd
* @功能说明:解散群
* @author chenniang
* @DataTime: 2021-07-27 18:04
*/
public function allLoginOut($ws,$data,$fd){
$room_key = $data['data']['room_key'];
$fangjian = $this->redis->hgetall($room_key);
$im_model = new BrochureIm();
$data['action'] = 'mOnMessage';
$data['data']['message_type'] = 2;
//给剩下的人发消息
$this->mOnMessage($ws,$data,$fd);
$bIm_model = new BrochureIm();
$dis = [
'room_key' => $room_key,
];
//修改演示状态
$bIm_model->where($dis)->update(['status'=>3]);
if(!empty($fangjian)){
foreach ($fangjian as $k => $vv) {
$this->redis->Hdel($room_key,$k);
$dis = [
'user_id' => $k,
'room_key'=> $room_key
];
$find = $im_model->dataInfo($dis);
if(!empty($find)&&$find['status']>1){
$time_long = time()-$find['update_time'];
$im_model->dataUpdate($dis,['time_long'=>$time_long+$find['time_long']]);
}
}
//删除房间
@$this->redis->sRem('group',$room_key);
}
// if(!empty($data['data']['url'])){
//
// $url = $data['data']['url'];
// //合并录音
// $im_model->addAudio($room_key,$url);
// }
}
/**
* @param $ws
* @param $fd
* @功能说明:退出
* @author chenniang
* @DataTime: 2021-07-23 17:44
*/
public function loginOut($ws, $fd){
$im_model = new BrochureIm();
//退出并删除多余的分组fd
$group = $this->redis->sMembers('group');
if(!empty($group)){
foreach ($group as $v) {
$fangjian = $this->redis->hgetall($v);
$data['data']['room_key'] = $v;
if(!empty($fangjian)){
foreach ($fangjian as $k => $vv) {
if ($fd == $vv) {
$this->redis->Hdel($v,$k);
$dis = [
'user_id' => $k,
'room_key'=> $v
];
$find = $im_model->dataInfo($dis);
if(!empty($find)&&$find['status']>1){
$time_long = time()-$find['update_time'];
$im_model->dataUpdate($dis,['time_long'=>$time_long+$find['time_long']]);
}
$data['action'] = 'onLogin';
//给剩下的人发消息
$this->onLogin($ws,$data,$fd);
}
}
}else{
@$this->redis->sRem('group',$v);
}
}
}
}
/**
* @param $ws
* @param $fd
* @功能说明:退出
* @author chenniang
* @DataTime: 2021-07-23 17:44
*/
public function loginOutV2($ws, $fd){
$im_model = new BrochureIm();
//退出并删除多余的分组fd
$group = $this->redis->sMembers('group');
foreach ($group as $v) {
$fangjian = $this->redis->hgetall($v);
$key = $v.'-leader';
//获取群组的用户id
$leader_id = $this->redis->get($key);
//当前用户的id
$user_id = array_search($fd,$fangjian);
//如果是群组则全部退出
$is_all = !empty($user_id)&&$leader_id==$user_id?1:0;
$data['data']['room_key'] = $v;
//修改房间状态
if($is_all==1){
$start_key = $v.'-is_start';
$this->redis->set($start_key,0);
$data['action'] = 'mOnMessage';
$data['data']['message_type'] = 2;
//给剩下的人发消息
$this->mOnMessage($ws,$data,$fd);
}
if(!empty($fangjian)){
foreach ($fangjian as $k => $vv) {
if ($fd == $vv||$is_all==1) {
$this->redis->hdel($v, $k);
$dis = [
'user_id' => $k,
'room_key'=> $v
];
$find = $im_model->dataInfo($dis);
if(!empty($find)){
$time_long = time()-$find['update_time'];
$im_model->dataUpdate($dis,['time_long'=>$time_long+$find['time_long']]);
}
}
}
}else{
@$this->redis->sRem('group',$v);
}
//如果是群主断开链接
if($is_all==0){
$data['action'] = 'onLogin';
//给剩下的人发消息
$this->onLogin($ws,$data,$fd);
}
}
}
}

82
app/im/controller/Tcp.php Normal file
View File

@@ -0,0 +1,82 @@
<?php
// +----------------------------------------------------------------------
// | Longbing [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright Chengdu longbing Technology Co., Ltd.
// +----------------------------------------------------------------------
// | Website http://longbing.org/
// +----------------------------------------------------------------------
// | Sales manager: +86-13558882532 / +86-13330887474
// | Technical support: +86-15680635005
// | After-sale service: +86-17361005938
// +----------------------------------------------------------------------
use Swoole\WebSocket\Server;
use think\facade\Cache;
class Tcp {
public $server;
public $redis;
public $key;
public function __construct() {
if(empty($this->redis)){
$this->redis = new Redis();
$this->redis ->connect('127.0.0.1',6379);
}
//创建Server对象监听 127.0.0.1:9501 端口
$server = new \Swoole\Server('127.0.0.1', 9501);
// $this->server->set(array(
//
// 'reactor_num' => 2, //reactor thread num
//
// 'worker_num' => 4, //worker process num
//
// 'backlog' => 128, //listen backlog
//
// 'max_request' => 50,
//
// 'dispatch_mode' => 1,
//
//// 'daemonize' => 1
//
// ));
//监听连接进入事件
$server->on('Connect', function ($server, $fd) {
echo "Client: Connect.\n";
});
//监听数据接收事件
$server->on('Receive', function ($server, $fd, $reactor_id, $data) {
$server->send($fd, "Server: {$data}");
});
//监听连接关闭事件
$server->on('Close', function ($server, $fd) {
echo "Client: Close.\n";
});
//启动服务器
$server->start();
}
}
new Tcp();

View File

@@ -0,0 +1,142 @@
<?php
// +----------------------------------------------------------------------
// | Longbing [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright Chengdu longbing Technology Co., Ltd.
// +----------------------------------------------------------------------
// | Website http://longbing.org/
// +----------------------------------------------------------------------
// | Sales manager: +86-13558882532 / +86-13330887474
// | Technical support: +86-15680635005
// | After-sale service: +86-17361005938
// +----------------------------------------------------------------------
use Swoole\WebSocket\Server;
use think\facade\Cache;
class WebsocketTest {
public $server;
public $redis;
public $key;
public function __construct() {
$this->key = '122345446';
if(empty($this->redis)){
$this->redis = new Redis();
$this->redis ->connect('127.0.0.1',6379);
}
$this->server = new Swoole\WebSocket\Server("0.0.0.0", 9501);
$this->server->set(array(
'reactor_num' => 2, //reactor thread num
'worker_num' => 4, //worker process num
'backlog' => 128, //listen backlog
'max_request' => 50,
'dispatch_mode' => 1,
// 'daemonize' => 1
));
$this->server->on('open', function (swoole_websocket_server $server, $request) {
//加入房间域
$this->redis->hset($this->key,$request->fd,$request->fd);
//加入组集合
$this->redis->sadd('group', $this->key);
});
$this->server->on('message', function (Swoole\WebSocket\Server $server, $frame) {
// echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
$group = $this->redis->sMembers('group');
foreach ($group as $v) {
$fangjian = $this->redis->hGetAll($v);
foreach ($fangjian as $k => $vv) {
$server->push($vv, count($fangjian).$frame->fd);
}
}
});
$this->server->on('close', function ($server, $fd) {
$this->redis->hdel($this->key, 2);
//echo "client {$fd} closed\n";
//退出并删除多余的分组fd
$group = $this->redis->sMembers('group');
foreach ($group as $v) {
$fangjian = $this->redis->hgetall($v);
foreach ($fangjian as $k => $vv) {
// if ($fd == $vv) {
$this->redis->hdel($v, $vv);
// }
}
}
});
//
$this->server->on('request', function ($request, $response) {
// 接收http请求从get获取message参数的值给用户推送
// $this->server->connections 遍历所有websocket连接用户的fd给所有用户推送
foreach ($this->server->connections as $fd) {
// 需要先判断是否是正确的websocket连接否则有可能会push失败
if ($this->server->isEstablished($fd)) {
$this->server->push($fd, '11');
}
}
});
$this->server->start();
}
}
new WebsocketTest();

197
app/im/controller/Ws.php Normal file
View File

@@ -0,0 +1,197 @@
<?php
namespace app\im\controller;
use app\im\controller\MessageHandlerV2;
use app\material\model\BrochureIm;
use Exception;
use Swoole\WebSocket\Server;
use think\App;
use think\facade\Config;
use think\session\driver\Cache;
class Ws {
public $ws = null;
public $server;
public $redis;
public $key;
public $messageHandler;
public function __construct() {
// $this->key = '1223454461';
// 加载框架里面的文件
require __DIR__ . '/../../../vendor/autoload.php';
$http = ( new App() )->http;
$response = $http->run();
$this->ws = new Server("0.0.0.0", Config::get('swoole.server.mport'));
$this->ws->set([
//worker进程数
'worker_num' => 4,
//task进程数
'task_worker_num' => 4,
//listen backlog
'backlog' => 128,
'max_request' => 50,
//心跳检测 每隔多少秒,遍历一遍所有的连接
'heartbeat_check_interval' => 30,
//心跳检测 最大闲置时间超时触发close并关闭
'heartbeat_idle_time' => 65,
// 总开关用来开启tcp_keepalive
'open_tcp_keepalive' => 1,
// 4s没有数据传输就进行检测
'tcp_keepidle' => 10,
// 4s没有数据传输就进行检测
'tcp_keepcount' => 10,
// 1s探测一次即每隔1s给客户端发一个包然后客户端可能会回一个ack的包如果服务端收到了这个ack包那么说明这个连接是活着的'tcp_keepcount' => 5,
// 探测的次数超过5次后客户端还没有回ack包那么close此连接
'tcp_keepinterval' => 5,
'log_file' => '/www/wwwroot/swoole.log',
'daemonize' => 1
]);
$this->ws->on("open", [$this, 'onOpen']);
$this->ws->on("message", [$this, 'onMessage']);
$this->ws->on("task", [$this, 'onTask']);
$this->ws->on("finish", [$this, 'onFinish']);
$this->ws->on("close", [$this, 'onClose']);
$this->ws->on('workerStart' ,[$this ,'onWorkerStart']);
$this->ws->start();
}
public function onWorkerStart()
{
$this->messageHandler = new Some();
}
/**
* @param $ws
* @param $request
* @功能说明:建立连接回调
* @author chenniang
* @DataTime: 2021-07-02 18:17
*/
public function onOpen($ws, $request) {
$request->get['action'] = !empty($request->get['action'])?$request->get['action']:'mOnOpen';
if(method_exists($this->messageHandler, $request->get['action']))
{
// try{
call_user_func([$this->messageHandler, $request->get['action']] , $request->get,$request->fd);
// }catch(Exception $e) {
//
// }
}
// echo FILE_UPLOAD_PATH;
}
/**
* @param $ws
* @param $frame
* @功能说明:接受消息回调
* @author chenniang
* @DataTime: 2021-07-02 18:17
*/
public function onMessage($ws, $frame) {
$data = @json_decode($frame->data,true);
if(is_array($data)){
if(method_exists($this->messageHandler, $data['action']))
{
// try{
call_user_func([$this->messageHandler, $data['action']] ,$ws,$data,$frame->fd);
// }catch(Exception $e) {
//
// }
}
}
}
/**
* @param $serv
* @param $task_id
* @param $worker_id
* @param $data
* @功能说明:完成异步任务回调
* @author chenniang
* @DataTime: 2021-07-02 18:17
*/
public function onTask($serv, $task_id, $worker_id, $data) {
//返回字符串给worker进程——>触发onFinish
return "success";
}
/**
* @param $serv
* @param $task_id
* @param $data
* @功能说明:完成任务投递回调
* @author chenniang
* @DataTime: 2021-07-02 18:16
*/
public function onFinish($serv, $task_id, $data) {
//task_worker进程将任务处理结果发送给worker进程
echo "完成任务{$task_id}投递 处理结果:{$data}";
}
/**
* @param $ws
* @param $fd
* @功能说明:关闭连接回调
* @author chenniang
* @DataTime: 2021-07-02 18:16
*/
public function onClose($ws, $fd) {
// try{
call_user_func([$this->messageHandler, 'loginOut'] ,$ws, $fd);
// }catch(Exception $e) {
//
// }
// echo "{$fd}关闭了连接1";
}
}
$obj = new Ws();

82
app/im/controller/net.php Normal file
View File

@@ -0,0 +1,82 @@
<?php
//SOCKET
//
class net
{
public $socket = 0;
//func
function listen($ip, $port)
{
$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($this->socket, $ip, $port);
$ex = socket_listen($this->socket, 4);
//socket_bind($this->socket, '127.0.0.1', $port) or die("socket_bind() fail:" . socket_strerror(socket_last_error()) . "/n");
//$ex = socket_listen($this->socket, 4) or die("socket_listen() fail:" . socket_strerror(socket_last_error()) . "/n");
return $ex;
}
function accept()
{
return socket_accept($this->socket);
}
function close()
{
if($this->socket == 0) return;
socket_close($this->socket);
$this->socket = 0;
}
function send_bytes($cs, $bytes)
{
$str = $this->bytes_to_string($arr);
$ex = $this->send($cs, $str);
return $ex;
}
function recv_bytes($cs, $len = 1024)
{
$ret = $this->recv($cs, $len);
$bytes = $this->string_to_bytes($ret);
return $bytes;
}
function send($cs, $msg)
{
$ex = socket_write($cs, $msg);
return $ex;
}
function recv($cs, $len = 1024)
{
$ret = socket_read($cs, $len);
return $ret;
}
///accessibility
function bytes_to_string($bytes)
{
$str = '';
for($i=0; $i<count($bytes); $i++)
{
$str .= chr($bytes[$i]);
}
return $str;
}
function string_to_bytes($str)
{
$bytes = array();
for($i=0; $i<strlen($str); $i++)
{
$bytes[] = ord($str[$i]);
}
return $bytes;
}
}
?>

View File

@@ -0,0 +1,61 @@
<?php
//include 'crc.php';
include 'net.php';
//打印十六进制(可以不用)
function println($bytes) {
for($i=0;$i<count($bytes);$i++)
{
printf("%02X ", $bytes[$i]);
}
printf(".");
}
//这里开始
$net = new net();
$net->listen('192.168.1.55', 50000);
while(true) {
$cs = $net->accept();
while($cs) {
try{
$ret = $net->recv_bytes($cs, 1024);
abc($ret);
//println($ret);
}
catch (Exception $e)
{
//printf('cs close');
break;
}
}
}
$net->close();
//abc处理读取到的卡4字节
function abc($ret)
{
$len = $ret[4];
if($len < 14)
{
//printf('无效数据');
return ;
}
//
$count = $ret[9];
$count = ($count - 3) / 4;
//
for($i=0; $i<$count; $i++)
{
$idx = 10 + ($i * 4);
$card = sprintf("%02X%02X%02X%02X", $ret[$idx+0], $ret[$idx+1], $ret[$idx+2], $ret[$idx+3]);//这是获取到的卡数据(按文档意思可能会读到多张卡,处理这个$card就可以了
printf('card['.$i.']>>'.$card.' | ');
}
}
?>

5
app/im/event.php Normal file
View File

@@ -0,0 +1,5 @@
<?php
// 这是系统自动生成的im应用event定义文件
return [
];

42
app/im/info/Info.php Normal file
View File

@@ -0,0 +1,42 @@
<?php
// +----------------------------------------------------------------------
// | Longbing [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright Chengdu longbing Technology Co., Ltd.
// +----------------------------------------------------------------------
// | Website http://longbing.org/
// +----------------------------------------------------------------------
// | Sales manager: +86-13558882532 / +86-13330887474
// | Technical support: +86-15680635005
// | After-sale service: +86-17361005938
// +----------------------------------------------------------------------
declare(strict_types=1);
return [
//模块名称[必填]
'name' => 'im',
//模块标题[必填]
'title' =>'即时通讯',
//内容简介
'desc' =>'',
//封面图标
'icon' =>'',
//模块类型[必填] model:模块 可以出现在左侧一级 app:应用中心 , 是一个应用中心的应用
'type' => 'model',
// 模块唯一标识[必填],格式:模块名.开发者标识.module
'identifier' => 'im.longbing.module',
// 版本[必填],格式采用三段式:主版本号.次版本号.修订版本号
'version' => '1.0.2',
// 模块依赖[可选],格式[[模块名, 模块唯一标识, 依赖版本, 对比方式]]
'need_module' => [
['admin', 'admin.longbing.module', '1.0.0']
],
// 应用依赖[可选],格式[[插件名, 应用唯一标识, 依赖版本, 对比方式]]
'need_app' => [],
//订阅消息
'tmpl_name'=>['im_msg']
];

View File

@@ -0,0 +1,71 @@
<?php
// +----------------------------------------------------------------------
// | Longbing [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright Chengdu longbing Technology Co., Ltd.
// +----------------------------------------------------------------------
// | Website http://longbing.org/
// +----------------------------------------------------------------------
// | Sales manager: +86-13558882532 / +86-13330887474
// | Technical support: +86-15680635005
// | After-sale service: +86-17361005938
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\im\info;
use longbingcore\permissions\PermissionAbstract;
/**
* 模块功能权限
* Class PermissionSendmsg
*/
class PermissionIm extends PermissionAbstract {
const tabbarKey = null;
//后台管理菜单对应key[必填] , 当前模块文件夹名称
const adminMenuKey = 'im';
public $saasKey ;
const apiPaths = [];
public function __construct(int $uniacid,$infoConfigOptions = [])
{
parent::__construct($uniacid, self::tabbarKey, self::adminMenuKey, $this->saasKey, self::apiPaths , $infoConfigOptions);
}
/**
* 返回saas端授权结果
* @return bool
*/
public function sAuth(): bool
{
return true ;
}
/**
* 返回p端授权结果
* @return bool
*/
public function pAuth(): bool
{
return true;
}
/**
* 返回c端授权结果
*
* @param int $user_id
* @return bool
* @author ArtizanZhang
* @DataTime: 2019/12/9 17:13
*/
public function cAuth(int $user_id): bool
{
return true;
}
}

82
app/im/info/Subscribe.php Normal file
View File

@@ -0,0 +1,82 @@
<?php
// +----------------------------------------------------------------------
// | Longbing [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright Chengdu longbing Technology Co., Ltd.
// +----------------------------------------------------------------------
// | Website http://longbing.org/
// +----------------------------------------------------------------------
// | Sales manager: +86-13558882532 / +86-13330887474
// | Technical support: +86-15680635005
// | After-sale service: +86-17361005938
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\im\info;
use app\card\model\CardCount;
use app\radar\model\RadarMessage;
use app\radar\model\RadarOrder;
use longbingcore\diy\BaseSubscribe;
/**
* @author shuixian
* @DataTime: 2019/12/11 16:23
* Class Subscribe
* @package app\ucenter\info
*/
class Subscribe extends BaseSubscribe
{
/**
* 相应个人中心工具菜单
*
* @return mixed
* @author shuixian
* @DataTime: 2019/12/12 11:24
*/
public function onAddWorkStaffCenterMenu(){
$toolsMenu= [
"title" => '话术库管理',
"icon" => 'iconhuashuku',
"link" => '/admin/pages/speech/index',
"linkType"=> '4',
];
return [$toolsMenu];
}
/**
* 员工 客户获取列表查询
*
* @param $data
* @return array
* @author shuixian
* @DataTime: 2019/12/26 10:30
*/
public function onStaffCustomerList($data)
{
// 聊天数量
$map1 = [ [ 'user_id', '=', $data[ 'uid' ] ], [ 'target_id', '=', $data['to_uid'] ] ];
$map2 = [ [ 'target_id', '=', $data[ 'uid' ] ], [ 'user_id', '=', $data['to_uid'] ] ];
$messageCount = RadarMessage::whereOr( [ $map1, $map2 ] )->count();
$msgData[ 'count' ] = $messageCount;
$msgData[ 'title' ] = "聊天";
// 通话数量
$phoneCount = CardCount::where( [ [ 'user_id', '=', $data[ 'uid' ] ], [ 'to_uid', '=', $data['to_uid'] ],
[ 'sign', '=', 'copy' ], [ 'type', 'in', [ 2, 3, 11 ] ] ]
)->count();
$phoneData[ 'count' ] = $phoneCount;
$phoneData[ 'title' ] = "通话";
return [$msgData , $phoneData];
}
}

30
app/im/info/UpdateSql.php Normal file
View File

@@ -0,0 +1,30 @@
<?php
//获取表前缀
$prefix = longbing_get_prefix();
//每个一个sql语句结束都必须以英文分号结束。因为在执行sql时需要分割单个脚本执行。
//表前缀需要自己添加{$prefix} 以下脚本被测试脚本
$sql = <<<updateSql
CREATE TABLE IF NOT EXISTS `{$prefix}longbing_card_message_friend` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(10) NOT NULL COMMENT '发送消息用户id',
`friend_id` int(10) NOT NULL COMMENT '接收消息用户id',
`message_type` varchar(50) NOT NULL DEFAULT 'text',
`lastmessage` text COMMENT '消息内容',
`not_read_message_count` int(11) NOT NULL DEFAULT '0' COMMENT '未读消息数量',
`uniacid` int(10) NOT NULL,
`create_time` int(11) NOT NULL DEFAULT '0',
`update_time` int(11) NOT NULL DEFAULT '0',
`is_read` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `chat_id` (`user_id`,`friend_id`,`create_time`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=175 DEFAULT CHARSET=utf8mb4 COMMENT='名片--聊天记录表';
ALTER TABLE `{$prefix}longbing_card_message_friend` ADD COLUMN `is_read` tinyint(1) NOT NULL DEFAULT 0;
updateSql;
return $sql;

14
app/im/lang/zh-cn.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
return [
'hello thinkphp' => '欢迎使用ThinkPHP',
'data type error' => '数据类型错误',
'test' => '你好啊',
'picture' => '图片',
'audio' => '音频',
'vedio' => '视频',
'Hello, I am ' => '您好,我是',
', May I help you? Please contact me!' => ',有什么可以帮到您的吗?记得联系我!',
'not chat id ,please check param' => '没有关系数据,请检查传入参数。',
'my reply' => '自定义话术',
'login error' => '登陆失败',
];

5
app/im/middleware.php Normal file
View File

@@ -0,0 +1,5 @@
<?php
// 这是系统自动生成的im应用middleware定义文件
return [
];

59
app/im/model/ImChart.php Normal file
View File

@@ -0,0 +1,59 @@
<?php
namespace app\im\model;
use app\BaseModel;
use think\facade\Db;
class ImChart extends BaseModel
{
protected $name = 'longbing_card_chart';
//创建
public function createChart($data)
{
$data['create_time'] = time();
return $this->createRow($data);
}
//更新
public function updateChart($filter ,$data)
{
$filter['deleted'] = 0;
return $this->updateRow($filter ,$data);
}
//获取列表
public function listChart($filter)
{
$filter['deleted'] = 0;
$result = $this->where($filter)->select();
if(!empty($result)) $result = $result->toArray();
return $result;
}
//获取总数
public function listChartCount($filter)
{
$filter['deleted'] = 0;
return $this->where($filter)->count();
}
//获取详情
public function getChart($filter)
{
$filter['deleted'] = 0;
return $this->getRow($filter);
}
//删除
public function delChart($filter)
{
$filter['deleted'] = 0;
return $this->delRow($filter);
}
//真删除
public function destoryChart($filter)
{
return $this->destoryRow($filter);
}
}

122
app/im/model/ImChat.php Normal file
View File

@@ -0,0 +1,122 @@
<?php
namespace app\im\model;
use app\BaseModel;
use think\facade\Db;
class ImChat extends BaseModel
{
//定义表名称
protected $name = 'longbing_card_chat';
//获取用户信息
// public function customer()
// {
// return $this->hasOne('ImCustomer' ,)
// }
//创建
public function createChat($data)
{
$data['create_time'] = time();
$result = $this->save($data);
if(!empty($result)) $result = $this->id;
return $result;
}
//更新
public function updateChat($filter ,$data)
{
$filter['deleted'] = 0;
return $this->updateRow($filter ,$data);
}
//获取列表
public function listChat($user_id , $uniacid,$page_config)
{
$start_row = 0;
$page_count = 10;
if(isset($page_config['page_count']) && !empty($page_config['page_count']) && $page_config['page_count'] > 0) $page_count = $page_config['page_count'];
if(isset($page_config['page']) && !empty($page_config['page']) && $page_config['page'] > 0) $start_row = ($page_config['page'] -1) * $page_count;
$result = $this->where(function ($query) use ($user_id) {
$query->whereOr(['target_id' => $user_id , 'user_id' => $user_id]) ;
})
->where(['deleted' => 0 ,'uniacid' => $uniacid])
->order('update_time', 'desc')
->limit($start_row,$page_count)
->select();
// $result = $this->where(['deleted' => 0])
// ->where(function($query) use($user_id) {
// $query->
// })
// ->limit($start_row,$page_count)
// ->select();
if(!empty($result)) $result = $result->toArray();
return $result;
}
//获取总数
public function listChatCount($user_id , $uniacid)
{
return $this->where(function ($query) use ($user_id) {
$query->whereOr(['target_id' => $user_id , 'user_id' => $user_id]) ;
})
->where(['deleted' => 0 ,'uniacid' => $uniacid])
->count();
}
//获取所有
public function listChatAll($user_id ,$uniacid)
{
$result = $this->where(function ($query) use ($user_id) {
$query->whereOr(['target_id' => $user_id] , ['user_id' => $user_id]) ;
})
->where(['deleted' => 0 ,'uniacid' => $uniacid])
->field('id as chat_id,user_id,target_id')
->select();
if(!empty($result)) $result = $result->toArray();
return $result;
}
//获取单个Chat
public function getChat($user_id ,$target_id ,$uniacid)
{
//查询条件1
$where = [
['user_id' , '=' ,$user_id],
['target_id' ,'=' , $target_id],
];
$whereOr = [
['user_id' , '=' ,$target_id],
['target_id' ,'=' , $user_id],
];
$result = $this->where(function ($query) use($where, $whereOr){
$query->whereOr([$where,$whereOr]);
})
->where(['uniacid' => $uniacid ,'deleted' => 0])
->field('id as chat_id,user_id,target_id')
->find();
return $result;
}
//通过id获取chat
public function getChatById($chat_id)
{
$result = $this->where(['id' => $chat_id])->find();
if(!empty($result)) $result = $result->toArray();
return $result;
}
//删除
public function delChat($filter)
{
$filter['deleted'] = 0;
return $this->updateChat($filter ,['deleted' => 0]);
}
//真删除
public function destroyChat($filter)
{
return $this->destroyRow($filter);
}
}

24
app/im/model/ImClient.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
namespace app\im\model;
use app\BaseModel;
class ImClient extends BaseModel
{
//定义表名称
protected $name = 'longbing_card_collection';
//是否是客户
public function isCustomer($user_id ,$customer_id ,$uniacid)
{
$filter = array(
'uid' => $customer_id,
'to_uid' => $user_id,
'uniacid' => $uniacid,
'intention' => 1
);
$result = $this->where($filter)->count();
return !empty($result);
}
}

124
app/im/model/ImMessage.php Normal file
View File

@@ -0,0 +1,124 @@
<?php
namespace app\im\model;
use app\BaseModel;
use think\facade\Db;
class ImMessage extends BaseModel
{
//定义表名称
protected $name = 'longbing_card_message';
//创建聊天消息
public function createMessage($data)
{
$data['create_time'] = time();
return $this->createRow($data);
}
//修改聊天消息
public function updateMessage($filter ,$data)
{
$filter['deleted'] = 0;
return $this->updateRow($filter ,$data);
}
//标记已读消息
public function readMessage($filter)
{
$filter['status'] = 1;
return $this->updateMessage($filter ,['status' => 2]);
}
//撤销消息
public function recallMessage($filter)
{
$filter['deleted'] = 0;
return $this->updateMessage($filter, ['status' => 3]);
}
//查询聊天消息列表
public function listMessage($filter ,$page_config)
{
$start_row = 0;
$page_count = 10;
if(isset($page_config['page_count']) && !empty($page_config['page_count']) && $page_config['page_count'] > 0) $page_count = $page_config['page_count'];
if(isset($page_config['page']) && !empty($page_config['page']) && $page_config['page'] > 0) $start_row = ($page_config['page'] -1) * $page_count;
// $filter['deleted'] = 0;
$result = $this->where($filter)
->where(['deleted'=>0])
->order('id desc')
->limit($start_row ,$page_count)
->select();
if(!empty($result))
{
$result = $result->toArray();
$result = array_reverse($result);
}
return $result;
}
//查询聊天消息列表
public function listMessageV2($filter ,$page_config,$dis)
{
$start_row = 0;
$page_count = 10;
if(isset($page_config['page_count']) && !empty($page_config['page_count']) && $page_config['page_count'] > 0) $page_count = $page_config['page_count'];
if(isset($page_config['page']) && !empty($page_config['page']) && $page_config['page'] > 0) $start_row = ($page_config['page'] -1) * $page_count;
// $filter['deleted'] = 0;
$result = $this->where($filter)
->whereOr(function ($query) use ($dis){
$query->where($dis);
})
->order('id desc')
->limit($start_row ,$page_count)
->select();
if(!empty($result))
{
$result = $result->toArray();
$result = array_reverse($result);
}
return $result;
}
//获取聊天消息总量
public function listMessageCount($filter)
{
$filter['deleted'] = 0;
$count = $this->where($filter)->count();
return $count;
}
//删除聊天消息
public function delMessage($filter)
{
$filter['deleted'] = 0;
return $this->deleteRow($filter);
}
//查询最后一条消息
public function lastMessage($filter)
{
$filter['deleted'] = 0;
$result = $this->where($filter)->order('create_time', 'desc')->field(['create_time' ,'content' ,'message_type'])->find();
return $result;
}
//获取未读消息列表
public function listNotReadMessage($filter)
{
$filter['deleted'] = 0;
$filter['status'] = 1;
$result = $this->where($filter)
->order('create_time' ,'asc')
->select();
if(!empty($result)) $result = $result->toArray();
$this->updateMessage($filter, ['status' =>2]);
return $result;
}
//真删除
public function destroyMessage($filter)
{
return $this->destoryRow($filter);
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace app\im\model;
use app\BaseModel;
class ImMessageFriend extends BaseModel
{
//定义表名称
protected $name = 'longbing_card_message_friend';
}

View File

@@ -0,0 +1,82 @@
<?php
namespace app\im\model;
use app\BaseModel;
class ImMyReply extends BaseModel
{
//定义表名称
protected $name = 'longbing_card_quick_reply';
public function searchContentAttr($query, $value, $data)
{
$query->where('content','like', '%' . $value . '%');
}
public function searchUserIdAttr($query, $value, $data)
{
$query->where('user_id','=', $value);
}
public function searchUniacidAttr($query, $value, $data)
{
$query->where('uniacid','=', $value);
}
public function type()
{
return $this->hasOne('ImReplyType' ,'id' ,'type');
}
//创建话术
public function createReply($data)
{
$data['create_time'] = time();
$result = $this->save($data);
return !empty($result);
}
//更新话术
public function updateReply($filter ,$data)
{
$data['update_time'] = time();
$result = $this->where($filter)->update($data);
return !empty($result);
}
//获取话术列表
public function listReply($filter)
{
$result = $this->where($filter)
->select();
if(!empty($result)) $result = $result->toArray();
return $result;
}
//获取话术列表(分页)
public function listReplys($filter ,$page_config)
{
$result = $this->with(['type'])
->withSearch(['content' ,'user_id' ,'uniacid'] ,$filter)
->order('top' ,'desc')
->page($page_config['page'] ,$page_config['page_count'])
->select();
if(!empty($result)) $result = $result->toArray();
return $result;
}
//获取话术总数
public function getReplyCount($filter)
{
$result = $this->withSearch(['content' ,'user_id' ,'uniacid'] ,$filter)->count();
if(empty($result)) $result = 0;
return $result;
}
//删除话术
public function deleteReply($filter)
{
return $this->destoryReply($filter);
}
//删除(真删除)
public function destoryReply($filter)
{
$result = $this->where($filter)->delete();
return !empty($result);
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace app\im\model;
use app\BaseModel;
class ImReplyType extends BaseModel
{
//定义表名称
protected $name = 'longbing_card_reply_type';
public function searchTitleAttr($query, $value, $data)
{
$query->where('title','like', '%' . $value . '%');
}
public function searchUniacidAttr($query, $value, $data)
{
$query->where('uniacid','=', $value );
}
public function reply()
{
return $this->belongsTo('ImMyReply' ,'id' ,'type');
}
//创建话术
public function createType($data)
{
$data['create_time'] = time();
return $this->save($data);
}
//更新话术
public function updateType($filter ,$data)
{
$data['update_time'] = time();
$result = $this->where($filter)->update($data);
return !empty($result);
}
//获取话术列表
public function listType($filter ,$page_config = ['page' => 1 ,'page_count' => 20])
{
$result = $this->withSearch(['title' ,'uniacid'] ,$filter)
->page($page_config['page'] ,$page_config['page_count'])
->order('top desc, id desc')
->select();
if(!empty($result)) $result = $result->toArray();
return $result;
}
//获取话术列表
public function getTypeCount($filter)
{
$result = $this->withSearch(['title' ,'uniacid'] ,$filter)
->count();
if(empty($result)) $result = 0;
return $result;
}
//删除话术
public function delType($filter)
{
$result = $this->where($filter)->delete();
return !empty($result);
}
public function listAllType($filter)
{
$result = $this->where($filter)
->order('top' ,'desc')
->select();
if(empty($result)) $result = $result->toArray();
return $result;
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace app\im\model;
use app\BaseModel;
class ImReplyType extends BaseModel
{
//定义表名称
protected $name = 'longbing_card_reply_type';
//创建话术
public function createReply($data)
{
return $this->createRow($data);
}
//更新话术
public function updateReply($filter ,$data)
{
return $this->updateRow($filter ,$data);
}
//获取话术列表
public function listReply($filter)
{
$filter['deleted'] = 0;
$result = $this->where($filter)
->select();
if(!empty($result)) $result = $result->toArray();
return $result;
}
//删除话术
public function delReply($filter)
{
return $this->deleteRow($filter);
}
}

19
app/im/model/ImUser.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
namespace app\im\model;
use app\BaseModel;
class ImUser extends BaseModel
{
//定义表名称
protected $name = 'longbing_card_user';
//获取用户信息
public function getUser($filter)
{
$filter['deleted'] = 0;
$result = $this->where($filter)->find();
if(!empty($result)) $result = $result->toArray();
return $result;
}
}

5
app/im/provider.php Normal file
View File

@@ -0,0 +1,5 @@
<?php
// 这是系统自动生成的im应用provider定义文件
return [
];

51
app/im/route/route.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
use think\facade\Route;
/**
* @model im
* @author yangqi
* @create time 2019年11月25日23:09:59
*
*/
Route::group('admin' ,function() {
});
Route::group('app' ,function() {
Route::post('listCustomer' , 'im/listCustomer');
Route::post('listCustomerV2' , 'im/listCustomerV2');
Route::get('listNotReadMessage' , 'im/listNotReadMessage');
Route::get('listMessage' , 'im/listMessage');
Route::get('listReply' , 'im/listReply');
Route::post('addReply' , 'im/addReply');
Route::get('delReply' , 'im/delReply');
//获取IM签名
Route::get('getTimUserSig' , 'im/getTimUserSig');
//保存发送成功的消息
Route::post('sendMessage' , 'im/sendMessage');
Route::post('readMessage' , 'im/readMessage');
//获取目标客户给我发送的消息数量
Route::post('getCustomerUnReadMessageCount' , 'im/getCustomerUnReadMessageCount');
//修改消息状态 1都可见 2删除对方可见 撤回都不可见
Route::post('updateMsgStatus' , 'im/updateMsgStatus');
});
Route::any('im/listCustomer' , 'im/listCustomer');
Route::any('im/listNotReadMessage' , 'im/listNotReadMessage');
Route::any('im/listMessage' , 'im/listMessage');
Route::any('im/listReply' , 'im/listReply');
Route::any('im/addReply' , 'im/addReply');
Route::any('im/delReply' , 'im/delReply');
Route::any('listCustomer' , 'im/listCustomer');
Route::any('listNotReadMessage' , 'im/listNotReadMessage');
Route::any('listMessage' , 'im/listMessage');
Route::any('listReply' , 'im/listReply');
Route::any('addReply' , 'im/addReply');
Route::any('delReply' , 'im/delReply');

View File

@@ -0,0 +1,395 @@
<?php
// +----------------------------------------------------------------------
// | Longbing [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright Chengdu longbing Technology Co., Ltd.
// +----------------------------------------------------------------------
// | Website http://longbing.org/
// +----------------------------------------------------------------------
// | Sales manager: +86-13558882532 / +86-13330887474
// | Technical support: +86-15680635005
// | After-sale service: +86-17361005938
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\im\service;
use app\Common\service\LongbingUserService;
use app\im\model\ImChat;
use app\im\model\ImMessage;
use app\im\model\ImMessageFriend;
use longbingcore\tools\LongbingDefault;
class ImMessageFriendService
{
/**
* @param $uniacid
* @param $userId
* @param int $page
* @param int $page_count
* @功能说明:获得用户的好友列表
* @author jingshuixian
* @DataTime: 2020/1/16 14:51
*/
public static function getFriendList($uniacid , $userId ,$page_count = 10 ){
$imMessageFriend = new ImMessageFriend() ;
$message_model = new ImMessage();
$where[] = [ 'user_id' , '=' , $userId ];
$friendList = $imMessageFriend->where($where)->order('is_read desc , update_time desc' )->paginate($page_count);
foreach ($friendList as $key => &$friend ){
$friendId = $friend['friend_id'] ;
$customer = longbingGetUser($friendId , $uniacid );
//判断客户是否是员工
if(isset($customer['is_staff']) && !empty($customer['is_staff']))
{
$customer_info = longbingGetUserInfo($friendId , $uniacid );
if(isset($customer_info['is_staff']) && !empty($customer_info['is_staff']))
{
if(!empty($customer_info['avatar'])) {
$customer_info = transImagesOne($customer_info ,['avatar'] , $uniacid );
}
//是员工 就用员工头像 By.jingshuixian
if(!empty($customer_info['avatar'])) $customer['avatarUrl'] = $customer_info['avatar'];
$customer['nickName'] = empty($customer_info['name']) ? $customer['nickName'] : $customer_info['name'];
}
}
//没有头像就给一个默认头像
$customer['avatarUrl'] = empty($customer['avatarUrl']) ? LongbingDefault::$avatarImgUrl : $customer['avatarUrl'];
$friend['customer'] = $customer ;
$friend['target_id'] = $friendId ;
$friend['not_read_message_count'] = self::notReadCount($friend) ;
$last_msg = self::getLastMsg($friend);
//兼容老数据格式
$friend['lastmessage'] = [
'message_type' => !empty($last_msg)?$last_msg['message_type']:'text',
'content' => !empty($last_msg)?$last_msg['content']:'',
'is_show' => !empty($last_msg)?$last_msg['is_show']:1,
'is_self' => !empty($last_msg)&&$last_msg['user_id'] == $friend['user_id']?1:0
];
$friend['time'] = date('Y-m-d H:i:s', $friend['update_time']);
}
return empty($friendList) ? [] : $friendList->toArray() ;
}
/**
* @author chenniang
* @DataTime: 2021-05-27 16:10
* @功能说明:后去最后一条消息(除开自己删除的)
*
*
*/
public static function getLastMsg($friend){
$message_model = new ImMessage();
//自己接收的
$dis = [
'user_id' => $friend['friend_id'],
'target_id' => $friend['user_id']
];
$where = [];
//自己发送的
$where[] = ['user_id','=',$friend['user_id']];
$where[] = ['target_id','=',$friend['target_id']];
//要除开删除的
$where[] = ['is_show','<>',2];
// $where[] = ['target_is_show','<>',2];
$last_msg = $message_model->where($dis)->where('target_is_show','<>',2)->whereOr(function ($query) use ($where) {
$query->where($where);
})->order('create_time desc')->find();
return !empty($last_msg)?$last_msg->toArray():[];
}
/**
* @author chenniang
* @DataTime: 2021-05-27 16:38
* @功能说明:未读消息读数量
*/
public static function notReadCount($friend){
$message_model = new ImMessage();
//自己接收的
$dis = [
'user_id' => $friend['friend_id'],
'target_id' => $friend['user_id'],
'status' => 1,
'target_is_show' => 1
];
$count = $message_model->where($dis)->count();
return $count;
}
/**
* @param $uniacid
* @param $userId
* @功能说明:老数据转移到新数据上
* @author jingshuixian
* @DataTime: 2020/1/16 14:52
*/
public static function initOldFriendList($uniacid , $userId){
$imMessageFriend = new ImMessageFriend() ;
$where[] = ['uniacid' , '=' , $uniacid ] ;
$where[] = ['user_id' , '=' , $userId ] ;
$friendCount = $imMessageFriend->where($where)->count();
if(! $friendCount){ //没有好友就用message数据导入好友列表
$imMessage = new ImMessage() ;
$whereIm[] = ['uniacid' , '=' , $uniacid ] ;
$whereIm[] = ['status' ,'in' , [ 1,2] ] ;
$whereOr[] = ['user_id' ,'=' ,$userId ] ;
$whereOr[] = ['target_id' ,'=' ,$userId ] ;
$chat_ids = $imMessage->where($whereIm)->where(function ($query) use($whereOr) {
$query->whereOr($whereOr);
})->distinct(true)->field('chat_id')->select();
$friendData = [] ;
foreach ($chat_ids as $key => $item) {
if ($item) {
$chat_id = $item['chat_id'];
$message = $imMessage->where([['uniacid', '=', $uniacid], ['chat_id', '=', intval($chat_id)], ['status', 'in', [1,2] ]])->where(function ($query) use ($whereOr) {
$query->whereOr($whereOr);
})->order('id desc')->find();
//这里代码和 updateFriendByMessage 里的代码,大部分是重复的,只是一个批量插入和一个此插入
if ($message) {
$friendId = $message['user_id'] != $userId ? $message['user_id'] : $message['target_id'];
//判断用户是否存在
if( !LongbingUserService::isUser($uniacid , $friendId) ) continue ;
$friendItem['user_id'] = $userId;
$friendItem['friend_id'] = $friendId;
$friendItem['uniacid'] = $uniacid;
//获取最后一条消息内容
$whereOr = [];
$whereOr[] = ['user_id', '=', $userId];
$whereOr[] = ['target_id', '=', $userId];
$friendItem['message_type'] = $message['message_type'];
$friendItem['lastmessage'] = in_array( $message['message_type'] , ['image' , 'picture' ]) ? '[图片]' :$message['content'];
$friendItem['create_time'] = $message['create_time'];
$friendItem['update_time'] = $message['update_time'];
$friendItem['is_show'] = $message['is_show'];
$notReadMessageCount = $imMessage->where([
['uniacid', '=', $uniacid],
['user_id', '=', $friendId],
['target_id', '=', $userId],
['status', '=', 1]
])->count();
$friendItem['not_read_message_count'] = $notReadMessageCount;
$friendItem['is_read'] = $notReadMessageCount ? 1 : 0 ;
$friendData[] = $friendItem;
}
}
}
$inserCount = $imMessageFriend->insertAll($friendData);
return $inserCount;
}
return false ;
}
/**
* @author jingshuixian
* @DataTime: 2020/1/16 15:03
* @功能说明:根据消息数据更新好友信息
*/
public static function updateFriendByMessage( ImMessage $message ){
if ($message) {
$userId = $message['user_id'] ;
$friendId = $message['target_id'] ;
$uniacid = $message['uniacid'] ;
self::updateFriendByUserIdAndFriend($uniacid , $userId , $friendId ) ;
self::updateFriendByUserIdAndFriend($uniacid , $friendId , $userId ) ;
}
return false ;
}
/**
* @param ImMessage $message
* @功能说明:更新用户好友的关系和未读数据信息
* @author jingshuixian
* @DataTime: 2020/1/16 16:47
*/
public static function updateFriendByUserIdAndFriend( $uniacid , $userId , $friendId){
//判断用户是否存在
if( !LongbingUserService::isUser($uniacid , $userId) && !LongbingUserService::isUser( $uniacid , $friendId) ) return false ;
$imMessage = new ImMessage() ;
$imMessageFriend = new ImMessageFriend() ;
$friendItem['user_id'] = $userId;
$friendItem['friend_id'] = $friendId;
$friendItem['uniacid'] = $uniacid;
//获取最后一条消息内容
$message = ImMessageService::getLastMessage( $uniacid , $userId , $friendId ) ;
if($message){
$friendItem['message_type'] = $message['message_type'];
$friendItem['lastmessage'] = in_array( $message['message_type'] , ['image' ,'picture' ]) ? '[图片]' : $message['content'];
$friendItem['create_time'] = $message['create_time'];
$friendItem['update_time'] = $message['update_time'];
}else{
$friendItem['message_type'] = '';
$friendItem['lastmessage'] = '';
$friendItem['create_time'] = time();
$friendItem['update_time'] = time();
}
//更新我的未读消息
$notReadMessageCount = $imMessage->where([
['uniacid', '=', $uniacid],
['user_id', '=',$friendId ],
['target_id', '=', $userId ],
['status', '=', 1]
])->count();
$friendItem['not_read_message_count'] = $notReadMessageCount;
$friendItem['is_read'] = $notReadMessageCount ? 1 : 0 ;
//判断 消息发送人好友关系
$oneFriend = self::getOneByUserIdAndFriendId($userId,$friendId);
if($oneFriend){
$friendItem['id'] = $oneFriend['id'];
$friendItem['create_time'] = $oneFriend['create_time'];
return $imMessageFriend->update( $friendItem );
}else{
return $imMessageFriend->insert( $friendItem );
}
}
/**
* @param $userId
* @param $friendId
* @功能说明:判断是否是好友关系
* @author jingshuixian
* @DataTime: 2020/1/16 15:12
*/
public static function isFriend($userId , $friendId){
$imMessageFriend = new ImMessageFriend() ;
$where[] = ['user_id' ,'=' ,$userId ] ;
$where[] = ['friend_id' ,'=' ,$friendId ] ;
$count = $imMessageFriend->where($where)->count();
return $count ? true : false;
}
/**
* @param $userId
* @param $friendId
* @功能说明:更新用户ID和朋友ID获取好友关系数据
* @author jingshuixian
* @DataTime: 2020/1/16 15:14
*/
public static function getOneByUserIdAndFriendId($userId , $friendId){
$imMessageFriend = new ImMessageFriend() ;
$where[] = ['user_id' ,'=' ,$userId ] ;
$where[] = ['friend_id' ,'=' ,$friendId ] ;
return $imMessageFriend->where($where)->find() ;
}
/**
* @param $uniacid
* @param $userId
* @param $friendId
* @功能说明:处理好友的已读情况
* @author jingshuixian
* @DataTime: 2020/1/16 17:23
*/
public static function readMessage($uniacid , $userId , $friendId){
$imMessageFriend = new ImMessageFriend() ;
$count = $imMessageFriend->where([ ['uniacid' , '=', $uniacid ] , ['user_id' , '=' ,$userId ] , ['friend_id' , '=' , $friendId ] ])->update([ 'is_read' => 0 , 'not_read_message_count' => 0 ]) ;
return $count;
}
}

View File

@@ -0,0 +1,51 @@
<?php
// +----------------------------------------------------------------------
// | Longbing [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright Chengdu longbing Technology Co., Ltd.
// +----------------------------------------------------------------------
// | Website http://longbing.org/
// +----------------------------------------------------------------------
// | Sales manager: +86-13558882532 / +86-13330887474
// | Technical support: +86-15680635005
// | After-sale service: +86-17361005938
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\im\service;
use app\im\model\ImMessage;
class ImMessageService
{
/**
* @param $uniacid
* @param $userId
* @param $friendId
* @功能说明: 我和好友之间聊天的最后一条记录
* @author jingshuixian
* @DataTime: 2020/1/16 16:57
*/
public static function getLastMessage($uniacid , $userId , $friendId ){
$whereOr1[] = ['user_id' ,'=' , $friendId] ;
$whereOr1[] = ['target_id' ,'=' ,$userId ] ;
$whereOr2[] = ['user_id' ,'=' ,$userId ] ;
$whereOr2[] = ['target_id' ,'=' ,$friendId ] ;
$imMessage = new ImMessage() ;
$message = $imMessage->where([['uniacid', '=', $uniacid] , ['status', 'in', [1,2] ]])->whereOr(function ($query) use ($whereOr1) {
$query->where($whereOr1);
})->whereOr(function ($query) use ($whereOr2) {
$query->where($whereOr2);
})->order('id desc')->find();
return $message ;
}
}

View File

@@ -0,0 +1,244 @@
<?php
// +----------------------------------------------------------------------
// | Longbing [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright Chengdu longbing Technology Co., Ltd.
// +----------------------------------------------------------------------
// | Website http://longbing.org/
// +----------------------------------------------------------------------
// | Sales manager: +86-13558882532 / +86-13330887474
// | Technical support: +86-15680635005
// | After-sale service: +86-17361005938
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\im\service;
use app\Common\LongbingServiceNotice;
use app\Common\model\LongbingUserInfo;
use app\Common\service\LongbingUserInfoService;
use app\Common\service\LongbingUserService;
use app\im\model\ImChat;
use app\im\model\ImMessage;
use app\publics\model\TmplConfig;
use longbingcore\tools\LongbingTime;
use longbingcore\wxcore\WxTmpl;
class ImService
{
/**
* @param $data
* @功能说明:新增消息
* @author jingshuixian
* @DataTime: 2020/1/13 17:01
*/
public static function addMessage($data){
//存储消息
$message_model = new ImMessage();
$result = $message_model->insertGetId( $data );
if($result){
//修改时间chat
$chat_model = new ImChat();
$chat_model->updateChat(['id' => $data['chat_id']] ,[]);
//修改朋友表数据
ImMessageFriendService::updateFriendByMessage($message_model->find($result));
}
return $result;
}
/**
* @param $uniacid
* @param $user_id
* @param $customer_id
* @功能说明:获取聊天房间ID
* @author jingshuixian
* @DataTime: 2020/1/13 17:01
*/
public static function getChatId($uniacid , $user_id ,$target_id )
{
$chat_model = new ImChat();
//查询条件
$where = [
['user_id' , '=' ,$user_id],
['target_id' ,'=' , $target_id],
];
$whereOr = [
['user_id' , '=' ,$target_id],
['target_id' ,'=' , $user_id],
];
$chatId = $chat_model->where(function ($query) use($where, $whereOr){
$query->whereOr([$where,$whereOr]);
})
->where(['uniacid' => $uniacid ,'deleted' => 0])
->field('id as chat_id,user_id,target_id')
->value('id');
if(empty($chatId))
{
$chatData= (['user_id' => $user_id ,'target_id' => $target_id ,'uniacid' => $uniacid ,'create_time' => time()]);
$chatId = $chat_model->createChat($chatData);
}
return $chatId;
}
/**
* @param $userId
* @功能说明:获取未读消息数量
* @author jingshuixian
* @DataTime: 2020/1/13 17:22
*/
public static function getUnReadMessageCount($userId){
$message_model = new ImMessage();
$count = $message_model->listMessageCount(['target_id' => $userId ,'status' => 1]);
return $count;
}
/**
* @param $userId
* @param $target_id
* @功能说明:根据用户ID和目标用户ID获取未读消息数量
* @author jingshuixian
* @DataTime: 2020/1/15 12:10
*/
public static function getUnReadMessageCountByUserIdAndTargetId($userId , $target_id ){
$message_model = new ImMessage();
$count = $message_model->listMessageCount(['user_id'=> $userId ,'target_id' => $target_id ,'status' => 1]);
return $count;
}
/**
* @param $uniacid
* @param $chat_id
* @param $user_id
* @功能说明: 更新消息未读信息,返回修改数量
* @author jingshuixian
* @DataTime: 2020/1/14 9:54
*/
public static function readMessage($uniacid , $user_id , $friendId){
$message_model = new ImMessage();
$count = $message_model->where([
['uniacid' , '=' , $uniacid] ,
['user_id' , '=' , $friendId ] ,
['target_id' , '=' , $user_id ]
])->update([ 'status' => 2 ]) ;
//处理未读消息数据
ImMessageFriendService::readMessage( $uniacid , $user_id , $friendId ) ;
return $count ;
}
/**
* @param $uniacid
* @param $userId
* @param $data
* @param string $page
* @功能说明:发送模板消息
* @author jingshuixian
* @DataTime: 2020/1/14 13:42
*/
public static function sendTmplMsg($uniacid , $userId ,$data , $page='' , $tmpl_name = 'im_msg'){
$openid = LongbingUserService::getUserOpenId($userId);
//模版消息model
$tmpl_model = new TmplConfig();
//获取模版
$tmpl = $tmpl_model->where(['uniacid'=>$uniacid,'tmpl_name'=>$tmpl_name])->find();
//如果未添加模版消息 则不发送
if(empty($tmpl)){
return true;
}else{
$tmpl = $tmpl->toArray();
}
//模版id
$tmpl_id = $tmpl['tmpl_id'];
$service_model = new WxTmpl( $uniacid );
$key_worlds = $service_model::getTmplKey($tmpl_id);
if(!empty($openid)&&!empty($tmpl_id)&&!empty($key_worlds)){
//发送内容
$send_data = [];
foreach ($key_worlds as $key => $item ){
$send_data[$item]['value'] = $data[$key -1 ] ;
}
//模版消息库类
$tmpl_sever = new WxTmpl($uniacid);
//发送模版消息
$res = $tmpl_sever::sendTmpl($openid,$tmpl_id,$send_data,$page);
}
return true;
}
/**
* @param $uniacid
* @param $user_id
* @param $target_id
* @功能说明:发送聊天通知信息
* @author jingshuixian
* @DataTime: 2020/2/27 11:49
*/
public static function sendImMessageTmpl($uniacid , $user_id , $target_id , $message = ''){
if(LongbingUserInfoService::isStraffByUserId($user_id) && !LongbingUserInfoService::isStraffByUserId($target_id)) //发送者是员工并且接收者是普通用户,员工回复消息,通知用户采用订阅消息
{
$message = '有未读私信' ;
$name= $name = LongbingUserInfoService::getNameByUserId($user_id);
ImService::sendTmplMsg($uniacid , $target_id , [ $name , $message , LongbingTime::getChinaNowTime()] , 'pages/user/home' );
}else //发送者是普通用户,消息接收人是员工
{
$count = self::getUnReadMessageCount($target_id);
$message = '有' . $count .'条未读私信' ;
$notice = new LongbingServiceNotice($uniacid);
$name = LongbingUserService::getUserNickNameOpenId($user_id);
$notice->sendImMessageServiceNoticeToStaff($target_id ,$message , $name);
}
}
}

View File