1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-08-03 04:55:53 +08:00

去掉了腾讯平台机器人(效果差),完善IM

This commit is contained in:
xiaochong0302 2020-08-19 20:41:37 +08:00
parent c9f286582a
commit 1de760ba56
57 changed files with 585 additions and 461 deletions

View File

@ -0,0 +1,83 @@
<?php
namespace App\Caches;
use App\Models\ImMessage;
use App\Models\ImMessage as ImMessageModel;
use App\Models\User as UserModel;
use App\Repos\ImGroup as ImGroupRepo;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class ImActiveGroupList extends Cache
{
protected $lifetime = 1 * 86400;
public function getLifetime()
{
return $this->lifetime;
}
public function getKey($id = null)
{
return 'im_active_group_list';
}
public function getContent($id = null)
{
$groups = $this->findGroups();
if (!$groups) return [];
$result = [];
foreach ($groups as $group) {
$result[] = [
'id' => $group->id,
'type' => $group->type,
'name' => $group->name,
'avatar' => $group->avatar,
'about' => $group->about,
'user_count' => $group->user_count,
'msg_count' => $group->msg_count,
];
}
return $result;
}
/**
* @param int $days
* @param int $limit
* @return ResultsetInterface|Resultset|UserModel[]
*/
protected function findGroups($days = 7, $limit = 12)
{
$result = [];
$startTime = strtotime("-{$days} days");
$endTime = time();
$rows = ImMessageModel::query()
->columns(['receiver_id', 'total_count' => 'count(receiver_id)'])
->groupBy('receiver_id')
->orderBy('total_count DESC')
->where('receiver_type = :type:', ['type' => ImMessageModel::TYPE_GROUP])
->betweenWhere('create_time', $startTime, $endTime)
->limit($limit)
->execute();
if ($rows->count() > 0) {
$ids = kg_array_column($rows->toArray(), 'receiver_id');
$groupRepo = new ImGroupRepo();
$result = $groupRepo->findByIds($ids);
}
return $result;
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace App\Caches;
use App\Models\ImMessage as ImMessageModel;
use App\Models\User as UserModel;
use App\Repos\User as UserRepo;
use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface;
class ImActiveUserList extends Cache
{
protected $lifetime = 1 * 86400;
public function getLifetime()
{
return $this->lifetime;
}
public function getKey($id = null)
{
return 'im_active_user_list';
}
public function getContent($id = null)
{
$users = $this->findUsers($id);
if (!$users) return [];
$result = [];
foreach ($users as $user) {
$result[] = [
'id' => $user->id,
'name' => $user->name,
'avatar' => $user->avatar,
'title' => $user->title,
'about' => $user->about,
'vip' => $user->vip,
];
}
return $result;
}
/**
* @param int $days
* @param int $limit
* @return ResultsetInterface|Resultset|UserModel[]
*/
protected function findUsers($days = 7, $limit = 12)
{
$result = [];
$startTime = strtotime("-{$days} days");
$endTime = time();
$rows = ImMessageModel::query()
->columns(['sender_id', 'total_count' => 'count(sender_id)'])
->groupBy('sender_id')
->orderBy('total_count DESC')
->betweenWhere('create_time', $startTime, $endTime)
->limit($limit)
->execute();
if ($rows->count() > 0) {
$ids = kg_array_column($rows->toArray(), 'sender_id');
$userRepo = new UserRepo();
$result = $userRepo->findByIds($ids);
}
return $result;
}
}

View File

@ -25,7 +25,7 @@ class ImNewGroupList extends Cache
{ {
$limit = 12; $limit = 12;
$groups = $this->findHotGroups($limit); $groups = $this->findGroups($limit);
if ($groups->count() == 0) { if ($groups->count() == 0) {
return []; return [];
@ -49,6 +49,8 @@ class ImNewGroupList extends Cache
'name' => $group->name, 'name' => $group->name,
'avatar' => $group->avatar, 'avatar' => $group->avatar,
'about' => $group->about, 'about' => $group->about,
'user_count' => $group->user_count,
'msg_count' => $group->msg_count,
]; ];
} }
@ -59,11 +61,11 @@ class ImNewGroupList extends Cache
* @param int $limit * @param int $limit
* @return ResultsetInterface|Resultset|ImGroupModel[] * @return ResultsetInterface|Resultset|ImGroupModel[]
*/ */
public function findHotGroups($limit = 12) public function findGroups($limit = 12)
{ {
return ImGroupModel::query() return ImGroupModel::query()
->where('deleted = 0') ->where('published = 1')
->orderBy('user_count DESC') ->orderBy('id DESC')
->limit($limit) ->limit($limit)
->execute(); ->execute();
} }

View File

@ -25,7 +25,7 @@ class ImNewUserList extends Cache
{ {
$limit = 12; $limit = 12;
$users = $this->findHotUsers($limit); $users = $this->findUsers($limit);
if ($users->count() == 0) { if ($users->count() == 0) {
return []; return [];
@ -47,6 +47,7 @@ class ImNewUserList extends Cache
'id' => $user->id, 'id' => $user->id,
'name' => $user->name, 'name' => $user->name,
'avatar' => $user->avatar, 'avatar' => $user->avatar,
'title' => $user->title,
'about' => $user->about, 'about' => $user->about,
'vip' => $user->vip, 'vip' => $user->vip,
]; ];
@ -59,7 +60,7 @@ class ImNewUserList extends Cache
* @param int $limit * @param int $limit
* @return ResultsetInterface|Resultset|UserModel[] * @return ResultsetInterface|Resultset|UserModel[]
*/ */
public function findHotUsers($limit = 12) public function findUsers($limit = 12)
{ {
return UserModel::query() return UserModel::query()
->where('deleted = 0') ->where('deleted = 0')

View File

@ -18,7 +18,7 @@ class IndexCarouselList extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'index:carousel_list'; return 'index_carousel_list';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -23,7 +23,7 @@ class IndexFreeCourseList extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'index:free_course_list'; return 'index_free_course_list';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -22,7 +22,7 @@ class IndexLiveList extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'index:live_list'; return 'index_live_list';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -23,7 +23,7 @@ class IndexNewCourseList extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'index:new_course_list'; return 'index_new_course_list';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -23,7 +23,7 @@ class IndexVipCourseList extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'index:vip_course_list'; return 'index_vip_course_list';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -16,7 +16,7 @@ class MaxCategoryId extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'max_id:category'; return 'max_category_id';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -16,7 +16,7 @@ class MaxChapterId extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'max_id:chapter'; return 'max_chapter_id';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -16,7 +16,7 @@ class MaxCourseId extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'max_id:course'; return 'max_course_id';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -16,7 +16,7 @@ class MaxHelpId extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'max_id:help'; return 'max_help_id';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -16,7 +16,7 @@ class MaxImGroupId extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'max_id:im_group'; return 'max_im_group_id';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -16,7 +16,7 @@ class MaxPackageId extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'max_id:package'; return 'max_package_id';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -16,7 +16,7 @@ class MaxPageId extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'max_id:page'; return 'max_page_id';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -16,7 +16,7 @@ class MaxTopicId extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'max_id:topic'; return 'max_topic_id';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -16,7 +16,7 @@ class MaxUserId extends Cache
public function getKey($id = null) public function getKey($id = null)
{ {
return 'max_id:user'; return 'max_user_id';
} }
public function getContent($id = null) public function getContent($id = null)

View File

@ -9,7 +9,7 @@
<br> <br>
<div class="kg-text-center"> <div class="kg-center">
<button class="layui-btn layui-bg-gray kg-back">返回上页</button> <button class="layui-btn layui-bg-gray kg-back">返回上页</button>
</div> </div>

View File

@ -66,7 +66,7 @@
</div> </div>
</form> </form>
{% else %} {% else %}
<div class="kg-text-center"> <div class="kg-center">
<button class="layui-btn layui-bg-gray kg-back">返回上页</button> <button class="layui-btn layui-bg-gray kg-back">返回上页</button>
</div> </div>
{% endif %} {% endif %}

View File

@ -7,7 +7,7 @@
<legend>手机推流</legend> <legend>手机推流</legend>
</fieldset> </fieldset>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="kg-text-center"> <div class="kg-center">
<img class="kg-qrcode" src="{{ qrcode }}" alt="二维码图片"> <img class="kg-qrcode" src="{{ qrcode }}" alt="二维码图片">
</div> </div>
</div> </div>

View File

@ -84,7 +84,7 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">站点统计</label> <label class="layui-form-label">站点统计</label>
<div class="layui-input-block"> <div class="layui-input-block">
<textarea name="analytics" class="layui-textarea" placeholder="使用百度统计,腾讯分析等第三方统计分析站点流量">{{ site.analytics }}</textarea> <textarea name="analytics" class="layui-textarea" placeholder="使用百度统计等第三方统计分析站点流量">{{ site.analytics }}</textarea>
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">

View File

@ -11,7 +11,7 @@
{% set trade_refund_url = url({'for':'admin.trade.refund','id':trade.id}) %} {% set trade_refund_url = url({'for':'admin.trade.refund','id':trade.id}) %}
<div class="kg-text-center"> <div class="kg-center">
{% if trade.status == 'finished' %} {% if trade.status == 'finished' %}
<button class="kg-refund layui-btn layui-bg-green" data-url="{{ trade_refund_url }}">申请退款</button> <button class="kg-refund layui-btn layui-bg-green" data-url="{{ trade_refund_url }}">申请退款</button>
{% endif %} {% endif %}

View File

@ -36,8 +36,6 @@ class ImController extends Controller
*/ */
public function csAction() public function csAction()
{ {
$this->seo->prependTitle('在线客服');
$service = new ImService(); $service = new ImService();
$csUser = $service->getCsUser(); $csUser = $service->getCsUser();
@ -45,20 +43,6 @@ class ImController extends Controller
$this->view->setVar('cs_user', $csUser); $this->view->setVar('cs_user', $csUser);
} }
/**
* @Get("/robot", name="web.im.robot")
*/
public function robotAction()
{
$this->seo->prependTitle('智能聊天');
$service = new ImService();
$csUser = $service->getRobotUser();
$this->view->setVar('cs_user', $csUser);
}
/** /**
* @Get("/init", name="web.im.init") * @Get("/init", name="web.im.init")
*/ */
@ -117,7 +101,9 @@ class ImController extends Controller
{ {
$service = new ImService(); $service = new ImService();
$service->pullUnreadFriendMessages(); $id = $this->request->getQuery('id');
$service->pullUnreadFriendMessages($id);
return $this->jsonSuccess(); return $this->jsonSuccess();
} }
@ -199,9 +185,12 @@ class ImController extends Controller
*/ */
public function sendChatMessageAction() public function sendChatMessageAction()
{ {
$from = $this->request->getPost('from');
$to = $this->request->getPost('to');
$service = new ImService(); $service = new ImService();
$service->sendChatMessage(); $service->sendChatMessage($from, $to);
return $this->jsonSuccess(); return $this->jsonSuccess();
} }
@ -211,9 +200,12 @@ class ImController extends Controller
*/ */
public function sendCsMessageAction() public function sendCsMessageAction()
{ {
$from = $this->request->getPost('from');
$to = $this->request->getPost('to');
$service = new ImService(); $service = new ImService();
$service->sendCsMessage(); $service->sendCsMessage($from, $to);
return $this->jsonSuccess(); return $this->jsonSuccess();
} }

View File

@ -17,21 +17,11 @@ class Im extends Service
use ImGroupTrait; use ImGroupTrait;
use ImMessageTrait; use ImMessageTrait;
use ImNoticeTrait; use ImNoticeTrait;
use ImStatTrait;
public function getRobotUser()
{
$imUser = new ImUserModel();
$imUser->id = -10000;
$imUser->name = '聊天机器人';
$imUser->avatar = kg_ci_avatar_img_url(null);
return $imUser;
}
public function getCsUser() public function getCsUser()
{ {
$userIds = []; $csUserIds = [];
$onlineUserIds = []; $onlineUserIds = [];
$cache = new SettingCache(); $cache = new SettingCache();
@ -41,21 +31,21 @@ class Im extends Service
Gateway::$registerAddress = $this->getRegisterAddress(); Gateway::$registerAddress = $this->getRegisterAddress();
if (!empty($imInfo['cs_user1_id'])) { if (!empty($imInfo['cs_user1_id'])) {
$userIds[] = $imInfo['cs_user1_id']; $csUserIds[] = $imInfo['cs_user1_id'];
if (Gateway::isUidOnline($imInfo['cs_user1_id'])) { if (Gateway::isUidOnline($imInfo['cs_user1_id'])) {
$onlineUserIds[] = $imInfo['cs_user1_id']; $onlineUserIds[] = $imInfo['cs_user1_id'];
} }
} }
if (!empty($imInfo['cs_user2_id'])) { if (!empty($imInfo['cs_user2_id'])) {
$userIds[] = $imInfo['cs_user2_id']; $csUserIds[] = $imInfo['cs_user2_id'];
if (Gateway::isUidOnline($imInfo['cs_user2_id'])) { if (Gateway::isUidOnline($imInfo['cs_user2_id'])) {
$onlineUserIds[] = $imInfo['cs_user2_id']; $onlineUserIds[] = $imInfo['cs_user2_id'];
} }
} }
if (!empty($imInfo['cs_user3_id'])) { if (!empty($imInfo['cs_user3_id'])) {
$userIds[] = $imInfo['cs_user3_id']; $csUserIds[] = $imInfo['cs_user3_id'];
if (Gateway::isUidOnline($imInfo['cs_user3_id'])) { if (Gateway::isUidOnline($imInfo['cs_user3_id'])) {
$onlineUserIds[] = $imInfo['cs_user3_id']; $onlineUserIds[] = $imInfo['cs_user3_id'];
} }
@ -65,8 +55,8 @@ class Im extends Service
$key = array_rand($onlineUserIds); $key = array_rand($onlineUserIds);
$userId = $onlineUserIds[$key]; $userId = $onlineUserIds[$key];
} else { } else {
$key = array_rand($userIds); $key = array_rand($csUserIds);
$userId = $userIds[$key]; $userId = $csUserIds[$key];
} }
return $this->getImUser($userId); return $this->getImUser($userId);

View File

@ -4,12 +4,12 @@ namespace App\Http\Web\Services;
use App\Models\ImFriendGroup as ImFriendGroupModel; use App\Models\ImFriendGroup as ImFriendGroupModel;
use App\Models\ImFriendUser as ImFriendUserModel; use App\Models\ImFriendUser as ImFriendUserModel;
use App\Models\ImSystemMessage as ImSystemMessageModel; use App\Models\ImNotice as ImNoticeModel;
use App\Models\ImUser as ImUserModel; use App\Models\ImUser as ImUserModel;
use App\Repos\ImFriendUser as ImFriendUserRepo; use App\Repos\ImFriendUser as ImFriendUserRepo;
use App\Repos\ImUser as ImUserRepo; use App\Repos\ImUser as ImUserRepo;
use App\Validators\ImFriendUser as ImFriendUserValidator; use App\Validators\ImFriendUser as ImFriendUserValidator;
use App\Validators\ImMessage as ImMessageValidator; use App\Validators\ImNotice as ImNoticeValidator;
use GatewayClient\Gateway; use GatewayClient\Gateway;
Trait ImFriendTrait Trait ImFriendTrait
@ -29,7 +29,7 @@ Trait ImFriendTrait
$group = $validator->checkGroup($post['group_id']); $group = $validator->checkGroup($post['group_id']);
$remark = $validator->checkRemark($post['remark']); $remark = $validator->checkRemark($post['remark']);
$validator->checkIfSelf($user->id, $friend->id); $validator->checkIfSelfApply($user->id, $friend->id);
$validator->checkIfJoined($user->id, $friend->id); $validator->checkIfJoined($user->id, $friend->id);
$this->handleApplyFriendNotice($user, $friend, $group, $remark); $this->handleApplyFriendNotice($user, $friend, $group, $remark);
@ -41,22 +41,22 @@ Trait ImFriendTrait
$user = $this->getImUser($loginUser->id); $user = $this->getImUser($loginUser->id);
$messageId = $this->request->getPost('message_id'); $noticeId = $this->request->getPost('notice_id');
$groupId = $this->request->getPost('group_id'); $groupId = $this->request->getPost('group_id');
$validator = new ImFriendUserValidator(); $validator = new ImFriendUserValidator();
$validator->checkGroup($groupId); $validator->checkGroup($groupId);
$validator = new ImMessageValidator(); $validator = new ImNoticeValidator();
$message = $validator->checkMessage($messageId, 'system'); $notice = $validator->checkNotice($noticeId);
if ($message->item_type != ImSystemMessageModel::TYPE_FRIEND_REQUEST) { if ($notice->item_type != ImNoticeModel::TYPE_FRIEND_REQUEST) {
return; return;
} }
$sender = $this->getImUser($message->sender_id); $sender = $this->getImUser($notice->sender_id);
$friendUserRepo = new ImFriendUserRepo(); $friendUserRepo = new ImFriendUserRepo();
@ -77,7 +77,7 @@ Trait ImFriendTrait
$friendUser = $friendUserRepo->findFriendUser($sender->id, $user->id); $friendUser = $friendUserRepo->findFriendUser($sender->id, $user->id);
$groupId = $message->item_info['group']['id'] ?: 0; $groupId = $notice->item_info['group']['id'] ?: 0;
if (!$friendUser) { if (!$friendUser) {
@ -92,13 +92,13 @@ Trait ImFriendTrait
$this->incrUserFriendCount($sender); $this->incrUserFriendCount($sender);
} }
$itemInfo = $message->item_info; $itemInfo = $notice->item_info;
$itemInfo['status'] = ImSystemMessageModel::REQUEST_ACCEPTED; $itemInfo['status'] = ImNoticeModel::REQUEST_ACCEPTED;
$message->update(['item_info' => $itemInfo]); $notice->update(['item_info' => $itemInfo]);
$this->handleAcceptFriendNotice($user, $sender, $message); $this->handleAcceptFriendNotice($user, $sender, $notice);
} }
public function refuseFriend() public function refuseFriend()
@ -107,23 +107,23 @@ Trait ImFriendTrait
$user = $this->getImUser($loginUser->id); $user = $this->getImUser($loginUser->id);
$messageId = $this->request->getPost('message_id'); $noticeId = $this->request->getPost('notice_id');
$validator = new ImMessageValidator(); $validator = new ImNoticeValidator();
$message = $validator->checkMessage($messageId, 'system'); $notice = $validator->checkNotice($noticeId);
if ($message->item_type != ImSystemMessageModel::TYPE_FRIEND_REQUEST) { if ($notice->item_type != ImNoticeModel::TYPE_FRIEND_REQUEST) {
return; return;
} }
$itemInfo = $message->item_info; $itemInfo = $notice->item_info;
$itemInfo['status'] = ImSystemMessageModel::REQUEST_REFUSED; $itemInfo['status'] = ImNoticeModel::REQUEST_REFUSED;
$message->update(['item_info' => $itemInfo]); $notice->update(['item_info' => $itemInfo]);
$sender = $this->getImUser($message->sender_id); $sender = $this->getImUser($notice->sender_id);
$this->handleRefuseFriendNotice($user, $sender); $this->handleRefuseFriendNotice($user, $sender);
} }
@ -145,24 +145,24 @@ Trait ImFriendTrait
{ {
$userRepo = new ImUserRepo(); $userRepo = new ImUserRepo();
$itemType = ImSystemMessageModel::TYPE_FRIEND_REQUEST; $itemType = ImNoticeModel::TYPE_FRIEND_REQUEST;
$message = $userRepo->findSystemMessage($receiver->id, $itemType); $notice = $userRepo->findNotice($receiver->id, $itemType);
if ($message) { if ($notice) {
$expired = time() - $message->create_time > 7 * 86400; $expired = time() - $notice->create_time > 7 * 86400;
$pending = $message->item_info['status'] == ImSystemMessageModel::REQUEST_PENDING; $pending = $notice->item_info['status'] == ImNoticeModel::REQUEST_PENDING;
if (!$expired && $pending) { if (!$expired && $pending) {
return; return;
} }
} }
$sysMsgModel = new ImSystemMessageModel(); $noticeModel = new ImNoticeModel();
$sysMsgModel->sender_id = $sender->id; $noticeModel->sender_id = $sender->id;
$sysMsgModel->receiver_id = $receiver->id; $noticeModel->receiver_id = $receiver->id;
$sysMsgModel->item_type = ImSystemMessageModel::TYPE_FRIEND_REQUEST; $noticeModel->item_type = ImNoticeModel::TYPE_FRIEND_REQUEST;
$sysMsgModel->item_info = [ $noticeModel->item_info = [
'sender' => [ 'sender' => [
'id' => $sender->id, 'id' => $sender->id,
'name' => $sender->name, 'name' => $sender->name,
@ -173,29 +173,31 @@ Trait ImFriendTrait
'name' => $group->name, 'name' => $group->name,
], ],
'remark' => $remark, 'remark' => $remark,
'status' => ImSystemMessageModel::REQUEST_PENDING, 'status' => ImNoticeModel::REQUEST_PENDING,
]; ];
$sysMsgModel->create(); $noticeModel->create();
Gateway::$registerAddress = $this->getRegisterAddress(); Gateway::$registerAddress = $this->getRegisterAddress();
$online = Gateway::isUidOnline($receiver->id); $online = Gateway::isUidOnline($receiver->id);
if ($online) { if ($online) {
$content = kg_json_encode(['type' => 'refresh_msg_box']); $content = kg_json_encode(['type' => 'refresh_msg_box']);
Gateway::sendToUid($receiver->id, $content); Gateway::sendToUid($receiver->id, $content);
} }
} }
protected function handleAcceptFriendNotice(ImUserModel $sender, ImUserModel $receiver, ImSystemMessageModel $applyMessage) protected function handleAcceptFriendNotice(ImUserModel $sender, ImUserModel $receiver, ImNoticeModel $applyNotice)
{ {
$sysMsgModel = new ImSystemMessageModel(); $noticeModel = new ImNoticeModel();
$sysMsgModel->sender_id = $sender->id; $noticeModel->sender_id = $sender->id;
$sysMsgModel->receiver_id = $receiver->id; $noticeModel->receiver_id = $receiver->id;
$sysMsgModel->item_type = ImSystemMessageModel::TYPE_FRIEND_ACCEPTED; $noticeModel->item_type = ImNoticeModel::TYPE_FRIEND_ACCEPTED;
$sysMsgModel->item_info = [ $noticeModel->item_info = [
'sender' => [ 'sender' => [
'id' => $sender->id, 'id' => $sender->id,
'name' => $sender->name, 'name' => $sender->name,
@ -203,7 +205,7 @@ Trait ImFriendTrait
] ]
]; ];
$sysMsgModel->create(); $noticeModel->create();
Gateway::$registerAddress = $this->getRegisterAddress(); Gateway::$registerAddress = $this->getRegisterAddress();
@ -214,12 +216,12 @@ Trait ImFriendTrait
/** /**
* 上层操作更新了item_info类型发生了变化故重新获取 * 上层操作更新了item_info类型发生了变化故重新获取
*/ */
$applyMessage->afterFetch(); $applyNotice->afterFetch();
/** /**
* @var array $itemInfo * @var array $itemInfo
*/ */
$itemInfo = $applyMessage->item_info; $itemInfo = $applyNotice->item_info;
$content = kg_json_encode([ $content = kg_json_encode([
'type' => 'friend_accepted', 'type' => 'friend_accepted',
@ -240,12 +242,12 @@ Trait ImFriendTrait
protected function handleRefuseFriendNotice(ImUserModel $sender, ImUserModel $receiver) protected function handleRefuseFriendNotice(ImUserModel $sender, ImUserModel $receiver)
{ {
$sysMsgModel = new ImSystemMessageModel(); $noticeModel = new ImNoticeModel();
$sysMsgModel->sender_id = $sender->id; $noticeModel->sender_id = $sender->id;
$sysMsgModel->receiver_id = $receiver->id; $noticeModel->receiver_id = $receiver->id;
$sysMsgModel->item_type = ImSystemMessageModel::TYPE_FRIEND_REFUSED; $noticeModel->item_type = ImNoticeModel::TYPE_FRIEND_REFUSED;
$sysMsgModel->item_info = [ $noticeModel->item_info = [
'sender' => [ 'sender' => [
'id' => $sender->id, 'id' => $sender->id,
'name' => $sender->name, 'name' => $sender->name,
@ -253,14 +255,16 @@ Trait ImFriendTrait
] ]
]; ];
$sysMsgModel->create(); $noticeModel->create();
Gateway::$registerAddress = $this->getRegisterAddress(); Gateway::$registerAddress = $this->getRegisterAddress();
$online = Gateway::isUidOnline($receiver->id); $online = Gateway::isUidOnline($receiver->id);
if ($online) { if ($online) {
$content = kg_json_encode(['type' => 'refresh_msg_box']); $content = kg_json_encode(['type' => 'refresh_msg_box']);
Gateway::sendToUid($receiver->id, $content); Gateway::sendToUid($receiver->id, $content);
} }
} }
@ -268,6 +272,7 @@ Trait ImFriendTrait
protected function incrUserFriendCount(ImUserModel $user) protected function incrUserFriendCount(ImUserModel $user)
{ {
$user->friend_count += 1; $user->friend_count += 1;
$user->update(); $user->update();
} }
@ -279,10 +284,4 @@ Trait ImFriendTrait
} }
} }
protected function incrFriendUserMsgCount(ImFriendUserModel $friendUser)
{
$friendUser->msg_count += 1;
$friendUser->update();
}
} }

View File

@ -4,14 +4,14 @@ namespace App\Http\Web\Services;
use App\Models\ImGroup as ImGroupModel; use App\Models\ImGroup as ImGroupModel;
use App\Models\ImGroupUser as ImGroupUserModel; use App\Models\ImGroupUser as ImGroupUserModel;
use App\Models\ImSystemMessage as ImSystemMessageModel; use App\Models\ImNotice as ImNoticeModel;
use App\Models\ImUser as ImUserModel; use App\Models\ImUser as ImUserModel;
use App\Repos\ImGroup as ImGroupRepo; use App\Repos\ImGroup as ImGroupRepo;
use App\Repos\ImGroupUser as ImGroupUserRepo; use App\Repos\ImGroupUser as ImGroupUserRepo;
use App\Repos\ImUser as ImUserRepo; use App\Repos\ImUser as ImUserRepo;
use App\Validators\ImGroup as ImGroupValidator; use App\Validators\ImGroup as ImGroupValidator;
use App\Validators\ImGroupUser as ImGroupUserValidator; use App\Validators\ImGroupUser as ImGroupUserValidator;
use App\Validators\ImMessage as ImMessageValidator; use App\Validators\ImNotice as ImNoticeValidator;
use GatewayClient\Gateway; use GatewayClient\Gateway;
Trait ImGroupTrait Trait ImGroupTrait
@ -41,17 +41,17 @@ Trait ImGroupTrait
$user = $this->getImUser($loginUser->id); $user = $this->getImUser($loginUser->id);
$messageId = $this->request->getPost('message_id'); $noticeId = $this->request->getPost('notice_id');
$validator = new ImMessageValidator(); $validator = new ImNoticeValidator();
$message = $validator->checkMessage($messageId, 'system'); $notice = $validator->checkNotice($noticeId, 'system');
if ($message->item_type != ImSystemMessageModel::TYPE_GROUP_REQUEST) { if ($notice->item_type != ImNoticeModel::TYPE_GROUP_REQUEST) {
return; return;
} }
$groupId = $message->item_info['group']['id'] ?: 0; $groupId = $notice->item_info['group']['id'] ?: 0;
$validator = new ImGroupValidator(); $validator = new ImGroupValidator();
@ -59,7 +59,7 @@ Trait ImGroupTrait
$validator->checkOwner($user->id, $group->user_id); $validator->checkOwner($user->id, $group->user_id);
$applicant = $this->getImUser($message->sender_id); $applicant = $this->getImUser($notice->sender_id);
$groupUserRepo = new ImGroupUserRepo(); $groupUserRepo = new ImGroupUserRepo();
@ -79,11 +79,11 @@ Trait ImGroupTrait
$this->incrUserGroupCount($applicant); $this->incrUserGroupCount($applicant);
} }
$itemInfo = $message->item_info; $itemInfo = $notice->item_info;
$itemInfo['status'] = ImSystemMessageModel::REQUEST_ACCEPTED; $itemInfo['status'] = ImNoticeModel::REQUEST_ACCEPTED;
$message->update(['item_info' => $itemInfo]); $notice->update(['item_info' => $itemInfo]);
$this->handleAcceptGroupNotice($user, $applicant, $group); $this->handleAcceptGroupNotice($user, $applicant, $group);
@ -96,17 +96,17 @@ Trait ImGroupTrait
$user = $this->getImUser($loginUser->id); $user = $this->getImUser($loginUser->id);
$messageId = $this->request->getPost('message_id'); $noticeId = $this->request->getPost('notice_id');
$validator = new ImMessageValidator(); $validator = new ImNoticeValidator();
$message = $validator->checkMessage($messageId, 'system'); $notice = $validator->checkNotice($noticeId);
if ($message->item_type != ImSystemMessageModel::TYPE_GROUP_REQUEST) { if ($notice->item_type != ImNoticeModel::TYPE_GROUP_REQUEST) {
return; return;
} }
$groupId = $message->item_info['group']['id'] ?: 0; $groupId = $notice->item_info['group']['id'] ?: 0;
$validator = new ImGroupValidator(); $validator = new ImGroupValidator();
@ -114,13 +114,13 @@ Trait ImGroupTrait
$validator->checkOwner($user->id, $group->user_id); $validator->checkOwner($user->id, $group->user_id);
$itemInfo = $message->item_info; $itemInfo = $notice->item_info;
$itemInfo['status'] = ImSystemMessageModel::REQUEST_REFUSED; $itemInfo['status'] = ImNoticeModel::REQUEST_REFUSED;
$message->update(['item_info' => $itemInfo]); $notice->update(['item_info' => $itemInfo]);
$sender = $this->getImUser($message->sender_id); $sender = $this->getImUser($notice->sender_id);
$this->handleRefuseGroupNotice($user, $sender); $this->handleRefuseGroupNotice($user, $sender);
} }
@ -150,24 +150,24 @@ Trait ImGroupTrait
$receiver = $userRepo->findById($group->owner_id); $receiver = $userRepo->findById($group->owner_id);
$itemType = ImSystemMessageModel::TYPE_GROUP_REQUEST; $itemType = ImNoticeModel::TYPE_GROUP_REQUEST;
$message = $userRepo->findSystemMessage($receiver->id, $itemType); $notice = $userRepo->findNotice($receiver->id, $itemType);
if ($message) { if ($notice) {
$expired = time() - $message->create_time > 7 * 86400; $expired = time() - $notice->create_time > 7 * 86400;
$pending = $message->item_info['status'] == ImSystemMessageModel::REQUEST_PENDING; $pending = $notice->item_info['status'] == ImNoticeModel::REQUEST_PENDING;
if (!$expired && $pending) { if (!$expired && $pending) {
return; return;
} }
} }
$sysMsgModel = new ImSystemMessageModel(); $noticeModel = new ImNoticeModel();
$sysMsgModel->sender_id = $sender->id; $noticeModel->sender_id = $sender->id;
$sysMsgModel->receiver_id = $receiver->id; $noticeModel->receiver_id = $receiver->id;
$sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_REQUEST; $noticeModel->item_type = ImNoticeModel::TYPE_GROUP_REQUEST;
$sysMsgModel->item_info = [ $noticeModel->item_info = [
'sender' => [ 'sender' => [
'id' => $sender->id, 'id' => $sender->id,
'name' => $sender->name, 'name' => $sender->name,
@ -178,29 +178,31 @@ Trait ImGroupTrait
'name' => $group->name, 'name' => $group->name,
], ],
'remark' => $remark, 'remark' => $remark,
'status' => ImSystemMessageModel::REQUEST_PENDING, 'status' => ImNoticeModel::REQUEST_PENDING,
]; ];
$sysMsgModel->create(); $noticeModel->create();
Gateway::$registerAddress = $this->getRegisterAddress(); Gateway::$registerAddress = $this->getRegisterAddress();
$online = Gateway::isUidOnline($receiver->id); $online = Gateway::isUidOnline($receiver->id);
if ($online) { if ($online) {
$content = kg_json_encode(['type' => 'refresh_msg_box']); $content = kg_json_encode(['type' => 'refresh_msg_box']);
Gateway::sendToUid($receiver->id, $content); Gateway::sendToUid($receiver->id, $content);
} }
} }
protected function handleAcceptGroupNotice(ImUserModel $sender, ImUserModel $receiver, ImGroupModel $group) protected function handleAcceptGroupNotice(ImUserModel $sender, ImUserModel $receiver, ImGroupModel $group)
{ {
$sysMsgModel = new ImSystemMessageModel(); $noticeModel = new ImNoticeModel();
$sysMsgModel->sender_id = $sender->id; $noticeModel->sender_id = $sender->id;
$sysMsgModel->receiver_id = $receiver->id; $noticeModel->receiver_id = $receiver->id;
$sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_ACCEPTED; $noticeModel->item_type = ImNoticeModel::TYPE_GROUP_ACCEPTED;
$sysMsgModel->item_info = [ $noticeModel->item_info = [
'sender' => [ 'sender' => [
'id' => $sender->id, 'id' => $sender->id,
'name' => $sender->name, 'name' => $sender->name,
@ -208,7 +210,7 @@ Trait ImGroupTrait
] ]
]; ];
$sysMsgModel->create(); $noticeModel->create();
Gateway::$registerAddress = $this->getRegisterAddress(); Gateway::$registerAddress = $this->getRegisterAddress();
@ -231,12 +233,12 @@ Trait ImGroupTrait
protected function handleRefuseGroupNotice(ImUserModel $sender, ImUserModel $receiver) protected function handleRefuseGroupNotice(ImUserModel $sender, ImUserModel $receiver)
{ {
$sysMsgModel = new ImSystemMessageModel(); $noticeModel = new ImNoticeModel();
$sysMsgModel->sender_id = $sender->id; $noticeModel->sender_id = $sender->id;
$sysMsgModel->receiver_id = $receiver->id; $noticeModel->receiver_id = $receiver->id;
$sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_REFUSED; $noticeModel->item_type = ImNoticeModel::TYPE_GROUP_REFUSED;
$sysMsgModel->item_info = [ $noticeModel->item_info = [
'sender' => [ 'sender' => [
'id' => $sender->id, 'id' => $sender->id,
'name' => $sender->name, 'name' => $sender->name,
@ -244,12 +246,14 @@ Trait ImGroupTrait
] ]
]; ];
$sysMsgModel->create(); $noticeModel->create();
Gateway::$registerAddress = $this->getRegisterAddress(); Gateway::$registerAddress = $this->getRegisterAddress();
if (Gateway::isUidOnline($receiver->id)) { if (Gateway::isUidOnline($receiver->id)) {
$content = kg_json_encode(['type' => 'refresh_msg_box']); $content = kg_json_encode(['type' => 'refresh_msg_box']);
Gateway::sendToUid($receiver->id, $content); Gateway::sendToUid($receiver->id, $content);
} }
} }
@ -289,6 +293,7 @@ Trait ImGroupTrait
protected function incrUserGroupCount(ImUserModel $user) protected function incrUserGroupCount(ImUserModel $user)
{ {
$user->group_count += 1; $user->group_count += 1;
$user->update(); $user->update();
} }
@ -303,6 +308,7 @@ Trait ImGroupTrait
protected function incrGroupUserCount(ImGroupModel $group) protected function incrGroupUserCount(ImGroupModel $group)
{ {
$group->user_count += 1; $group->user_count += 1;
$group->update(); $group->update();
} }
@ -314,10 +320,4 @@ Trait ImGroupTrait
} }
} }
protected function incrGroupMessageCount(ImGroupModel $group)
{
$group->msg_count += 1;
$group->update();
}
} }

