- 管理端前端设备判定改为按宽高比(嵌入竖屏容器时正确使用手机版布局) - 统计上报跨源读取 parent.location 报错防护(降级用 referrer) - 续接会话时校验客服在线,离线不再误入聊天页 - 聊天记录整理与消息发送的用户资料缺失空值防护,避免接口 400 - entrypoint 数据库导入加空库守卫,容器重启/线上更新不再重置数据
236 lines
8.2 KiB
PHP
236 lines
8.2 KiB
PHP
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
|
// +----------------------------------------------------------------------
|
|
// | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
|
|
// +----------------------------------------------------------------------
|
|
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
|
// +----------------------------------------------------------------------
|
|
// | Author: CRMEB Team <admin@crmeb.com>
|
|
// +----------------------------------------------------------------------
|
|
|
|
namespace app\services\chat;
|
|
|
|
|
|
use app\dao\chat\ChatServiceDialogueRecordDao;
|
|
use crmeb\basic\BaseServices;
|
|
use think\App;
|
|
use think\db\exception\DataNotFoundException;
|
|
use think\db\exception\DbException;
|
|
use think\db\exception\ModelNotFoundException;
|
|
use think\facade\Cache;
|
|
|
|
/**
|
|
* Class ChatServiceDialogueRecordServices
|
|
* @package app\services\chat
|
|
* @method whereByCount(array $where) 根据条件获取条数
|
|
* @method getServiceList(array $where, int $page, int $limit, array $field = ['*']) 获取聊天记录并分页
|
|
* @method saveAll(array $data) 插入数据
|
|
* @method getMessageNum(array $where) 获取聊天记录条数
|
|
* @method getMessageList(array $where, int $page, int $limit) 获取聊天记录列表
|
|
* @method getMessageCount(array $where) 获取聊天记录总条数
|
|
* @method getMessageOne(array $where) 获取最新的一条数据
|
|
* @method int chatCount(string $appid, int $userId) 获取是否用户的聊天记录条数
|
|
*/
|
|
class ChatServiceDialogueRecordServices extends BaseServices
|
|
{
|
|
//文本消息类型
|
|
const MSN_TYPE_TXT = 1;
|
|
//表情消息类型
|
|
const MSN_TYPE_EMOT = 2;
|
|
//图片消息类型
|
|
const MSN_TYPE_IME = 3;
|
|
//音频消息类型
|
|
const MSN_TYPE_VOICE = 4;
|
|
//商品链接消息类型
|
|
const MSN_TYPE_GOODS = 5;
|
|
//订单信息消息类型
|
|
const MSN_TYPE_ORDER = 6;
|
|
|
|
/**
|
|
* 消息类型
|
|
* @var array 1=文字 2=表情 3=图片 4=语音 5 = 商品链接 6 = 订单类型
|
|
*/
|
|
const MSN_TYPE = [
|
|
self::MSN_TYPE_TXT,
|
|
self::MSN_TYPE_EMOT,
|
|
self::MSN_TYPE_IME,
|
|
self::MSN_TYPE_VOICE,
|
|
self::MSN_TYPE_GOODS,
|
|
self::MSN_TYPE_ORDER
|
|
];
|
|
|
|
/**
|
|
* ChatServiceDialogueRecordServices constructor.
|
|
* @param ChatServiceDialogueRecordDao $dao
|
|
*/
|
|
public function __construct(ChatServiceDialogueRecordDao $dao)
|
|
{
|
|
$this->dao = $dao;
|
|
}
|
|
|
|
/**
|
|
* @param App $app
|
|
* @return $this
|
|
*/
|
|
public function setApp(App $app)
|
|
{
|
|
$this->dao->setApp($app);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array $where
|
|
* @return array
|
|
* @throws DataNotFoundException
|
|
* @throws DbException
|
|
* @throws ModelNotFoundException
|
|
*/
|
|
public function getDialogueRecord(array $where)
|
|
{
|
|
[$page, $limit] = $this->getPageValue();
|
|
$list = $this->dao->getDialogueRecord($where)->with(['user', 'userThis'])->page($page, $limit)->select()->toArray();
|
|
$count = $this->dao->getDialogueRecord($where)->count();
|
|
/** @var ChatServiceRecordServices $service */
|
|
$service = app()->make(ChatServiceRecordServices::class);
|
|
/** @var ChatUserServices $userService */
|
|
$userService = app()->make(ChatUserServices::class);
|
|
$data = [
|
|
'record' => $service->count(),
|
|
'tourist' => $userService->count(['is_tourist' => 1]),
|
|
'user' => $userService->count(['is_tourist' => 0]),
|
|
'count' => $this->dao->getDialogueRecord()->count()
|
|
];
|
|
return compact('list', 'count', 'data');
|
|
}
|
|
|
|
/**
|
|
* 获取聊天记录中的uid和to_uid
|
|
* @param int $userId
|
|
* @return array
|
|
*/
|
|
public function getChatUserIds(int $userId)
|
|
{
|
|
$list = $this->dao->getServiceUserUids($userId);
|
|
$arr_user = $arr_to_user = [];
|
|
foreach ($list as $key => $value) {
|
|
array_push($arr_user, $value["user_id"]);
|
|
array_push($arr_to_user, $value["to_user_id"]);
|
|
}
|
|
$userids = array_merge($arr_user, $arr_to_user);
|
|
$userids = array_flip(array_flip($userids));
|
|
$userids = array_flip($userids);
|
|
unset($userids[$userId]);
|
|
return array_flip($userids);
|
|
}
|
|
|
|
/**
|
|
* 获取某个用户的客服聊天记录
|
|
* @param array $where
|
|
* @return array
|
|
* @throws DataNotFoundException
|
|
* @throws DbException
|
|
* @throws ModelNotFoundException
|
|
*/
|
|
public function getChatLogList(array $where)
|
|
{
|
|
[$page, $limit] = $this->getPageValue();
|
|
$list = $this->dao->getServiceList($where, $page, $limit);
|
|
$count = $this->dao->count($where);
|
|
return compact('list', 'count');
|
|
}
|
|
|
|
/**
|
|
* 获取聊天记录列表
|
|
* @param array $where
|
|
* @param int $uid
|
|
* @return array
|
|
* @throws DataNotFoundException
|
|
* @throws DbException
|
|
* @throws ModelNotFoundException
|
|
*/
|
|
public function getChatList(array $where, int $userId)
|
|
{
|
|
[$page, $limit] = $this->getPageValue();
|
|
$list = $this->dao->getServiceList($where, $page, $limit);
|
|
return $this->tidyChat($list);
|
|
}
|
|
|
|
/**
|
|
* 聊天列表格式化
|
|
* @param array $list
|
|
* @param int $uid
|
|
* @return array
|
|
*/
|
|
public function tidyChat(array $list)
|
|
{
|
|
foreach ($list as &$item) {
|
|
$item['_add_time'] = $item['add_time'];
|
|
$item['add_time'] = strtotime($item['_add_time']);
|
|
$item['msn_type'] = (int)$item['msn_type'];
|
|
if (!isset($item['nickname'])) {
|
|
$item['nickname'] = '';
|
|
}
|
|
if (!isset($item['avatar'])) {
|
|
$item['avatar'] = '';
|
|
}
|
|
|
|
if (!$item['avatar'] && !$item['nickname']) {
|
|
// isset 空值防护:chat_user 行缺失时关联为 null,直接取 ['id'] 会抛异常导致整个接口 400
|
|
if (isset($item['userThis']['id']) && $item['userThis']['id'] == $item['user_id']) {
|
|
$item['nickname'] = $item['userThis']['nickname'] ?? '';
|
|
$item['avatar'] = $item['userThis']['avatar'] ?? '';
|
|
} else if (isset($item['userTO']['id']) && $item['userTO']['id'] == $item['user_id']) {
|
|
$item['nickname'] = $item['userTO']['nickname'] ?? '';
|
|
$item['avatar'] = $item['userTO']['avatar'] ?? '';
|
|
} else if (isset($item['userTO']['id']) && $item['userTO']['id'] == $item['to_user_id']) {
|
|
$item['nickname'] = $item['userTO']['nickname'] ?? '';
|
|
$item['avatar'] = $item['userTO']['avatar'] ?? '';
|
|
} else if (isset($item['userThis']['id']) && $item['userThis']['id'] == $item['to_user_id']) {
|
|
$item['nickname'] = $item['userThis']['nickname'] ?? '';
|
|
$item['avatar'] = $item['userThis']['avatar'] ?? '';
|
|
}
|
|
}
|
|
}
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* 获取聊天记录
|
|
* @param array $where
|
|
* @param int $page
|
|
* @param int $limit
|
|
* @param bool $isUp
|
|
* @return array
|
|
* @throws DataNotFoundException
|
|
* @throws DbException
|
|
* @throws ModelNotFoundException
|
|
*/
|
|
public function getServiceChatList(array $where, int $limit, int $upperId)
|
|
{
|
|
return $this->dao->getChatList($where, $limit, $upperId, ['userThis', 'userTO']);
|
|
}
|
|
|
|
/**
|
|
* 获取唯一id
|
|
* @return float|int|string
|
|
* @throws \Exception
|
|
*/
|
|
public function getSendId()
|
|
{
|
|
$snowflake = new \Godruoyi\Snowflake\Snowflake();
|
|
$is_callable = function ($currentTime) {
|
|
$redis = Cache::store('redis');
|
|
$swooleSequenceResolver = new \Godruoyi\Snowflake\RedisSequenceResolver($redis->handler());
|
|
return $swooleSequenceResolver->sequence($currentTime);
|
|
};
|
|
//32位
|
|
if (PHP_INT_SIZE == 4) {
|
|
$id = abs($snowflake->setSequenceResolver($is_callable)->id());
|
|
} else {
|
|
$id = $snowflake->setStartTimeStamp(strtotime('2020-06-05') * 1000)->setSequenceResolver($is_callable)->id();
|
|
}
|
|
return $id;
|
|
}
|
|
}
|