From 986b60a50bfa1c73eae76428e2f344457320f1c0 Mon Sep 17 00:00:00 2001 From: xiaochong0302 Date: Fri, 26 Jun 2020 19:35:17 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E6=B6=88=E6=81=AF=E7=9B=92?= =?UTF-8?q?=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Builders/ChapterTreeList.php | 2 +- app/Console/Tasks/SyncLearningTask.php | 8 +- app/Http/Admin/Views/audit/list.volt | 2 +- app/Http/Admin/Views/chapter/lessons.volt | 2 +- app/Http/Admin/Views/partials/ip2region.volt | 2 +- app/Http/Admin/Views/public/login.volt | 2 +- app/Http/Admin/Views/setting/captcha.volt | 2 +- app/Http/Admin/Views/student/list.volt | 2 +- app/Http/Admin/Views/trade/show.volt | 2 +- .../Web/Controllers/AccountController.php | 16 +- .../Web/Controllers/MessengerController.php | 16 ++ app/Http/Web/Services/Messenger.php | 263 ++++++++++++++++-- app/Http/Web/Views/chapter/show_live.volt | 2 +- app/Http/Web/Views/order/pay.volt | 2 +- app/Http/Web/Views/refund/info.volt | 4 +- app/Http/Web/Views/vip/index.volt | 16 +- app/Models/Chapter.php | 12 +- app/Models/ImChatGroup.php | 7 + app/Repos/ImChatGroupUser.php | 8 +- .../Frontend/Chapter/ChapterBasic.php | 18 +- app/Services/Frontend/Chapter/ChapterInfo.php | 6 +- app/Services/Frontend/Chapter/Learning.php | 7 +- app/Validators/ImChatGroupUser.php | 20 ++ config/errors.php | 1 + public/static/admin/js/common.js | 6 +- public/static/admin/js/index.js | 4 +- public/static/lib/layui/extends/helper.js | 20 ++ public/static/web/js/captcha.login.js | 2 +- public/static/web/js/captcha.verify.js | 2 +- public/static/web/js/common.js | 30 +- public/static/web/js/course.show.js | 20 +- public/static/web/js/im.find.js | 19 +- public/static/web/js/im.js | 51 +++- public/static/web/js/im.msgbox.js | 25 +- public/static/web/js/user.show.js | 9 +- public/static/web/js/vip.js | 16 ++ 36 files changed, 472 insertions(+), 154 deletions(-) create mode 100644 public/static/lib/layui/extends/helper.js create mode 100644 public/static/web/js/vip.js diff --git a/app/Builders/ChapterTreeList.php b/app/Builders/ChapterTreeList.php index d4dce9bd..1b6a48ab 100644 --- a/app/Builders/ChapterTreeList.php +++ b/app/Builders/ChapterTreeList.php @@ -57,7 +57,7 @@ class ChapterTreeList extends Builder */ $attrs = $lesson->attrs; - if ($attrs['model'] == CourseModel::MODEL_VOD) { + if ($chapter->model == CourseModel::MODEL_VOD) { unset($attrs['file_id'], $attrs['file_status']); } diff --git a/app/Console/Tasks/SyncLearningTask.php b/app/Console/Tasks/SyncLearningTask.php index 30c34efd..d44006c5 100644 --- a/app/Console/Tasks/SyncLearningTask.php +++ b/app/Console/Tasks/SyncLearningTask.php @@ -103,8 +103,6 @@ class SyncLearningTask extends Task if (!$chapter) return; - $chapterModel = $chapter->attrs['model']; - $chapterUser->duration += $learning->duration; /** @@ -114,7 +112,7 @@ class SyncLearningTask extends Task * 2.直播观看时间超过10分钟 * 3.图文浏览即消费 */ - if ($chapterModel == CourseModel::MODEL_VOD) { + if ($chapter->model == CourseModel::MODEL_VOD) { $duration = $chapter->attrs['duration'] ?: 300; @@ -124,11 +122,11 @@ class SyncLearningTask extends Task $chapterUser->progress = $progress < 100 ? $progress : 100; $chapterUser->consumed = $chapterUser->duration > 0.3 * $duration ? 1 : 0; - } elseif ($chapterModel == CourseModel::MODEL_LIVE) { + } elseif ($chapter->model == CourseModel::MODEL_LIVE) { $chapterUser->consumed = $chapterUser->duration > 600 ? 1 : 0; - } elseif ($chapterModel == CourseModel::MODEL_READ) { + } elseif ($chapter->model == CourseModel::MODEL_READ) { $chapterUser->consumed = 1; } diff --git a/app/Http/Admin/Views/audit/list.volt b/app/Http/Admin/Views/audit/list.volt index 2edd9f05..83b138f7 100644 --- a/app/Http/Admin/Views/audit/list.volt +++ b/app/Http/Admin/Views/audit/list.volt @@ -60,7 +60,7 @@ var layer = layui.layer; $('.kg-view').on('click', function () { - var url = $(this).attr('data-url'); + var url = $(this).data('url'); layer.open({ type: 2, title: '请求内容', diff --git a/app/Http/Admin/Views/chapter/lessons.volt b/app/Http/Admin/Views/chapter/lessons.volt index b906f230..724a09fe 100644 --- a/app/Http/Admin/Views/chapter/lessons.volt +++ b/app/Http/Admin/Views/chapter/lessons.volt @@ -38,7 +38,7 @@ form.on('switch(free)', function (data) { var checked = $(this).is(':checked'); var free = checked ? 1 : 0; - var url = $(this).attr('data-url'); + var url = $(this).data('url'); $.ajax({ type: 'POST', url: url, diff --git a/app/Http/Admin/Views/partials/ip2region.volt b/app/Http/Admin/Views/partials/ip2region.volt index 12975962..aef53ccf 100644 --- a/app/Http/Admin/Views/partials/ip2region.volt +++ b/app/Http/Admin/Views/partials/ip2region.volt @@ -6,7 +6,7 @@ var layer = layui.layer; $('.kg-ip2region').on('click', function () { - var ip = $(this).attr('data-ip'); + var ip = $(this).data('ip'); var url = '/admin/ip2region?ip=' + ip; layer.open({ type: 2, diff --git a/app/Http/Admin/Views/public/login.volt b/app/Http/Admin/Views/public/login.volt index cb0c6693..89129372 100644 --- a/app/Http/Admin/Views/public/login.volt +++ b/app/Http/Admin/Views/public/login.volt @@ -47,7 +47,7 @@ var $ = layui.jquery; var captcha = new TencentCaptcha( $('#captcha-btn')[0], - $('#captcha-btn').attr('data-app-id'), + $('#captcha-btn').data('app-id'), function (res) { if (res.ret === 0) { $('input[name=ticket]').val(res.ticket); diff --git a/app/Http/Admin/Views/setting/captcha.volt b/app/Http/Admin/Views/setting/captcha.volt index 028a4708..db3f9f44 100644 --- a/app/Http/Admin/Views/setting/captcha.volt +++ b/app/Http/Admin/Views/setting/captcha.volt @@ -66,7 +66,7 @@ var captcha = new TencentCaptcha( $('#front-captcha-btn')[0], - $('#front-captcha-btn').attr('data-app-id'), + $('#front-captcha-btn').data('app-id'), function (res) { if (res.ret === 0) { $('input[name=ticket]').val(res.ticket); diff --git a/app/Http/Admin/Views/student/list.volt b/app/Http/Admin/Views/student/list.volt index f29117c4..82231584 100644 --- a/app/Http/Admin/Views/student/list.volt +++ b/app/Http/Admin/Views/student/list.volt @@ -91,7 +91,7 @@ var $ = layui.jquery; $('.kg-learning').on('click', function () { - var url = $(this).attr('data-url'); + var url = $(this).data('url'); layer.open({ id: 'xm-course', type: 2, diff --git a/app/Http/Admin/Views/trade/show.volt b/app/Http/Admin/Views/trade/show.volt index 67831485..c0ad90ba 100644 --- a/app/Http/Admin/Views/trade/show.volt +++ b/app/Http/Admin/Views/trade/show.volt @@ -54,7 +54,7 @@ var $ = layui.jquery; $('.kg-refund').on('click', function () { - var url = $(this).attr('data-url'); + var url = $(this).data('url'); var tips = '确定要申请退款吗?'; layer.confirm(tips, function () { $.ajax({ diff --git a/app/Http/Web/Controllers/AccountController.php b/app/Http/Web/Controllers/AccountController.php index 66a525cd..59316fb1 100644 --- a/app/Http/Web/Controllers/AccountController.php +++ b/app/Http/Web/Controllers/AccountController.php @@ -82,10 +82,9 @@ class AccountController extends Controller $returnUrl = $this->request->getPost('return_url'); - $content = [ - 'location' => $returnUrl ?: '/', - 'msg' => '登录成功', - ]; + $location = $returnUrl ?: $this->url->get(['for' => 'web.index']); + + $content = ['location' => $location]; return $this->jsonSuccess($content); } @@ -101,10 +100,9 @@ class AccountController extends Controller $returnUrl = $this->request->getPost('return_url'); - $content = [ - 'location' => $returnUrl ?: '/', - 'msg' => '登录成功', - ]; + $location = $returnUrl ?: $this->url->get(['for' => 'web.index']); + + $content = ['location' => $location]; return $this->jsonSuccess($content); } @@ -127,7 +125,7 @@ class AccountController extends Controller public function forgetPasswordAction() { if ($this->authUser->id > 0) { - $this->response->redirect('/'); + $this->response->redirect(['for' => 'web.index']); } $service = new AccountService(); diff --git a/app/Http/Web/Controllers/MessengerController.php b/app/Http/Web/Controllers/MessengerController.php index e721e66b..83e3909a 100644 --- a/app/Http/Web/Controllers/MessengerController.php +++ b/app/Http/Web/Controllers/MessengerController.php @@ -278,7 +278,23 @@ class MessengerController extends LayerController */ public function acceptGroupAction() { + $service = new MessengerService(); + $service->acceptGroup(); + + return $this->jsonSuccess(); + } + + /** + * @Post("/group/refuse", name="web.web.im.refuse_group") + */ + public function refuseGroupAction() + { + $service = new MessengerService(); + + $service->refuseGroup(); + + return $this->jsonSuccess(); } } diff --git a/app/Http/Web/Services/Messenger.php b/app/Http/Web/Services/Messenger.php index fce1750d..26d080c6 100644 --- a/app/Http/Web/Services/Messenger.php +++ b/app/Http/Web/Services/Messenger.php @@ -6,6 +6,8 @@ use App\Builders\ImMessageList as ImMessageListBuilder; use App\Caches\ImHotGroupList as ImHotGroupListCache; use App\Caches\ImHotUserList as ImHotUserListCache; use App\Library\Paginator\Query as PagerQuery; +use App\Models\ImChatGroup as ImChatGroupModel; +use App\Models\ImChatGroupUser as ImChatGroupUserModel; use App\Models\ImFriendGroup as ImFriendGroupModel; use App\Models\ImFriendMessage as ImFriendMessageModel; use App\Models\ImFriendUser as ImFriendUserModel; @@ -13,12 +15,14 @@ use App\Models\ImGroupMessage as ImGroupMessageModel; use App\Models\ImSystemMessage as ImSystemMessageModel; use App\Models\User as UserModel; use App\Repos\ImChatGroup as ImChatGroupRepo; +use App\Repos\ImChatGroupUser as ImChatGroupUserRepo; use App\Repos\ImFriendMessage as ImFriendMessageRepo; use App\Repos\ImFriendUser as ImFriendUserRepo; use App\Repos\ImGroupMessage as ImGroupMessageRepo; use App\Repos\ImSystemMessage as ImSystemMessageRepo; use App\Repos\User as UserRepo; use App\Validators\ImChatGroup as ImChatGroupValidator; +use App\Validators\ImChatGroupUser as ImChatGroupUserValidator; use App\Validators\ImFriendUser as ImFriendUserValidator; use App\Validators\ImMessage as ImMessageValidator; use App\Validators\User as UserValidator; @@ -223,7 +227,7 @@ class Messenger extends Service $clientId = $this->request->getPost('client_id'); - Gateway::$registerAddress = '127.0.0.1:1238'; + Gateway::$registerAddress = $this->getRegisterAddress(); Gateway::bindUid($clientId, $user->id); @@ -273,7 +277,7 @@ class Messenger extends Service 'message' => $message, ]); - Gateway::$registerAddress = '127.0.0.1:1238'; + Gateway::$registerAddress = $this->getRegisterAddress(); if ($to['type'] == 'friend') { @@ -286,12 +290,12 @@ class Messenger extends Service $messageModel = new ImFriendMessageModel(); - $messageModel->sender_id = $from['id']; - $messageModel->receiver_id = $to['id']; - $messageModel->content = $from['content']; - $messageModel->viewed = $online ? 1 : 0; - - $messageModel->create(); + $messageModel->create([ + 'sender_id' => $from['id'], + 'receiver_id' => $to['id'], + 'content' => $from['content'], + 'viewed' => $online ? 1 : 0, + ]); if ($online) { Gateway::sendToUid($to['id'], $content); @@ -302,11 +306,11 @@ class Messenger extends Service $messageModel = new ImGroupMessageModel(); - $messageModel->sender_id = $from['id']; - $messageModel->group_id = $to['id']; - $messageModel->content = $from['content']; - - $messageModel->create(); + $messageModel->create([ + 'sender_id' => $from['id'], + 'group_id' => $to['id'], + 'content' => $from['content'], + ]); $excludeClientId = null; @@ -426,7 +430,7 @@ class Messenger extends Service $itemInfo['status'] = ImSystemMessageModel::REQUEST_ACCEPTED; $message->update(['item_info' => $itemInfo]); - $this->handleAcceptFriendNotice($user, $sender); + $this->handleAcceptFriendNotice($user, $sender, $message); } public function refuseFriend() @@ -456,14 +460,97 @@ class Messenger extends Service public function applyGroup() { + $post = $this->request->getPost(); + + $user = $this->getLoginUser(); + + $validator = new ImChatGroupUserValidator(); + + $group = $validator->checkGroup($post['group_id']); + $remark = $validator->checkRemark($post['remark']); + + $validator->checkIfJoined($user->id, $group->id); + $validator->checkIfBlocked($user->id, $group->id); + + $this->handleApplyGroupNotice($user, $group, $remark); } public function acceptGroup() { + $user = $this->getLoginUser(); + + $messageId = $this->request->getPost('message_id'); + + $validator = new ImMessageValidator(); + + $message = $validator->checkMessage($messageId, 'system'); + + if ($message->item_type != ImSystemMessageModel::TYPE_GROUP_REQUEST) { + return; + } + + $groupId = $message->item_info['group']['id'] ?: 0; + + $validator = new ImChatGroupValidator(); + + $group = $validator->checkGroup($groupId); + + $validator->checkOwner($user->id, $group->user_id); + + $userRepo = new UserRepo(); + + $sender = $userRepo->findById($message->sender_id); + + $groupUserRepo = new ImChatGroupUserRepo(); + + $groupUser = $groupUserRepo->findGroupUser($group->id, $sender->id); + + if (!$groupUser) { + $groupUserModel = new ImChatGroupUserModel(); + $groupUserModel->create([ + 'group_id' => $group->id, + 'user_id' => $sender->id, + ]); + } + + $itemInfo = $message->item_info; + $itemInfo['status'] = ImSystemMessageModel::REQUEST_ACCEPTED; + $message->update(['item_info' => $itemInfo]); + + $this->handleAcceptGroupNotice($user, $sender, $group); } public function refuseGroup() { + $user = $this->getLoginUser(); + + $messageId = $this->request->getPost('message_id'); + + $validator = new ImMessageValidator(); + + $message = $validator->checkMessage($messageId, 'system'); + + if ($message->item_type != ImSystemMessageModel::TYPE_GROUP_REQUEST) { + return; + } + + $groupId = $message->item_info['group']['id'] ?: 0; + + $validator = new ImChatGroupValidator(); + + $group = $validator->checkGroup($groupId); + + $validator->checkOwner($user->id, $group->user_id); + + $itemInfo = $message->item_info; + $itemInfo['status'] = ImSystemMessageModel::REQUEST_REFUSED; + $message->update(['item_info' => $itemInfo]); + + $userRepo = new UserRepo(); + + $sender = $userRepo->findById($message->sender_id); + + $this->handleRefuseGroupNotice($user, $sender); } protected function pullUnreadFriendMessages($userId) @@ -689,7 +776,7 @@ class Messenger extends Service if ($message) { $expired = time() - $message->create_time > 7 * 86400; - $pending = $message->item_type['status'] == ImSystemMessageModel::REQUEST_PENDING; + $pending = $message->item_info['status'] == ImSystemMessageModel::REQUEST_PENDING; if (!$expired && $pending) { return; } @@ -716,19 +803,17 @@ class Messenger extends Service $sysMsgModel->create(); - Gateway::$registerAddress = '127.0.0.1:1238'; + Gateway::$registerAddress = $this->getRegisterAddress(); $online = Gateway::isUidOnline($receiver->id); if ($online) { - - $content = kg_json_encode(['type' => 'refresh_sys_msg']); - + $content = kg_json_encode(['type' => 'show_sys_msg']); Gateway::sendToUid($receiver->id, $content); } } - protected function handleAcceptFriendNotice(UserModel $sender, UserModel $receiver) + protected function handleAcceptFriendNotice(UserModel $sender, UserModel $receiver, ImSystemMessageModel $message) { $sysMsgModel = new ImSystemMessageModel(); @@ -745,13 +830,29 @@ class Messenger extends Service $sysMsgModel->create(); - Gateway::$registerAddress = '127.0.0.1:1238'; + Gateway::$registerAddress = $this->getRegisterAddress(); $online = Gateway::isUidOnline($receiver->id); if ($online) { - $content = kg_json_encode(['type' => 'show_msg_box']); + /** + * @var array $itemInfo + */ + $itemInfo = $message->item_info; + + $content = kg_json_encode([ + 'type' => 'friend_accepted', + 'friend' => [ + 'id' => $sender->id, + 'name' => $sender->name, + 'avatar' => $sender->avatar, + ], + 'group' => [ + 'id' => $itemInfo['group']['id'], + 'name' => $itemInfo['group']['name'], + ], + ]); Gateway::sendToUid($receiver->id, $content); } @@ -774,21 +875,135 @@ class Messenger extends Service $sysMsgModel->create(); - Gateway::$registerAddress = '127.0.0.1:1238'; + Gateway::$registerAddress = $this->getRegisterAddress(); + + $online = Gateway::isUidOnline($receiver->id); + + if ($online) { + $content = kg_json_encode(['type' => 'show_sys_msg']); + Gateway::sendToUid($receiver->id, $content); + } + } + + protected function handleApplyGroupNotice(UserModel $sender, ImChatGroupModel $group, $remark) + { + $userRepo = new UserRepo(); + + $receiver = $userRepo->findById($group->user_id); + + $itemType = ImSystemMessageModel::TYPE_GROUP_REQUEST; + + $message = $userRepo->findImSystemMessage($receiver->id, $itemType); + + if ($message) { + $expired = time() - $message->create_time > 7 * 86400; + $pending = $message->item_info['status'] == ImSystemMessageModel::REQUEST_PENDING; + if (!$expired && $pending) { + return; + } + } + + $sysMsgModel = new ImSystemMessageModel(); + + $sysMsgModel->sender_id = $sender->id; + $sysMsgModel->receiver_id = $receiver->id; + $sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_REQUEST; + $sysMsgModel->item_info = [ + 'sender' => [ + 'id' => $sender->id, + 'name' => $sender->name, + 'avatar' => $sender->avatar, + ], + 'group' => [ + 'id' => $group->id, + 'name' => $group->name, + ], + 'remark' => $remark, + 'status' => ImSystemMessageModel::REQUEST_PENDING, + ]; + + $sysMsgModel->create(); + + Gateway::$registerAddress = $this->getRegisterAddress(); + + $online = Gateway::isUidOnline($receiver->id); + + if ($online) { + $content = kg_json_encode(['type' => 'show_sys_msg']); + Gateway::sendToUid($receiver->id, $content); + } + } + + protected function handleAcceptGroupNotice(UserModel $sender, UserModel $receiver, ImChatGroupModel $group) + { + $sysMsgModel = new ImSystemMessageModel(); + + $sysMsgModel->sender_id = $sender->id; + $sysMsgModel->receiver_id = $receiver->id; + $sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_ACCEPTED; + $sysMsgModel->item_info = [ + 'sender' => [ + 'id' => $sender->id, + 'name' => $sender->name, + 'avatar' => $sender->avatar, + ] + ]; + + $sysMsgModel->create(); + + Gateway::$registerAddress = $this->getRegisterAddress(); $online = Gateway::isUidOnline($receiver->id); if ($online) { - $content = kg_json_encode(['type' => 'show_msg_box']); + $content = kg_json_encode([ + 'type' => 'group_accepted', + 'group' => [ + 'id' => $group->id, + 'name' => $group->name, + ], + ]); Gateway::sendToUid($receiver->id, $content); } } + protected function handleRefuseGroupNotice(UserModel $sender, UserModel $receiver) + { + $sysMsgModel = new ImSystemMessageModel(); + + $sysMsgModel->sender_id = $sender->id; + $sysMsgModel->receiver_id = $receiver->id; + $sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_REFUSED; + $sysMsgModel->item_info = [ + 'sender' => [ + 'id' => $sender->id, + 'name' => $sender->name, + 'avatar' => $sender->avatar, + ] + ]; + + $sysMsgModel->create(); + + Gateway::$registerAddress = $this->getRegisterAddress(); + + $online = Gateway::isUidOnline($receiver->id); + + if ($online) { + $content = kg_json_encode(['type' => 'show_sys_msg']); + Gateway::sendToUid($receiver->id, $content); + } + } + protected function getGroupName($groupId) { return "group_{$groupId}"; } + protected function getRegisterAddress() + { + return '127.0.0.1:1238'; + } + } diff --git a/app/Http/Web/Views/chapter/show_live.volt b/app/Http/Web/Views/chapter/show_live.volt index c9441a5b..cc9ab01c 100644 --- a/app/Http/Web/Views/chapter/show_live.volt +++ b/app/Http/Web/Views/chapter/show_live.volt @@ -55,7 +55,7 @@ function refreshLiveStats() { var $liveStats = $('#sidebar-live-stats'); - helper.ajaxLoadHtml($liveStats.attr('data-url'), $liveStats.attr('id')); + helper.ajaxLoadHtml($liveStats.data('url'), $liveStats.attr('id')); } diff --git a/app/Http/Web/Views/order/pay.volt b/app/Http/Web/Views/order/pay.volt index 2f2217d0..98c4309f 100644 --- a/app/Http/Web/Views/order/pay.volt +++ b/app/Http/Web/Views/order/pay.volt @@ -53,7 +53,7 @@ }); }; $('.pay-btn').on('click', function () { - var channel = $(this).attr('data-channel'); + var channel = $(this).data('channel'); var createUrl = $('input[name=trade_create_url]').val(); var statusUrl = $('input[name=trade_status_url]').val(); var forwardUrl = $('input[name=forward_url]').val(); diff --git a/app/Http/Web/Views/refund/info.volt b/app/Http/Web/Views/refund/info.volt index 3af517dc..b3a35c67 100644 --- a/app/Http/Web/Views/refund/info.volt +++ b/app/Http/Web/Views/refund/info.volt @@ -46,8 +46,8 @@ var $ = layui.jquery; var layer = layui.layer; $('.kg-refund').on('click', function () { - var url = $(this).attr('data-url'); - var data = {sn: $(this).attr('data-sn')}; + var url = $(this).data('url'); + var data = {sn: $(this).data('sn')}; var tips = '确定要取消退款吗?'; layer.confirm(tips, function () { $.ajax({ diff --git a/app/Http/Web/Views/vip/index.volt b/app/Http/Web/Views/vip/index.volt index 783c0b92..ced62b8c 100644 --- a/app/Http/Web/Views/vip/index.volt +++ b/app/Http/Web/Views/vip/index.volt @@ -48,20 +48,8 @@ {% endblock %} -{% block inline_js %} +{% block include_js %} - + {{ js_include('web/js/vip.js') }} {% endblock %} \ No newline at end of file diff --git a/app/Models/Chapter.php b/app/Models/Chapter.php index 9a750f47..e51fc963 100644 --- a/app/Models/Chapter.php +++ b/app/Models/Chapter.php @@ -23,7 +23,6 @@ class Chapter extends Model * 点播扩展属性 */ protected $_vod_attrs = [ - 'model' => 'vod', 'duration' => 0, 'file_id' => '', 'file_status' => 'pending', @@ -35,7 +34,6 @@ class Chapter extends Model * 直播扩展属性 */ protected $_live_attrs = [ - 'model' => 'live', 'start_time' => 0, 'end_time' => 0, ]; @@ -46,7 +44,6 @@ class Chapter extends Model * 图文扩展属性 */ protected $_read_attrs = [ - 'model' => 'read', 'duration' => 0, 'word_count' => 0, ]; @@ -100,6 +97,13 @@ class Chapter extends Model */ public $free; + /** + * 模式类型 + * + * @var string + */ + public $model; + /** * 扩展属性 * @@ -195,6 +199,8 @@ class Chapter extends Model $course = Course::findFirst($this->course_id); + $this->model = $course->model; + $attrs = []; switch ($course->model) { diff --git a/app/Models/ImChatGroup.php b/app/Models/ImChatGroup.php index 3c9a1f3f..ae313239 100644 --- a/app/Models/ImChatGroup.php +++ b/app/Models/ImChatGroup.php @@ -22,6 +22,13 @@ class ImChatGroup extends Model */ public $course_id; + /** + * 群主编号 + * + * @var string + */ + public $user_id; + /** * 名称 * diff --git a/app/Repos/ImChatGroupUser.php b/app/Repos/ImChatGroupUser.php index 4737a78c..2e24e72c 100644 --- a/app/Repos/ImChatGroupUser.php +++ b/app/Repos/ImChatGroupUser.php @@ -9,15 +9,15 @@ class ImChatGroupUser extends Repository { /** - * @param int $userId * @param int $groupId + * @param int $userId * @return ImChatGroupUserModel|Model|bool */ - public function findGroupUser($userId, $groupId) + public function findGroupUser($groupId, $userId) { return ImChatGroupUserModel::findFirst([ - 'conditions' => 'user_id = ?1 AND group_id = ?2', - 'bind' => [1 => $userId, 2 => $groupId], + 'conditions' => 'group_id = ?1 AND user_id = ?2', + 'bind' => [1 => $groupId, 2 => $userId], 'order' => 'id DESC', ]); } diff --git a/app/Services/Frontend/Chapter/ChapterBasic.php b/app/Services/Frontend/Chapter/ChapterBasic.php index cb59acb0..d870ded8 100644 --- a/app/Services/Frontend/Chapter/ChapterBasic.php +++ b/app/Services/Frontend/Chapter/ChapterBasic.php @@ -25,14 +25,9 @@ class ChapterBasic extends FrontendService protected function handleChapter(ChapterModel $chapter) { - /** - * @var array $attrs - */ - $attrs = $chapter->attrs; - $result = []; - switch ($attrs['model']) { + switch ($chapter->model) { case CourseModel::MODEL_VOD: $result = $this->formatChapterVod($chapter); break; @@ -62,7 +57,7 @@ class ChapterBasic extends FrontendService 'id' => $chapter->id, 'title' => $chapter->title, 'summary' => $chapter->summary, - 'model' => $attrs['model'], + 'model' => $chapter->model, 'play_urls' => $playUrls, 'user_count' => $chapter->user_count, 'agree_count' => $chapter->agree_count, @@ -98,7 +93,7 @@ class ChapterBasic extends FrontendService 'id' => $chapter->id, 'title' => $chapter->title, 'summary' => $chapter->summary, - 'model' => $attrs['model'], + 'model' => $chapter->model, 'play_urls' => $playUrls, 'start_time' => $live->start_time, 'end_time' => $live->end_time, @@ -115,16 +110,11 @@ class ChapterBasic extends FrontendService $read = $chapterRepo->findChapterRead($chapter->id); - /** - * @var array $attrs - */ - $attrs = $chapter->attrs; - return [ 'id' => $chapter->id, 'title' => $chapter->title, 'summary' => $chapter->summary, - 'model' => $attrs['model'], + 'model' => $chapter->model, 'content' => $read->content, 'user_count' => $chapter->user_count, 'agree_count' => $chapter->agree_count, diff --git a/app/Services/Frontend/Chapter/ChapterInfo.php b/app/Services/Frontend/Chapter/ChapterInfo.php index c58bd8b0..deb7ee77 100644 --- a/app/Services/Frontend/Chapter/ChapterInfo.php +++ b/app/Services/Frontend/Chapter/ChapterInfo.php @@ -139,7 +139,7 @@ class ChapterInfo extends FrontendService 'id' => $chapter->id, 'title' => $chapter->title, 'summary' => $chapter->summary, - 'model' => $attrs['model'], + 'model' => $chapter->model, 'play_urls' => $playUrls, 'user_count' => $chapter->user_count, 'agree_count' => $chapter->agree_count, @@ -163,7 +163,7 @@ class ChapterInfo extends FrontendService 'id' => $chapter->id, 'title' => $chapter->title, 'summary' => $chapter->summary, - 'model' => $attrs['model'], + 'model' => $chapter->model, 'start_time' => $attrs['start_time'], 'end_time' => $attrs['end_time'], 'play_urls' => $playUrls, @@ -189,7 +189,7 @@ class ChapterInfo extends FrontendService 'id' => $chapter->id, 'title' => $chapter->title, 'summary' => $chapter->summary, - 'model' => $attrs['model'], + 'model' => $chapter->model, 'content' => $read->content, 'user_count' => $chapter->user_count, 'agree_count' => $chapter->agree_count, diff --git a/app/Services/Frontend/Chapter/Learning.php b/app/Services/Frontend/Chapter/Learning.php index 475c37fe..d87300cb 100644 --- a/app/Services/Frontend/Chapter/Learning.php +++ b/app/Services/Frontend/Chapter/Learning.php @@ -33,12 +33,7 @@ class Learning extends FrontendService $data['request_id'] = $validator->checkRequestId($post['request_id']); $data['plan_id'] = $validator->checkPlanId($post['plan_id']); - /** - * @var array $attrs - */ - $attrs = $chapter->attrs; - - if ($attrs['model'] == CourseModel::MODEL_VOD) { + if ($chapter->model == CourseModel::MODEL_VOD) { $data['position'] = $validator->checkPosition($post['position']); } diff --git a/app/Validators/ImChatGroupUser.php b/app/Validators/ImChatGroupUser.php index 5749033c..de0e1f0a 100644 --- a/app/Validators/ImChatGroupUser.php +++ b/app/Validators/ImChatGroupUser.php @@ -8,6 +8,26 @@ use App\Repos\ImChatGroupUser as ImChatGroupUserRepo; class ImChatGroupUser extends Validator { + public function checkGroup($groupId) + { + $validator = new ImChatGroup(); + + return $validator->checkGroup($groupId); + } + + public function checkRemark($remark) + { + $value = $this->filter->sanitize($remark, ['trim', 'string']); + + $length = kg_strlen($value); + + if ($length > 30) { + throw new BadRequestException('im_chat_group_user.remark_too_long'); + } + + return $remark; + } + public function checkIfJoined($userId, $groupId) { $repo = new ImChatGroupUserRepo(); diff --git a/config/errors.php b/config/errors.php index 5a453244..5d8cfe84 100644 --- a/config/errors.php +++ b/config/errors.php @@ -341,6 +341,7 @@ $error['im_chat_group.about_too_long'] = '群组简介太长(超过255字符 $error['im_chat_group_user.has_joined'] = '已经加入过群组'; $error['im_chat_group_user.blocked'] = '对方拒绝接收消息'; +$error['im_chat_group_user.remark_too_long'] = '验证信息太长(超过30字符)'; $error['im_friend_user.user_not_found'] = '用户不存在'; $error['im_friend_user.remark_too_long'] = '验证信息太长(超过30字符)'; diff --git a/public/static/admin/js/common.js b/public/static/admin/js/common.js index 8e8b4e4b..2c5629c6 100644 --- a/public/static/admin/js/common.js +++ b/public/static/admin/js/common.js @@ -48,7 +48,7 @@ layui.use(['jquery', 'form', 'element', 'layer', 'dropdown'], function () { form.on('switch(published)', function (data) { var checked = $(this).is(':checked'); var published = checked ? 1 : 0; - var url = $(this).attr('data-url'); + var url = $(this).data('url'); var tips = published === 1 ? '确定要上线?' : '确定要下线?'; layer.confirm(tips, function () { $.ajax({ @@ -73,7 +73,7 @@ layui.use(['jquery', 'form', 'element', 'layer', 'dropdown'], function () { $('.kg-priority-input').on('change', function () { var priority = $(this).val(); - var url = $(this).attr('data-url'); + var url = $(this).data('url'); $.ajax({ type: 'POST', url: url, @@ -89,7 +89,7 @@ layui.use(['jquery', 'form', 'element', 'layer', 'dropdown'], function () { }); $('.kg-delete,.kg-restore').on('click', function () { - var url = $(this).attr('data-url'); + var url = $(this).data('url'); var tips = $(this).hasClass('kg-delete') ? '确定要删除吗?' : '确定要还原吗?'; layer.confirm(tips, function () { $.ajax({ diff --git a/public/static/admin/js/index.js b/public/static/admin/js/index.js index b294525b..0e764eee 100644 --- a/public/static/admin/js/index.js +++ b/public/static/admin/js/index.js @@ -4,10 +4,10 @@ layui.use(['jquery', 'element'], function () { $('.kg-nav-module > li').on('click', function () { - var module = $(this).attr('data-module'); + var module = $(this).data('module'); $('.layui-nav-tree').each(function () { - if ($(this).attr('data-module') === module) { + if ($(this).data('module') === module) { $(this).removeClass('layui-hide'); window.frames['content'].location.href = $(this).find('a[target=content]:first').attr('href'); } else { diff --git a/public/static/lib/layui/extends/helper.js b/public/static/lib/layui/extends/helper.js new file mode 100644 index 00000000..781720b7 --- /dev/null +++ b/public/static/lib/layui/extends/helper.js @@ -0,0 +1,20 @@ +layui.define(['jquery', 'element'], function (exports) { + + var MOD_NAME = 'helper'; + var $ = layui.jquery; + var element = layui.element; + + var helper = {}; + + helper.ajaxLoadHtml = function (url, target) { + var $target = $('#' + target); + var html = '
'; + $target.html(html); + $.get(url, function (html) { + $target.html(html); + element.init(); + }); + }; + + exports(MOD_NAME, helper); +}); \ No newline at end of file diff --git a/public/static/web/js/captcha.login.js b/public/static/web/js/captcha.login.js index 945d2d19..d6464d19 100644 --- a/public/static/web/js/captcha.login.js +++ b/public/static/web/js/captcha.login.js @@ -2,7 +2,7 @@ layui.use(['jquery'], function () { var $ = layui.jquery; var captcha = new TencentCaptcha( $('#captcha-btn')[0], - $('#captcha-btn').attr('data-app-id'), + $('#captcha-btn').data('app-id'), function (res) { if (res.ret === 0) { $('#ticket').val(res.ticket); diff --git a/public/static/web/js/captcha.verify.js b/public/static/web/js/captcha.verify.js index d65737b3..6322b529 100644 --- a/public/static/web/js/captcha.verify.js +++ b/public/static/web/js/captcha.verify.js @@ -42,7 +42,7 @@ layui.use(['jquery', 'util'], function () { $account.on('keyup', function () { var accountOk; - var type = $(this).attr('data-type'); + var type = $(this).data('type'); var account = $(this).val(); if (type === 'phone') { accountOk = isPhone(account); diff --git a/public/static/web/js/common.js b/public/static/web/js/common.js index 43841ee3..cfd081c8 100644 --- a/public/static/web/js/common.js +++ b/public/static/web/js/common.js @@ -1,23 +1,15 @@ -layui.define(['jquery', 'element'], function (exports) { - exports('ajaxLoadHtml', function (url, target) { - var $ = layui.jquery; - var element = layui.element; - var $target = $('#' + target); - var html = '
'; - $target.html(html); - $.get(url, function (html) { - $target.html(html); - element.init(); - }); - }); +layui.config({ + base: '/static/lib/layui/extends/' +}).extend({ + helper: 'helper' }); -layui.use(['jquery', 'form', 'element', 'layer'], function () { +layui.use(['jquery', 'form', 'element', 'layer', 'helper'], function () { var $ = layui.jquery; - var element = layui.element; var form = layui.form; var layer = layui.layer; + var helper = layui.helper; $.ajaxSetup({ beforeSend: function (xhr) { @@ -72,7 +64,7 @@ layui.use(['jquery', 'form', 'element', 'layer'], function () { }); $('.kg-delete').on('click', function () { - var url = $(this).attr('data-url'); + var url = $(this).data('url'); var tips = '确定要删除吗?'; layer.confirm(tips, function () { $.ajax({ @@ -101,9 +93,11 @@ layui.use(['jquery', 'form', 'element', 'layer'], function () { }); $('body').on('click', '.layui-laypage > a', function () { - var url = $(this).attr('data-url'); - var target = $(this).attr('data-target'); - layui.ajaxLoadHtml(url, target); + var url = $(this).data('url'); + var target = $(this).data('target'); + if (url.length > 0 && target.length > 0) { + helper.ajaxLoadHtml(url, target); + } }); }); \ No newline at end of file diff --git a/public/static/web/js/course.show.js b/public/static/web/js/course.show.js index 3441694e..b16dd266 100644 --- a/public/static/web/js/course.show.js +++ b/public/static/web/js/course.show.js @@ -1,30 +1,36 @@ -layui.use(['jquery', 'element'], function () { +layui.use(['jquery', 'helper'], function () { var $ = layui.jquery; + var helper = layui.helper; if ($('#tab-packages').length > 0) { var $tabPackages = $('#tab-packages'); - layui.ajaxLoadHtml($tabPackages.attr('data-url'), $tabPackages.attr('id')); + helper.ajaxLoadHtml($tabPackages.data('url'), $tabPackages.attr('id')); } + if ($('#tab-consults').length > 0) { var $tabConsults = $('#tab-consults'); - layui.ajaxLoadHtml($tabConsults.attr('data-url'), $tabConsults.attr('id')); + helper.ajaxLoadHtml($tabConsults.data('url'), $tabConsults.attr('id')); } + if ($('#tab-reviews').length > 0) { var $tabReviews = $('#tab-reviews'); - layui.ajaxLoadHtml($tabReviews.attr('data-url'), $tabReviews.attr('id')); + helper.ajaxLoadHtml($tabReviews.data('url'), $tabReviews.attr('id')); } + if ($('#sidebar-topics').length > 0) { var $sdTopics = $('#sidebar-topics'); - layui.ajaxLoadHtml($sdTopics.attr('data-url'), $sdTopics.attr('id')); + helper.ajaxLoadHtml($sdTopics.data('url'), $sdTopics.attr('id')); } + if ($('#sidebar-recommended').length > 0) { var $sdRecommended = $('#sidebar-recommended'); - layui.ajaxLoadHtml($sdRecommended.attr('data-url'), $sdRecommended.attr('id')); + helper.ajaxLoadHtml($sdRecommended.data('url'), $sdRecommended.attr('id')); } + if ($('#sidebar-related').length > 0) { var $sdRelated = $('#sidebar-related'); - layui.ajaxLoadHtml($sdRelated.attr('data-url'), $sdRelated.attr('id')); + helper.ajaxLoadHtml($sdRelated.data('url'), $sdRelated.attr('id')); } }); \ No newline at end of file diff --git a/public/static/web/js/im.find.js b/public/static/web/js/im.find.js index 26a16cab..7ae3284d 100644 --- a/public/static/web/js/im.find.js +++ b/public/static/web/js/im.find.js @@ -1,22 +1,23 @@ -layui.use(['jquery', 'form', 'layer', 'layim'], function () { +layui.use(['jquery', 'form', 'layer', 'layim', 'helper'], function () { var $ = layui.jquery; var form = layui.form; var layer = layui.layer; var layim = layui.layim; + var helper = layui.helper; form.on('submit(im_search)', function (data) { var usersUrl = '/im/search?limit=12&target=tab-users&type=user&query=' + data.field.query; var groupsUrl = '/im/search?limit=12&target=tab-groups&type=group&query=' + data.field.query; - layui.ajaxLoadHtml(usersUrl, 'tab-users'); - layui.ajaxLoadHtml(groupsUrl, 'tab-groups'); + helper.ajaxLoadHtml(usersUrl, 'tab-users'); + helper.ajaxLoadHtml(groupsUrl, 'tab-groups'); return false; }); $('body').on('click', '.apply-friend', function () { - var friendId = $(this).attr('data-id'); - var username = $(this).attr('data-name'); - var avatar = $(this).attr('data-avatar'); + var friendId = $(this).data('id'); + var username = $(this).data('name'); + var avatar = $(this).data('avatar'); layim.add({ type: 'friend', username: username, @@ -44,9 +45,9 @@ layui.use(['jquery', 'form', 'layer', 'layim'], function () { }); $('body').on('click', '.apply-group', function () { - var groupId = $(this).attr('data-id'); - var groupName = $(this).attr('data-name'); - var avatar = $(this).attr('data-avatar'); + var groupId = $(this).data('id'); + var groupName = $(this).data('name'); + var avatar = $(this).data('avatar'); layim.add({ type: 'group', groupname: groupName, diff --git a/public/static/web/js/im.js b/public/static/web/js/im.js index 2a2b3df7..57282bf9 100644 --- a/public/static/web/js/im.js +++ b/public/static/web/js/im.js @@ -22,12 +22,18 @@ layui.use(['jquery', 'layim'], function () { if (data.type === 'ping') { socket.send('pong...'); } else if (data.type === 'bind_user') { - bindUser(data.client_id); - refreshSystemMessage(); + bindUser(data); + showSystemMessage(); } else if (data.type === 'show_chat_msg') { - showChatMessage(data.message); - } else if (data.type === 'refresh_sys_msg') { - refreshSystemMessage(); + showChatMessage(data); + } else if (data.type === 'show_sys_msg') { + showSystemMessage(); + } else if (data.type === 'friend_accepted') { + friendAccepted(data); + showSystemMessage(); + } else if (data.type === 'group_accepted') { + groupAccepted(data); + showSystemMessage(); } }; @@ -52,7 +58,7 @@ layui.use(['jquery', 'layim'], function () { }); layim.on('sendMessage', function (res) { - sendChatMessage(res.mine, res.to); + sendChatMessage(res); }); layim.on('sign', function (sign) { @@ -63,27 +69,27 @@ layui.use(['jquery', 'layim'], function () { }); }); - function bindUser(clientId) { + function bindUser(res) { $.ajax({ type: 'POST', url: '/im/user/bind', - data: {client_id: clientId} + data: {client_id: res.client_id} }); } - function sendChatMessage(from, to) { + function sendChatMessage(res) { $.ajax({ type: 'POST', url: '/im/msg/send', - data: {from: from, to: to} + data: {from: res.mine, to: res.to} }); } - function showChatMessage(message) { - layim.getMessage(message); + function showChatMessage(res) { + layim.getMessage(res.message); } - function refreshSystemMessage() { + function showSystemMessage() { $.ajax({ type: 'GET', url: '/im/msg/unread/count', @@ -95,4 +101,23 @@ layui.use(['jquery', 'layim'], function () { }); } + function friendAccepted(res) { + layim.addList({ + type: 'friend', + groupid: res.group.id, + username: res.friend.name, + avatar: res.friend.avatar, + id: res.friend.id + }); + } + + function groupAccepted(res) { + layim.addList({ + type: 'group', + groupname: res.group.name, + avatar: res.group.avatar, + id: res.group.id + }); + } + }); \ No newline at end of file diff --git a/public/static/web/js/im.msgbox.js b/public/static/web/js/im.msgbox.js index a3736f55..272fe28b 100644 --- a/public/static/web/js/im.msgbox.js +++ b/public/static/web/js/im.msgbox.js @@ -46,7 +46,6 @@ layui.use(['jquery', 'layer', 'layim', 'laypage'], function () { $.post('/im/msg/read'); } - //操作 var action = { acceptFriend: function (othis) { var li = othis.parents('li'); @@ -72,7 +71,7 @@ layui.use(['jquery', 'layer', 'layim', 'laypage'], function () { username: sender.data('name'), avatar: sender.data('avatar'), id: sender.data('id'), - groupid: group, + groupid: group }); othis.parent().html('已同意'); parent.layer.close(index); @@ -96,8 +95,30 @@ layui.use(['jquery', 'layer', 'layim', 'laypage'], function () { }); }, acceptGroup: function (othis) { + var li = othis.parents('li'); + $.ajax({ + type: 'POST', + url: '/im/group/accept', + data: {message_id: li.data('id')}, + success: function () { + layer.close(index); + othis.parent().html('已同意'); + } + }); }, refuseGroup: function (othis) { + var li = othis.parents('li'); + layer.confirm('确定拒绝吗?', function (index) { + $.ajax({ + type: 'POST', + url: '/im/group/refuse', + data: {message_id: li.data('id')}, + success: function () { + layer.close(index); + othis.parent().html('已拒绝'); + } + }); + }); } }; diff --git a/public/static/web/js/user.show.js b/public/static/web/js/user.show.js index 55014323..de5678b1 100644 --- a/public/static/web/js/user.show.js +++ b/public/static/web/js/user.show.js @@ -1,18 +1,19 @@ -layui.use(['jquery', 'element'], function () { +layui.use(['jquery', 'helper'], function () { var $ = layui.jquery; + var helper = layui.helper; if ($('#tab-courses').length > 0) { var $tabCourses = $('#tab-courses'); - layui.ajaxLoadHtml($tabCourses.attr('data-url'), $tabCourses.attr('id')); + helper.ajaxLoadHtml($tabCourses.data('url'), $tabCourses.attr('id')); } if ($('#tab-favorites').length > 0) { var $tabFavorites = $('#tab-favorites'); - layui.ajaxLoadHtml($tabFavorites.attr('data-url'), $tabFavorites.attr('id')); + helper.ajaxLoadHtml($tabFavorites.data('url'), $tabFavorites.attr('id')); } if ($('#tab-friends').length > 0) { var $tabFriends = $('#tab-friends'); - layui.ajaxLoadHtml($tabFriends.attr('data-url'), $tabFriends.attr('id')); + helper.ajaxLoadHtml($tabFriends.data('url'), $tabFriends.attr('id')); } }); \ No newline at end of file diff --git a/public/static/web/js/vip.js b/public/static/web/js/vip.js new file mode 100644 index 00000000..352d7370 --- /dev/null +++ b/public/static/web/js/vip.js @@ -0,0 +1,16 @@ +layui.use(['jquery', 'helper'], function () { + + var $ = layui.jquery; + var helper = layui.helper; + + if ($('#tab-courses').length > 0) { + var $tabCourses = $('#tab-courses'); + helper.ajaxLoadHtml($tabCourses.data('url'), $tabCourses.attr('id')); + } + + if ($('#tab-users').length > 0) { + var $tabUsers = $('#tab-users'); + helper.ajaxLoadHtml($tabUsers.data('url'), $tabUsers.attr('id')); + } + +}); \ No newline at end of file