View File

@ -4,6 +4,8 @@ namespace App\Http\Web\Services;
use App\Builders\ImMessageList as ImMessageListBuilder; use App\Builders\ImMessageList as ImMessageListBuilder;
use App\Library\Paginator\Query as PagerQuery; use App\Library\Paginator\Query as PagerQuery;
use App\Models\ImFriendUser as ImFriendUserModel;
use App\Models\ImGroup as ImGroupModel;
use App\Models\ImMessage as ImMessageModel; use App\Models\ImMessage as ImMessageModel;
use App\Repos\ImFriendUser as ImFriendUserRepo; use App\Repos\ImFriendUser as ImFriendUserRepo;
use App\Repos\ImMessage as ImMessageRepo; use App\Repos\ImMessage as ImMessageRepo;
@ -22,12 +24,10 @@ use GatewayClient\Gateway;
Trait ImMessageTrait Trait ImMessageTrait
{ {
public function pullUnreadFriendMessages() public function pullUnreadFriendMessages($id)
{ {
$user = $this->getLoginUser(); $user = $this->getLoginUser();
$id = $this->request->getQuery('id');
$validator = new ImUserValidator(); $validator = new ImUserValidator();
$friend = $validator->checkUser($id); $friend = $validator->checkUser($id);
@ -113,15 +113,12 @@ Trait ImMessageTrait
} }
} }
public function sendChatMessage() public function sendChatMessage($from, $to)
{ {
$user = $this->getLoginUser();
$from = $this->request->getPost('from');
$to = $this->request->getPost('to');
$validator = new ImMessageValidator(); $validator = new ImMessageValidator();
$validator->checkIfSelfChat($from['id'], $to['id']);
$from['content'] = $validator->checkContent($from['content']); $from['content'] = $validator->checkContent($from['content']);
$message = [ $message = [
@ -146,11 +143,11 @@ Trait ImMessageTrait
Gateway::$registerAddress = $this->getRegisterAddress(); Gateway::$registerAddress = $this->getRegisterAddress();
if ($to['type'] == ImMessageModel::TYPE_FRIEND) { if ($to['type'] == 'friend') {
$validator = new ImFriendUserValidator(); $validator = new ImFriendUserValidator();
$relation = $validator->checkFriendUser($to['id'], $user->id); $relation = $validator->checkFriendUser($to['id'], $from['id']);
$online = Gateway::isUidOnline($to['id']); $online = Gateway::isUidOnline($to['id']);
@ -159,7 +156,7 @@ Trait ImMessageTrait
$messageModel->create([ $messageModel->create([
'sender_id' => $from['id'], 'sender_id' => $from['id'],
'receiver_id' => $to['id'], 'receiver_id' => $to['id'],
'receiver_type' => $to['type'], 'receiver_type' => ImMessageModel::TYPE_FRIEND,
'content' => $from['content'], 'content' => $from['content'],
'viewed' => $online ? 1 : 0, 'viewed' => $online ? 1 : 0,
]); ]);
@ -170,7 +167,9 @@ Trait ImMessageTrait
$this->incrFriendUserMsgCount($relation); $this->incrFriendUserMsgCount($relation);
} }
} elseif ($to['type'] == ImMessageModel::TYPE_GROUP) { } elseif ($to['type'] == 'group') {
$user = $this->getLoginUser();
$validator = new ImGroupValidator(); $validator = new ImGroupValidator();
@ -185,11 +184,11 @@ Trait ImMessageTrait
$messageModel->create([ $messageModel->create([
'sender_id' => $from['id'], 'sender_id' => $from['id'],
'receiver_id' => $to['id'], 'receiver_id' => $to['id'],
'receiver_type' => $to['type'], 'receiver_type' => ImMessageModel::TYPE_GROUP,
'content' => $from['content'], 'content' => $from['content'],
]); ]);
$this->incrGroupMessageCount($group); $this->incrGroupMsgCount($group);
$excludeClientId = null; $excludeClientId = null;
@ -200,26 +199,59 @@ Trait ImMessageTrait
$excludeClientId = Gateway::getClientIdByUid($user->id); $excludeClientId = Gateway::getClientIdByUid($user->id);
} }
$groupName = $this->getGroupName($to['id']); $groupName = $this->getGroupName($group->id);
Gateway::sendToGroup($groupName, $content, $excludeClientId); Gateway::sendToGroup($groupName, $content, $excludeClientId);
} }
} }
public function sendCsMessage() protected function sendCsMessage($from, $to)
{ {
$from = $this->request->getPost('from');
$to = $this->request->getPost('to');
$validator = new ImMessageValidator(); $validator = new ImMessageValidator();
$from['content'] = $validator->checkContent($from['content']); $validator->checkIfSelfChat($from['id'], $to['id']);
if ($to['id'] > 0) { $sender = $this->getImUser($from['id']);
$this->sendCsUserMessage($from, $to); $receiver = $this->getImUser($to['id']);
} else {
$this->sendCsRobotMessage($from, $to); $friendUserRepo = new ImFriendUserRepo();
$friendUser = $friendUserRepo->findFriendUser($sender->id, $receiver->id);
if (!$friendUser) {
$friendUserModel = new ImFriendUserModel();
$friendUserModel->create([
'user_id' => $sender->id,
'friend_id' => $receiver->id,
]);
$this->incrUserFriendCount($sender);
} }
$friendUser = $friendUserRepo->findFriendUser($receiver->id, $sender->id);
if (!$friendUser) {
$friendUserModel = new ImFriendUserModel();
$friendUserModel->create([
'user_id' => $receiver->id,
'friend_id' => $sender->id,
]);
$this->incrUserFriendCount($receiver);
}
/**
* 统一普通聊天和自定义聊天的用户名字段
*/
$to['username'] = $to['name'];
unset($to['name']);
$this->sendChatMessage($from, $to);
} }
protected function handleChatMessagePager($pager) protected function handleChatMessagePager($pager)
@ -251,81 +283,18 @@ Trait ImMessageTrait
return $pager; return $pager;
} }
/** protected function incrFriendUserMsgCount(ImFriendUserModel $friendUser)
* 向客服发送消息,建立临时好友关系
*
* @param array $from
* @param array $to
*/
protected function sendCsUserMessage($from, $to)
{ {
$message = [ $friendUser->msg_count += 1;
'username' => $from['username'],
'avatar' => $from['avatar'],
'content' => $from['content'],
'fromid' => $from['id'],
'id' => $from['id'],
'type' => $to['type'],
'timestamp' => 1000 * time(),
'mine' => false,
];
$content = kg_json_encode([ $friendUser->update();
'type' => 'show_cs_msg',
'message' => $message,
]);
Gateway::$registerAddress = $this->getRegisterAddress();
$online = Gateway::isUidOnline($to['id']);
$messageModel = new ImMessageModel();
$messageModel->create([
'sender_id' => $from['id'],
'receiver_id' => $to['id'],
'receiver_type' => $to['type'],
'content' => $from['content'],
'viewed' => $online ? 1 : 0,
]);
if ($online) {
Gateway::sendToUid($to['id'], $content);
}
} }
/** protected function incrGroupMsgCount(ImGroupModel $group)
* 向机器人发送消息,机器人自动应答
*
* @param array $from
* @param array $to
*/
protected function sendCsRobotMessage($from, $to)
{ {
/** $group->msg_count += 1;
* @todo 从腾讯平台获取应答内容
*/
$content = '不知道你在说什么...';
$message = [ $group->update();
'username' => $to['name'],
'avatar' => $to['avatar'],
'content' => $content,
'fromid' => $to['id'],
'id' => $to['id'],
'type' => $to['type'],
'timestamp' => 1000 * time(),
'mine' => false,
];
$content = kg_json_encode([
'type' => 'show_cs_msg',
'message' => $message,
]);
Gateway::$registerAddress = $this->getRegisterAddress();
Gateway::sendToUid($from['id'], $content);
} }
} }

View File

@ -0,0 +1,28 @@
<?php
namespace App\Http\Web\Services;
trait ImStatTrait
{
public function getActiveGroups()
{
}
public function getActiveUsers()
{
}
public function getNewGroups()
{
}
public function getNewUsers()
{
}
}

View File

@ -1,77 +0,0 @@
<?php
namespace App\Http\Web\Services;
use App\Builders\ImGroupList as ImGroupListBuilder;
use App\Library\Paginator\Query as PagerQuery;
use App\Repos\ImGroup as ImGroupRepo;
class ImSummary extends Service
{
public function getActiveGroups()
{
$pagerQuery = new PagerQuery();
$params = $pagerQuery->getParams();
$params['published'] = 1;
$sort = $pagerQuery->getSort();
$page = $pagerQuery->getPage();
$limit = $pagerQuery->getLimit();
$groupRepo = new ImGroupRepo();
$pager = $groupRepo->paginate($params, $sort, $page, $limit);
return $this->handleGroups($pager);
}
public function getActiveUsers()
{
}
public function getOnlineUsers()
{
}
protected function handleGroups($pager)
{
if ($pager->total_items == 0) {
return $pager;
}
$builder = new ImGroupListBuilder();
$groups = $pager->items->toArray();
$users = $builder->getUsers($groups);
$baseUrl = kg_ci_base_url();
$items = [];
foreach ($groups as $group) {
$group['avatar'] = $baseUrl . $group['avatar'];
$group['owner'] = $users[$group['owner_id']] ?? new \stdClass();
$items[] = [
'id' => $group['id'],
'type' => $group['type'],
'name' => $group['name'],
'avatar' => $group['avatar'],
'about' => $group['about'],
'user_count' => $group['user_count'],
'msg_count' => $group['msg_count'],
'owner' => $group['owner'],
];
}
$pager->items = $items;
return $pager;
}
}

View File

@ -19,7 +19,8 @@
<div class="layui-colla-content layui-show"> <div class="layui-colla-content layui-show">
<ul class="help-list"> <ul class="help-list">
{% for help in item.helps %} {% for help in item.helps %}
<li><a href="{{ url({'for':'web.help.show','id':help.id}) }}"><i class="layui-icon layui-icon-right"></i>{{ help.title }}</a></li> {% set show_url = url({'for':'web.help.show','id':help.id}) %}
<li><a href="{{ show_url }}"><i class="layui-icon layui-icon-right"></i>{{ help.title }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
@ -29,15 +30,24 @@
</div> </div>
</div> </div>
<div class="layout-sidebar"> <div class="layout-sidebar">
<div class="layui-card"> <div class="layui-card cs-sidebar">
<div class="layui-card-header">意见反馈</div> <div class="layui-card-header">客户服务</div>
<div class="layui-card-body"> <div class="layui-card-body">
<form class="layui-form"> <p>没解决你的疑问?试试联系客服吧!</p>
<textarea name="content" class="layui-textarea" lay-verify="required"></textarea> {% if im_info.cs.enabled == 1 %}
</form> <p class="center">
<button class="layui-btn layui-btn-sm btn-cs">联系客服</button>
</p>
{% endif %}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block include_js %}
{{ js_include('web/js/help.js') }}
{% endblock %}

View File

@ -1,14 +1,7 @@
{% extends 'templates/main.volt' %} {% extends 'templates/layer.volt' %}
{% block content %} {% block content %}
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="/">首页</a>
<a><cite>在线客服</cite></a>
</span>
</div>
<div class="layui-hide"> <div class="layui-hide">
<input type="hidden" name="cs_user.id" value="{{ cs_user.id }}"> <input type="hidden" name="cs_user.id" value="{{ cs_user.id }}">
<input type="hidden" name="cs_user.name" value="{{ cs_user.name }}"> <input type="hidden" name="cs_user.name" value="{{ cs_user.name }}">

View File

@ -1,36 +1,40 @@
{% if pager.total_pages > 0 %} {%- macro type_info(value) %}
<div class="group-list clearfix"> {% if value == 'course' %}
<div class="layui-row layui-col-space20"> <span class="layui-badge layui-bg-green type">课</span>
{% for item in pager.items %} {% elseif value == 'chat' %}
{% set group_url = url({'for':'web.group.show','id':item.id}) %} <span class="layui-badge layui-bg-blue type">聊</span>
{% set owner_url = url({'for':'web.user.show','id':item.owner.id}) %} {% elseif value == 'staff' %}
{% set item.about = item.about ? item.about : '这家伙真懒,什么都没留下!' %} <span class="layui-badge layui-bg-red type">工</span>
<div class="layui-col-md3"> {% endif %}
<div class="user-card"> {%- endmacro %}
{% if item.type == 'course' %}
<span class="layui-badge layui-bg-green type">课</span> <div class="group-list clearfix">
{% elseif item.type == 'chat' %} <div class="layui-row layui-col-space20">
<span class="layui-badge layui-bg-blue type">聊</span> {% for item in pager.items %}
{% endif %} {% set group_url = url({'for':'web.group.show','id':item.id}) %}
<div class="avatar"> {% set owner_url = url({'for':'web.user.show','id':item.owner.id}) %}
<a href="{{ group_url }}" title="{{ item.about }}"> {% set item.about = item.about ? item.about : '这家伙真懒,什么都没留下!' %}
<img src="{{ item.avatar }}" alt="{{ item.name }}"> <div class="layui-col-md3">
</a> <div class="user-card">
</div> {{ type_info(item.type) }}
<div class="name layui-elip"> <div class="avatar">
<a href="{{ group_url }}" title="{{ item.name }}">{{ item.name }}</a> <a href="{{ group_url }}" title="{{ item.about }}">
</div> <img src="{{ item.avatar }}" alt="{{ item.name }}">
<div class="owner"> </a>
<span>组长:<a href="{{ owner_url }}">{{ item.owner.name }}</a></span> </div>
</div> <div class="name layui-elip">
<div class="meta layui-elip"> <a href="{{ group_url }}" title="{{ item.name }}">{{ item.name }}</a>
<span>成员:{{ item.user_count }}</span> </div>
<span>讨论:{{ item.msg_count }}</span> <div class="owner">
</div> <span>组长:<a href="{{ owner_url }}">{{ item.owner.name }}</a></span>
</div>
<div class="meta layui-elip">
<span>成员:{{ item.user_count }}</span>
<span>讨论:{{ item.msg_count }}</span>
</div> </div>
</div> </div>
{% endfor %} </div>
</div> {% endfor %}
</div> </div>
{{ partial('partials/pager_ajax') }} </div>
{% endif %} {{ partial('partials/pager_ajax') }}

View File

@ -2,6 +2,23 @@
{% block content %} {% block content %}
<div class="tab-wrap">
<div class="layui-tab layui-tab-brief user-tab">
<ul class="layui-tab-title">
<li class="layui-this">活跃群组</li>
<li>活跃用户</li>
<li>新进群组</li>
<li>新进用户</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show"></div>
<div class="layui-tab-item"></div>
<div class="layui-tab-item"></div>
<div class="layui-tab-item"></div>
</div>
</div>
</div>
{% endblock %} {% endblock %}
{% block include_js %} {% block include_js %}

View File

@ -1,25 +0,0 @@
{% extends 'templates/main.volt' %}
{% block content %}
<div class="breadcrumb">
<span class="layui-breadcrumb">
<a href="/">首页</a>
<a><cite>智能聊天</cite></a>
</span>
</div>
<div class="layui-hide">
<input type="hidden" name="cs_user.id" value="{{ cs_user.id }}">
<input type="hidden" name="cs_user.name" value="{{ cs_user.name }}">
<input type="hidden" name="cs_user.avatar" value="{{ cs_user.avatar }}">
<input type="hidden" name="cs_user.welcome" value="我是智能聊天机器人,试试和我聊天吧!">
</div>
{% endblock %}
{% block include_js %}
{{ js_include('web/js/im.cs.js') }}
{% endblock %}

View File

@ -20,7 +20,7 @@
</tr> </tr>
</table> </table>
<br> <br>
<div class="text-center"> <div class="center">
{% if order.status == 'pending' %} {% if order.status == 'pending' %}
<a class="layui-btn layui-bg-blue" href="{{ order_pay_url }}" target="_top">立即支付</a> <a class="layui-btn layui-bg-blue" href="{{ order_pay_url }}" target="_top">立即支付</a>
{% endif %} {% endif %}

View File

@ -13,9 +13,6 @@
cs: { cs: {
enabled: '{{ im_info.cs.enabled }}' enabled: '{{ im_info.cs.enabled }}'
}, },
robot: {
enabled: '{{ im_info.robot.enabled }}'
},
websocket: { websocket: {
url: '{{ im_info.websocket.url }}' url: '{{ im_info.websocket.url }}'
} }

View File

@ -46,13 +46,13 @@
</div> </div>
</div> </div>
<br> <br>
<div class="layui-form-item text-center"> <div class="layui-form-item center">
<button class="layui-btn" lay-submit="true" lay-filter="go">申请退款</button> <button class="layui-btn" lay-submit="true" lay-filter="go">申请退款</button>
<input type="hidden" name="order_sn" value="{{ order.sn }}"> <input type="hidden" name="order_sn" value="{{ order.sn }}">
</div> </div>
</form> </form>
{% else %} {% else %}
<div class="text-center">没有符合条件的退款项目</div> <div class="center">没有符合条件的退款项目</div>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -20,7 +20,7 @@
</tr> </tr>
</table> </table>
<br> <br>
<div class="text-center"> <div class="center">
{% if refund.status == 'approved' %} {% if refund.status == 'approved' %}
<button class="kg-refund layui-btn" data-sn="{{ refund.sn }}" data-url="{{ cancel_url }}">取消退款</button> <button class="kg-refund layui-btn" data-sn="{{ refund.sn }}" data-url="{{ cancel_url }}">取消退款</button>
{% endif %} {% endif %}

View File

@ -7,7 +7,7 @@
<legend>手机推流</legend> <legend>手机推流</legend>
</fieldset> </fieldset>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="text-center"> <div class="center">
<div class="qrcode-sm"><img src="{{ qrcode }}" alt="二维码图片"></div> <div class="qrcode-sm"><img src="{{ qrcode }}" alt="二维码图片"></div>
</div> </div>
</div> </div>

View File

@ -15,6 +15,7 @@
<body class="layer"> <body class="layer">
{% block content %}{% endblock %} {% block content %}{% endblock %}
{{ partial('partials/js_global_vars') }}
{{ js_include('lib/layui/layui.js') }} {{ js_include('lib/layui/layui.js') }}
{{ js_include('web/js/common.js') }} {{ js_include('web/js/common.js') }}

View File

@ -7,8 +7,11 @@ use Phalcon\Mvc\Model\Behavior\SoftDelete;
class ImMessage extends Model class ImMessage extends Model
{ {
const TYPE_FRIEND = 'friend'; /**
const TYPE_GROUP = 'group'; * 接受者类型
*/
const TYPE_FRIEND = 1; // 好友
const TYPE_GROUP = 2; // 群组
/** /**
* 主键编号 * 主键编号
@ -101,7 +104,9 @@ class ImMessage extends Model
{ {
$this->create_time = time(); $this->create_time = time();
if ($this->chat_type == self::TYPE_FRIEND) { $this->chat_id = 0;
if ($this->receiver_type == self::TYPE_FRIEND) {
$this->chat_id = self::getChatId($this->sender_id, $this->receiver_id); $this->chat_id = self::getChatId($this->sender_id, $this->receiver_id);
} }
} }

View File

@ -41,7 +41,7 @@ class CourseIndex extends Service
public function getSyncKey() public function getSyncKey()
{ {
return 'sync:course_index'; return 'sync_course_index';
} }
} }

View File

@ -41,7 +41,7 @@ class GroupIndex extends Service
public function getSyncKey() public function getSyncKey()
{ {
return 'sync:group_index'; return 'sync_group_index';
} }
} }

View File

@ -79,7 +79,7 @@ class Learning extends Service
public function getSyncKey() public function getSyncKey()
{ {
return 'sync:learning'; return 'sync_learning';
} }
} }

View File

@ -41,7 +41,7 @@ class UserIndex extends Service
public function getSyncKey() public function getSyncKey()
{ {
return 'sync:user_index'; return 'sync_user_index';
} }
} }

View File

@ -61,7 +61,7 @@ class ImFriendUser extends Validator
return $record; return $record;
} }
public function checkIfSelf($userId, $friendId) public function checkIfSelfApply($userId, $friendId)
{ {
if ($userId == $friendId) { if ($userId == $friendId) {
throw new BadRequestException('im_friend_user.self_apply'); throw new BadRequestException('im_friend_user.self_apply');

View File

@ -3,29 +3,16 @@
namespace App\Validators; namespace App\Validators;
use App\Exceptions\BadRequest as BadRequestException; use App\Exceptions\BadRequest as BadRequestException;
use App\Repos\ImFriendMessage as ImFriendMessageRepo; use App\Repos\ImMessage as ImMessageRepo;
use App\Repos\ImGroupMessage as ImGroupMessageRepo;
use App\Repos\ImSystemMessage as ImSystemMessageRepo;
class ImMessage extends Validator class ImMessage extends Validator
{ {
public function checkMessage($id, $type) public function checkMessage($id)
{ {
$this->checkType($type); $repo = new ImMessageRepo();
$message = null; $message = $repo->findById($id);
if ($type == 'friend') {
$repo = new ImFriendMessageRepo();
$message = $repo->findById($id);
} elseif ($type == 'group') {
$repo = new ImGroupMessageRepo();
$message = $repo->findById($id);
} elseif ($type == 'system') {
$repo = new ImSystemMessageRepo();
$message = $repo->findById($id);
}
if (!$message) { if (!$message) {
throw new BadRequestException('im_message.not_found'); throw new BadRequestException('im_message.not_found');
@ -36,7 +23,7 @@ class ImMessage extends Validator
public function checkType($type) public function checkType($type)
{ {
if (!in_array($type, ['friend', 'group', 'system'])) { if (!in_array($type, ['friend', 'group'])) {
throw new BadRequestException('im_message.invalid_type'); throw new BadRequestException('im_message.invalid_type');
} }
@ -60,4 +47,11 @@ class ImMessage extends Validator
return $value; return $value;
} }
public function checkIfSelfChat($fromId, $toId)
{
if ($fromId == $toId) {
throw new BadRequestException('im_message.self_chat');
}
}
} }

View File

@ -0,0 +1,41 @@
<?php
namespace App\Validators;
use App\Exceptions\BadRequest as BadRequestException;
use App\Repos\ImNotice as ImNoticeRepo;
class ImNotice extends Validator
{
public function checkNotice($id)
{
$repo = new ImNoticeRepo();
$notice = $repo->findById($id);
if (!$notice) {
throw new BadRequestException('im_notice.not_found');
}
return $notice;
}
public function checkContent($content)
{
$value = $this->filter->sanitize($content, ['trim', 'string']);
$length = kg_strlen($value);
if ($length < 1) {
throw new BadRequestException('im_notice.content_too_short');
}
if ($length > 1000) {
throw new BadRequestException('im_notice.content_too_long');
}
return $value;
}
}

View File

@ -349,5 +349,6 @@ $error['im_message.not_found'] = '消息不存在';
$error['im_message.invalid_type'] = '无效的消息类型'; $error['im_message.invalid_type'] = '无效的消息类型';
$error['im_message.content_too_short'] = '消息内容太短少于1字符'; $error['im_message.content_too_short'] = '消息内容太短少于1字符';
$error['im_message.content_too_long'] = '消息内容太长超过1000字符'; $error['im_message.content_too_long'] = '消息内容太长超过1000字符';
$error['im_message.self_chat'] = '不能给自己发送消息';
return $error; return $error;

View File

@ -18,7 +18,7 @@
cursor: pointer; cursor: pointer;
} }
.kg-text-center { .kg-center {
text-align: center; text-align: center;
} }

View File

@ -23,6 +23,15 @@ layui.define(['jquery', 'layer'], function (exports) {
callback(); callback();
}; };
helper.cs = function () {
layer.open({
type: 2,
title: '在线客服',
area: ['600px', '560px'],
content: ['/im/cs', 'no']
});
};
helper.getRequestId = function () { helper.getRequestId = function () {
var id = Date.now().toString(36); var id = Date.now().toString(36);
id += Math.random().toString(36).substr(3); id += Math.random().toString(36).substr(3);

View File

@ -34,7 +34,7 @@
padding: 20px; padding: 20px;
} }
.text-center { .center {
text-align: center; text-align: center;
} }
@ -193,6 +193,10 @@ body {
line-height: 30px; line-height: 30px;
} }
.cs-sidebar p {
line-height: 40px;
}
.index-wrap .layui-tab { .index-wrap .layui-tab {
margin-bottom: 0; margin-bottom: 0;
} }

View File

@ -1,19 +1,16 @@
layui.use(['jquery', 'util'], function () { layui.use(['helper', 'util'], function () {
var $ = layui.jquery; var helper = layui.helper;
var util = layui.util; var util = layui.util;
var csEnabled = $('input[name="im.cs.enabled"]').val();
var robotEnabled = $('input[name="im.robot.enabled"]').val();
util.fixbar({ util.fixbar({
bar1: csEnabled === '1' ? '&#xe626;' : false, bar1: window.im.cs.enabled === '1',
bar2: robotEnabled === '1' ? '&#xe684;' : false, bar2: true,
click: function (type) { click: function (type) {
if (type === 'bar1') { if (type === 'bar1') {
window.open('/im/cs', 'cs'); helper.cs();
} else if (type === 'bar2') { } else if (type === 'bar2') {
window.open('/im/robot', 'robot'); window.open('/help', 'help');
} }
} }
}); });

View File

@ -0,0 +1,10 @@
layui.use(['jquery', 'helper'], function () {
var $ = layui.jquery;
var helper = layui.helper;
$('.btn-cs').on('click', function () {
helper.cs();
});
});

View File

@ -37,8 +37,8 @@ layui.use(['jquery', 'layim'], function () {
socket.send('pong...'); socket.send('pong...');
} else if (data.type === 'bind_user') { } else if (data.type === 'bind_user') {
bindUser(data); bindUser(data);
} else if (data.type === 'show_cs_msg') { } else if (data.type === 'show_chat_msg') {
showCsMessage(data); showChatMessage(data);
} }
}; };
@ -77,7 +77,6 @@ layui.use(['jquery', 'layim'], function () {
} }
function sendCsMessage(res) { function sendCsMessage(res) {
console.log(res);
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: '/im/msg/cs/send', url: '/im/msg/cs/send',
@ -85,7 +84,7 @@ layui.use(['jquery', 'layim'], function () {
}); });
} }
function showCsMessage(res) { function showChatMessage(res) {
layim.getMessage(res.message); layim.getMessage(res.message);
} }

View File

@ -60,7 +60,7 @@ layui.use(['jquery', 'layer', 'laypage'], function () {
type: 'POST', type: 'POST',
url: '/im/friend/accept', url: '/im/friend/accept',
data: { data: {
message_id: li.data('id'), notice_id: li.data('id'),
group_id: group group_id: group
}, },
success: function () { success: function () {
@ -85,7 +85,7 @@ layui.use(['jquery', 'layer', 'laypage'], function () {
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: '/im/friend/refuse', url: '/im/friend/refuse',
data: {message_id: li.data('id')}, data: {notice_id: li.data('id')},
success: function () { success: function () {
layer.close(index); layer.close(index);
othis.parent().html('<em>已拒绝</em>'); othis.parent().html('<em>已拒绝</em>');
@ -98,7 +98,7 @@ layui.use(['jquery', 'layer', 'laypage'], function () {
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: '/im/group/accept', url: '/im/group/accept',
data: {message_id: li.data('id')}, data: {notice_id: li.data('id')},
success: function () { success: function () {
othis.parent().html('已同意'); othis.parent().html('已同意');
} }
@ -110,7 +110,7 @@ layui.use(['jquery', 'layer', 'laypage'], function () {
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: '/im/group/refuse', url: '/im/group/refuse',
data: {message_id: li.data('id')}, data: {notice_id: li.data('id')},
success: function () { success: function () {
layer.close(index); layer.close(index);
othis.parent().html('<em>已拒绝</em>'); othis.parent().html('<em>已拒绝</em>');