diff --git a/app/Console/Tasks/DeliverTask.php b/app/Console/Tasks/DeliverTask.php index d41a22b7..e15007da 100644 --- a/app/Console/Tasks/DeliverTask.php +++ b/app/Console/Tasks/DeliverTask.php @@ -21,17 +21,13 @@ use Phalcon\Mvc\Model\ResultsetInterface; class DeliverTask extends Task { - const TRY_COUNT = 3; - public function mainAction() { $logger = $this->getLogger('order'); $tasks = $this->findTasks(30); - if ($tasks->count() == 0) { - return; - } + if ($tasks->count() == 0) return; $orderRepo = new OrderRepo(); @@ -84,7 +80,7 @@ class DeliverTask extends Task $task->try_count += 1; $task->priority += 1; - if ($task->try_count > self::TRY_COUNT) { + if ($task->try_count > $task->max_try_count) { $task->status = TaskModel::STATUS_FAILED; } diff --git a/app/Console/Tasks/NoticeTask.php b/app/Console/Tasks/NoticeTask.php index 7d17318d..17613ae7 100644 --- a/app/Console/Tasks/NoticeTask.php +++ b/app/Console/Tasks/NoticeTask.php @@ -3,6 +3,10 @@ namespace App\Console\Tasks; use App\Models\Task as TaskModel; +use App\Services\DingTalk\Notice\ConsultCreate as ConsultCreateNotice; +use App\Services\DingTalk\Notice\CustomService as CustomServiceNotice; +use App\Services\DingTalk\Notice\ServerMonitor as ServerMonitorNotice; +use App\Services\DingTalk\Notice\TeacherLive as TeacherLiveNotice; use App\Services\Logic\Notice\AccountLogin as AccountLoginNotice; use App\Services\Logic\Notice\ConsultReply as ConsultReplyNotice; use App\Services\Logic\Notice\LiveBegin as LiveBeginNotice; @@ -14,8 +18,6 @@ use Phalcon\Mvc\Model\ResultsetInterface; class NoticeTask extends Task { - const TRY_COUNT = 3; - public function mainAction() { $logger = $this->getLogger('notice'); @@ -46,6 +48,18 @@ class NoticeTask extends Task case TaskModel::TYPE_NOTICE_CONSULT_REPLY: $this->handleConsultReplyNotice($task); break; + case TaskModel::TYPE_NOTICE_CONSULT_CREATE: + $this->handleConsultCreateNotice($task); + break; + case TaskModel::TYPE_NOTICE_TEACHER_LIVE: + $this->handleTeacherLiveNotice($task); + break; + case TaskModel::TYPE_NOTICE_SERVER_MONITOR: + $this->handleServerMonitorNotice($task); + break; + case TaskModel::TYPE_NOTICE_CUSTOM_SERVICE: + $this->handleCustomServiceNotice($task); + break; } $task->status = TaskModel::STATUS_FINISHED; @@ -57,7 +71,7 @@ class NoticeTask extends Task $task->try_count += 1; $task->priority += 1; - if ($task->try_count > self::TRY_COUNT) { + if ($task->try_count >= $task->max_try_count) { $task->status = TaskModel::STATUS_FAILED; } @@ -108,11 +122,39 @@ class NoticeTask extends Task return $notice->handleTask($task); } + protected function handleConsultCreateNotice(TaskModel $task) + { + $notice = new ConsultCreateNotice(); + + return $notice->handleTask($task); + } + + protected function handleTeacherLiveNotice(TaskModel $task) + { + $notice = new TeacherLiveNotice(); + + return $notice->handleTask($task); + } + + protected function handleServerMonitorNotice(TaskModel $task) + { + $notice = new ServerMonitorNotice(); + + return $notice->handleTask($task); + } + + protected function handleCustomServiceNotice(TaskModel $task) + { + $notice = new CustomServiceNotice(); + + return $notice->handleTask($task); + } + /** * @param int $limit * @return ResultsetInterface|Resultset|TaskModel[] */ - protected function findTasks($limit = 100) + protected function findTasks($limit = 300) { $itemTypes = [ TaskModel::TYPE_NOTICE_ACCOUNT_LOGIN, @@ -120,6 +162,10 @@ class NoticeTask extends Task TaskModel::TYPE_NOTICE_ORDER_FINISH, TaskModel::TYPE_NOTICE_REFUND_FINISH, TaskModel::TYPE_NOTICE_CONSULT_REPLY, + TaskModel::TYPE_NOTICE_CONSULT_CREATE, + TaskModel::TYPE_NOTICE_TEACHER_LIVE, + TaskModel::TYPE_NOTICE_SERVER_MONITOR, + TaskModel::TYPE_NOTICE_CUSTOM_SERVICE, ]; $status = TaskModel::STATUS_PENDING; diff --git a/app/Console/Tasks/OptimizeTableTask.php b/app/Console/Tasks/OptimizeTableTask.php new file mode 100644 index 00000000..7143c0b7 --- /dev/null +++ b/app/Console/Tasks/OptimizeTableTask.php @@ -0,0 +1,71 @@ +optimizeImMessageTable(); + $this->optimizeLearningTable(); + $this->optimizeTaskTable(); + } + + protected function optimizeImMessageTable() + { + $count = ImMessageModel::count(); + + if ($count < 1000000) return; + + $messageModel = new ImMessageModel(); + + $tableName = $messageModel->getSource(); + + $this->db->delete($tableName, "create_time < :create_time", [ + 'create_time' => strtotime('-6 months'), + ]); + + $this->db->execute("OPTIMIZE TABLE {$tableName}"); + } + + protected function optimizeLearningTable() + { + $count = LearningModel::count(); + + if ($count < 1000000) return; + + $learningModel = new LearningModel(); + + $tableName = $learningModel->getSource(); + + $this->db->delete($tableName, "create_time < :create_time", [ + 'create_time' => strtotime('-6 months'), + ]); + + $this->db->execute("OPTIMIZE TABLE {$tableName}"); + } + + protected function optimizeTaskTable() + { + $count = TaskModel::count(); + + if ($count < 1000000) return; + + $taskModel = new TaskModel(); + + $tableName = $taskModel->getSource(); + + $this->db->delete($tableName, "create_time < :create_time AND status > :status", [ + 'create_time' => strtotime('-6 months'), + 'status' => TaskModel::STATUS_PENDING, + ]); + + $this->db->execute("OPTIMIZE TABLE {$tableName}"); + } + +} \ No newline at end of file diff --git a/app/Console/Tasks/PointGiftDeliverTask.php b/app/Console/Tasks/PointGiftDeliverTask.php index 0f8baac9..1af243e7 100644 --- a/app/Console/Tasks/PointGiftDeliverTask.php +++ b/app/Console/Tasks/PointGiftDeliverTask.php @@ -13,6 +13,7 @@ use App\Repos\ImGroup as ImGroupRepo; use App\Repos\ImGroupUser as ImGroupUserRepo; use App\Repos\PointGift as PointGiftRepo; use App\Repos\PointRedeem as PointRedeemRepo; +use App\Services\DingTalk\Notice\PointRedeem as PointRedeemNotice; use App\Services\Logic\Point\PointHistory as PointHistoryService; use Phalcon\Mvc\Model\Resultset; use Phalcon\Mvc\Model\ResultsetInterface; @@ -20,17 +21,13 @@ use Phalcon\Mvc\Model\ResultsetInterface; class PointGiftDeliverTask extends Task { - const TRY_COUNT = 3; - public function mainAction() { $logger = $this->getLogger('point'); $tasks = $this->findTasks(30); - if ($tasks->count() == 0) { - return; - } + if ($tasks->count() == 0) return; $redeemRepo = new PointRedeemRepo(); @@ -77,7 +74,7 @@ class PointGiftDeliverTask extends Task $task->try_count += 1; $task->priority += 1; - if ($task->try_count > self::TRY_COUNT) { + if ($task->try_count > $task->max_try_count) { $task->status = TaskModel::STATUS_FAILED; } @@ -167,7 +164,9 @@ class PointGiftDeliverTask extends Task protected function handleGoodsRedeem(PointRedeemModel $redeem) { + $notice = new PointRedeemNotice(); + $notice->createTask($redeem); } protected function handleCashRedeem(PointRedeemModel $redeem) diff --git a/app/Console/Tasks/RefundTask.php b/app/Console/Tasks/RefundTask.php index 41e04a51..9689542c 100644 --- a/app/Console/Tasks/RefundTask.php +++ b/app/Console/Tasks/RefundTask.php @@ -20,20 +20,13 @@ use Phalcon\Mvc\Model\ResultsetInterface; class RefundTask extends Task { - /** - * 重试次数 - */ - const TRY_COUNT = 3; - public function mainAction() { $logger = $this->getLogger('refund'); $tasks = $this->findTasks(30); - if ($tasks->count() == 0) { - return; - } + if ($tasks->count() == 0) return; $tradeRepo = new TradeRepo(); $orderRepo = new OrderRepo(); @@ -96,7 +89,7 @@ class RefundTask extends Task $task->try_count += 1; $task->priority += 1; - if ($task->try_count > self::TRY_COUNT) { + if ($task->try_count > $task->max_try_count) { $task->status = TaskModel::STATUS_FAILED; } diff --git a/app/Console/Tasks/ServerMonitorTask.php b/app/Console/Tasks/ServerMonitorTask.php new file mode 100644 index 00000000..7c2f4486 --- /dev/null +++ b/app/Console/Tasks/ServerMonitorTask.php @@ -0,0 +1,190 @@ +getSettings('dingtalk.robot'); + + if ($robot['enabled'] == 0) return; + + $items = [ + 'cpu' => $this->checkCPU(), + 'disk' => $this->checkDisk(), + 'mysql' => $this->checkMysql(), + 'redis' => $this->checkRedis(), + 'xunsearch' => $this->checkXunSearch(), + 'websocket' => $this->checkWebSocket(), + ]; + + foreach ($items as $key => $value) { + if (empty($value)) { + unset($items[$key]); + } + } + + if (empty($items)) return; + + $content = implode("\n", $items); + + $notice = new ServerMonitorNotice(); + + $notice->createTask($content); + } + + protected function checkCPU() + { + $coreCount = $this->getCpuCount(); + + $cpu = ServerInfo::cpu(); + + if ($cpu[1] > $coreCount * 0.8) { + return sprintf("cpu负载超过%s", $cpu[1]); + } + } + + protected function checkDisk() + { + $disk = ServerInfo::disk(); + + if ($disk['percent'] > 80) { + return sprintf("disk空间超过%s%%", $disk['percent']); + } + } + + protected function checkMysql() + { + try { + + $benchmark = new Benchmark(); + + $benchmark->start(); + + $user = UserModel::findFirst(); + + $benchmark->stop(); + + $elapsedTime = $benchmark->getElapsedTime(); + + if ($user === false) { + return sprintf("mysql查询失败"); + } + + if ($elapsedTime > 1) { + return sprintf("mysql查询响应超过%s秒", round($elapsedTime, 2)); + } + + } catch (\Exception $e) { + return sprintf("mysql可能存在异常"); + } + } + + protected function checkRedis() + { + try { + + $benchmark = new Benchmark(); + + $benchmark->start(); + + $site = $this->getSettings('site'); + + $benchmark->stop(); + + $elapsedTime = $benchmark->getElapsedTime(); + + if (empty($site)) { + return sprintf("redis查询失败"); + } + + if ($elapsedTime > 1) { + return sprintf("redis查询响应超过%s秒", round($elapsedTime, 2)); + } + + } catch (\Exception $e) { + return sprintf("redis可能存在异常"); + } + } + + protected function checkXunSearch() + { + try { + + $benchmark = new Benchmark(); + + $benchmark->start(); + + $searcher = new UserSearcher(); + + $user = $searcher->search('id:10000'); + + $benchmark->stop(); + + $elapsedTime = $benchmark->getElapsedTime(); + + if (empty($user)) { + return sprintf("xunsearch搜索失败"); + } + + if ($elapsedTime > 1) { + return sprintf("xunsearch搜索响应超过%s秒", round($elapsedTime, 2)); + } + + } catch (\Exception $e) { + return sprintf("xunsearch可能存在异常"); + } + } + + protected function checkWebSocket() + { + try { + + $benchmark = new Benchmark(); + + $config = $this->getConfig(); + + Gateway::$registerAddress = $config->path('websocket.register_address'); + + $benchmark->start(); + + Gateway::isUidOnline(10000); + + $benchmark->stop(); + + $elapsedTime = $benchmark->getElapsedTime(); + + if ($elapsedTime > 1) { + return sprintf("websocket响应超过%s秒", round($elapsedTime, 2)); + } + + } catch (\Exception $e) { + return sprintf("websocket可能存在异常"); + } + } + + protected function getCpuCount() + { + $cpuInfo = file_get_contents('/proc/cpuinfo'); + + preg_match("/^cpu cores\s:\s(\d+)/m", $cpuInfo, $matches); + + $coreCount = intval($matches[1]); + + preg_match_all("/^processor/m", $cpuInfo, $matches); + + $processorCount = count($matches[0]); + + return $coreCount * $processorCount; + } + +} \ No newline at end of file diff --git a/app/Console/Tasks/TeacherLiveNoticeTask.php b/app/Console/Tasks/TeacherLiveNoticeTask.php new file mode 100644 index 00000000..fac00d68 --- /dev/null +++ b/app/Console/Tasks/TeacherLiveNoticeTask.php @@ -0,0 +1,81 @@ +findLives(); + + if ($lives->count() == 0) return; + + $redis = $this->getRedis(); + + $keyName = $this->getCacheKeyName(); + + foreach ($lives as $live) { + $redis->sAdd($keyName, $live->chapter_id); + } + + $redis->expire($keyName, 86400); + } + + /** + * 消费讲师提醒 + */ + public function consumeAction() + { + $redis = $this->getRedis(); + + $keyName = $this->getCacheKeyName(); + + $liveIds = $redis->sMembers($keyName); + + if (count($liveIds) == 0) return; + + $liveRepo = new ChapterLiveRepo(); + + $notice = new TeacherLiveNotice(); + + foreach ($liveIds as $liveId) { + + $live = $liveRepo->findById($liveId); + + if ($live->start_time - time() < 30 * 60) { + + $notice->createTask($live); + + $redis->sRem($keyName, $liveId); + } + } + } + + /** + * @return ResultsetInterface|Resultset|ChapterLiveModel[] + */ + protected function findLives() + { + $today = strtotime(date('Ymd')); + + return ChapterLiveModel::query() + ->betweenWhere('start_time', $today, $today + 86400) + ->execute(); + } + + protected function getCacheKeyName() + { + return 'teacher_live_notice_task'; + } + +} \ No newline at end of file diff --git a/app/Http/Admin/Views/setting/dingtalk_robot.volt b/app/Http/Admin/Views/setting/dingtalk_robot.volt new file mode 100644 index 00000000..9d62e7f4 --- /dev/null +++ b/app/Http/Admin/Views/setting/dingtalk_robot.volt @@ -0,0 +1,62 @@ +{% extends 'templates/main.volt' %} + +{% block content %} + +
+ + + +{% endblock %} \ No newline at end of file diff --git a/app/Http/Home/Controllers/ImController.php b/app/Http/Home/Controllers/ImController.php index 7461363e..133ba5fa 100644 --- a/app/Http/Home/Controllers/ImController.php +++ b/app/Http/Home/Controllers/ImController.php @@ -205,14 +205,14 @@ class ImController extends Controller /** * @Post("/msg/cs/send", name="home.im.send_cs_msg") */ - public function sendCsMessageAction() + public function sendCustomMessageAction() { $from = $this->request->getPost('from', 'string'); $to = $this->request->getPost('to', 'string'); $service = new ImService(); - $service->sendCsMessage($from, $to); + $service->sendCustomMessage($from, $to); return $this->jsonSuccess(); } diff --git a/app/Http/Home/Services/ImMessageTrait.php b/app/Http/Home/Services/ImMessageTrait.php index 5a4842bb..07b33bd7 100644 --- a/app/Http/Home/Services/ImMessageTrait.php +++ b/app/Http/Home/Services/ImMessageTrait.php @@ -11,6 +11,7 @@ use App\Models\ImMessage as ImMessageModel; use App\Repos\ImFriendUser as ImFriendUserRepo; use App\Repos\ImMessage as ImMessageRepo; use App\Repos\ImUser as ImUserRepo; +use App\Services\DingTalk\Notice\CustomService as CustomServiceNotice; use App\Validators\ImFriendUser as ImFriendUserValidator; use App\Validators\ImGroup as ImGroupValidator; use App\Validators\ImGroupUser as ImGroupUserValidator; @@ -22,7 +23,7 @@ use GatewayClient\Gateway; * layim中普通聊天和自定义聊天中接收方用户名使用的字段不一样,也够坑爹的 * 普通聊天username,自定义聊天name */ -Trait ImMessageTrait +trait ImMessageTrait { public function getChatMessages() @@ -166,9 +167,11 @@ Trait ImMessageTrait } $this->eventsManager->fire('ImMessage:afterCreate', $this, $imMessage); + + return $imMessage; } - public function sendCsMessage($from, $to) + public function sendCustomMessage($from, $to) { $validator = new ImMessageValidator(); @@ -214,7 +217,11 @@ Trait ImMessageTrait unset($to['name']); - $this->sendChatMessage($from, $to); + $message = $this->sendChatMessage($from, $to); + + $this->handleCustomServiceNotice($message); + + return $message; } public function pullUnreadFriendMessages($id) @@ -334,4 +341,11 @@ Trait ImMessageTrait $group->update(); } + protected function handleCustomServiceNotice(ImMessageModel $message) + { + $notice = new CustomServiceNotice(); + + $notice->createTask($message); + } + } \ No newline at end of file diff --git a/app/Models/Task.php b/app/Models/Task.php index 77839de6..de8cb067 100644 --- a/app/Models/Task.php +++ b/app/Models/Task.php @@ -13,12 +13,25 @@ class Task extends Model const TYPE_POINT_GIFT_DELIVER = 3; // 积分礼品派发 const TYPE_LUCKY_GIFT_DELIVER = 4; // 抽奖礼品派发 + /** + * 针对外部用户 + */ const TYPE_NOTICE_ACCOUNT_LOGIN = 11; // 帐号登录通知 const TYPE_NOTICE_LIVE_BEGIN = 12; // 直播开始通知 const TYPE_NOTICE_ORDER_FINISH = 13; // 订单完成通知 const TYPE_NOTICE_REFUND_FINISH = 14; // 退款完成通知 const TYPE_NOTICE_CONSULT_REPLY = 15; // 咨询回复通知 + /** + * 针对内部人员 + */ + const TYPE_NOTICE_CONSULT_CREATE = 31; // 咨询创建通知 + const TYPE_NOTICE_TEACHER_LIVE = 32; // 直播讲师通知 + const TYPE_NOTICE_SERVER_MONITOR = 33; // 服务监控通知 + const TYPE_NOTICE_CUSTOM_SERVICE = 34; // 客服消息通知 + const TYPE_NOTICE_POINT_REDEEM = 35; // 积分兑换通知 + const TYPE_NOTICE_LUCKY_REDEEM = 36; // 抽奖兑换通知 + /** * 优先级 */ @@ -83,6 +96,13 @@ class Task extends Model */ public $try_count = 0; + /** + * 最大重试次数 + * + * @var int + */ + public $max_try_count = 3; + /** * 创建时间 * diff --git a/app/Repos/ChapterLive.php b/app/Repos/ChapterLive.php index 6319a384..74d83587 100644 --- a/app/Repos/ChapterLive.php +++ b/app/Repos/ChapterLive.php @@ -5,6 +5,7 @@ namespace App\Repos; use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder; use App\Models\Chapter as ChapterModel; use App\Models\ChapterLive as ChapterLiveModel; +use Phalcon\Mvc\Model; class ChapterLive extends Repository { @@ -54,4 +55,28 @@ class ChapterLive extends Repository return $pager->paginate(); } + /** + * @param int $id + * @return ChapterLiveModel|Model|bool + */ + public function findById($id) + { + return ChapterLiveModel::findFirst([ + 'conditions' => 'id = :id:', + 'bind' => ['id' => $id], + ]); + } + + /** + * @param int $chapterId + * @return ChapterLiveModel|Model|bool + */ + public function findByChapterId($chapterId) + { + return ChapterLiveModel::findFirst([ + 'conditions' => 'chapter_id = :chapter_id:', + 'bind' => ['chapter_id' => $chapterId], + ]); + } + } diff --git a/app/Services/DingTalk/Notice/ConsultCreate.php b/app/Services/DingTalk/Notice/ConsultCreate.php new file mode 100644 index 00000000..7bb9abf3 --- /dev/null +++ b/app/Services/DingTalk/Notice/ConsultCreate.php @@ -0,0 +1,65 @@ +findById($task->item_id); + + $userRepo = new UserRepo(); + + $user = $userRepo->findById($consult->owner_id); + + $courseRepo = new CourseRepo(); + + $course = $courseRepo->findById($consult->course_id); + + $content = kg_ph_replace("{user.name} 对课程:{course.title} 发起了咨询:\n{consult.question}", [ + 'user.name' => $user->name, + 'course.title' => $course->title, + 'consult.question' => $consult->question, + ]); + + return $this->atCourseTeacher($course->id, $content); + } + + public function createTask(ConsultModel $consult) + { + $keyName = "dingtalk_consult_create_notice:{$consult->owner_id}"; + + $cache = $this->getCache(); + + $content = $cache->get($keyName); + + if ($content) return; + + $cache->save($keyName, 1, 3600); + + $task = new TaskModel(); + + $itemInfo = [ + 'consult' => ['id' => $consult->id], + ]; + + $task->item_id = $consult->id; + $task->item_info = $itemInfo; + $task->item_type = TaskModel::TYPE_NOTICE_CONSULT_CREATE; + $task->priority = TaskModel::PRIORITY_LOW; + $task->status = TaskModel::STATUS_PENDING; + + $task->create(); + } + +} \ No newline at end of file diff --git a/app/Services/DingTalk/Notice/CustomService.php b/app/Services/DingTalk/Notice/CustomService.php new file mode 100644 index 00000000..a57483cb --- /dev/null +++ b/app/Services/DingTalk/Notice/CustomService.php @@ -0,0 +1,59 @@ +findById($task->item_id); + + $userRepo = new UserRepo(); + + $sender = $userRepo->findById($message->sender_id); + + $content = kg_ph_replace("{user.name} 通过在线客服给你发送了消息:{message.content}", [ + 'user.name' => $sender->name, + 'message.content' => $message->content, + ]); + + return $this->atCustomService($content); + } + + public function createTask(ImMessageModel $message) + { + $keyName = "dingtalk_custom_service_notice:{$message->sender_id}"; + + $cache = $this->getCache(); + + $content = $cache->get($keyName); + + if ($content) return; + + $cache->save($keyName, 1, 3600); + + $task = new TaskModel(); + + $itemInfo = [ + 'im_message' => ['id' => $message->id], + ]; + + $task->item_id = $message->id; + $task->item_info = $itemInfo; + $task->item_type = TaskModel::TYPE_NOTICE_CUSTOM_SERVICE; + $task->priority = TaskModel::PRIORITY_MIDDLE; + $task->status = TaskModel::STATUS_PENDING; + + $task->create(); + } + +} \ No newline at end of file diff --git a/app/Services/DingTalk/Notice/LiveTeacher.php b/app/Services/DingTalk/Notice/LiveTeacher.php new file mode 100644 index 00000000..db20b0cb --- /dev/null +++ b/app/Services/DingTalk/Notice/LiveTeacher.php @@ -0,0 +1,49 @@ +findById($task->item_id); + + $courseRepo = new CourseRepo(); + + $course = $courseRepo->findById($live->course_id); + + $content = kg_ph_replace("课程:{course.title} 计划于 {live.start_time} 开播,不要错过直播时间哦!", [ + 'course.title' => $course->title, + 'live.start_time' => date('Y-m-d H:i', $live->start_time), + ]); + + return $this->atCourseTeacher($course->id, $content); + } + + public function createTask(ChapterLiveModel $live) + { + $task = new TaskModel(); + + $itemInfo = [ + 'live' => ['id' => $live->id], + ]; + + $task->item_id = $live->id; + $task->item_info = $itemInfo; + $task->item_type = TaskModel::TYPE_NOTICE_TEACHER_LIVE; + $task->priority = TaskModel::PRIORITY_LOW; + $task->status = TaskModel::STATUS_PENDING; + + $task->create(); + } + +} \ No newline at end of file diff --git a/app/Services/DingTalk/Notice/PointRedeem.php b/app/Services/DingTalk/Notice/PointRedeem.php new file mode 100644 index 00000000..791db8b1 --- /dev/null +++ b/app/Services/DingTalk/Notice/PointRedeem.php @@ -0,0 +1,47 @@ +findById($task->item_id); + + $content = kg_ph_replace("{user.name} 兑换了商品 {gift.name},不要忘记发货哦!", [ + 'user.name' => $redeem->user_name, + 'gift.name' => $redeem->gift_name, + ]); + + return $this->atCustomService($content); + } + + public function createTask(PointRedeemModel $redeem) + { + if ($redeem->gift_type != PointGiftModel::TYPE_GOODS) return; + + $task = new TaskModel(); + + $itemInfo = [ + 'point_redeem' => ['id' => $redeem->id], + ]; + + $task->item_id = $redeem->id; + $task->item_info = $itemInfo; + $task->item_type = TaskModel::TYPE_NOTICE_POINT_REDEEM; + $task->priority = TaskModel::PRIORITY_MIDDLE; + $task->status = TaskModel::STATUS_PENDING; + + $task->create(); + } + +} \ No newline at end of file diff --git a/app/Services/DingTalk/Notice/ServerMonitor.php b/app/Services/DingTalk/Notice/ServerMonitor.php new file mode 100644 index 00000000..3901bafc --- /dev/null +++ b/app/Services/DingTalk/Notice/ServerMonitor.php @@ -0,0 +1,36 @@ +item_info['content']; + + return $notice->atTechSupport($content); + } + + public function createTask($content) + { + $task = new TaskModel(); + + $itemInfo = ['content' => $content]; + + $task->item_id = time(); + $task->item_info = $itemInfo; + $task->item_type = TaskModel::TYPE_NOTICE_SERVER_MONITOR; + $task->priority = TaskModel::PRIORITY_HIGH; + $task->status = TaskModel::STATUS_PENDING; + $task->max_try_count = 1; + + $task->create(); + } + +} \ No newline at end of file diff --git a/app/Services/Logic/Consult/ConsultCreate.php b/app/Services/Logic/Consult/ConsultCreate.php index 369fd19a..2ec411dd 100644 --- a/app/Services/Logic/Consult/ConsultCreate.php +++ b/app/Services/Logic/Consult/ConsultCreate.php @@ -6,6 +6,7 @@ use App\Models\Chapter as ChapterModel; use App\Models\Consult as ConsultModel; use App\Models\Course as CourseModel; use App\Models\User as UserModel; +use App\Services\DingTalk\Notice\ConsultCreate as ConsultCreateNotice; use App\Services\Logic\ChapterTrait; use App\Services\Logic\CourseTrait; use App\Services\Logic\Service; @@ -75,6 +76,8 @@ class ConsultCreate extends Service $this->incrUserDailyConsultCount($user); + $this->handleConsultCreateNotice($consult); + return $consult; } @@ -111,6 +114,8 @@ class ConsultCreate extends Service $this->incrUserDailyConsultCount($user); + $this->handleConsultCreateNotice($consult); + return $consult; } @@ -150,4 +155,11 @@ class ConsultCreate extends Service $this->eventsManager->fire('UserDailyCounter:incrConsultCount', $this, $user); } + protected function handleConsultCreateNotice(ConsultModel $consult) + { + $notice = new ConsultCreateNotice(); + + $notice->createTask($consult); + } + } diff --git a/app/Services/Logic/Notice/AccountLogin.php b/app/Services/Logic/Notice/AccountLogin.php index 6ae4b18f..9f4fdd06 100644 --- a/app/Services/Logic/Notice/AccountLogin.php +++ b/app/Services/Logic/Notice/AccountLogin.php @@ -54,6 +54,7 @@ class AccountLogin extends LogicService $task->item_type = TaskModel::TYPE_NOTICE_ACCOUNT_LOGIN; $task->priority = TaskModel::PRIORITY_LOW; $task->status = TaskModel::STATUS_PENDING; + $task->max_try_count = 1; $task->create(); } diff --git a/app/Services/Logic/Notice/ConsultReply.php b/app/Services/Logic/Notice/ConsultReply.php index 3b77f7c1..34cfaebc 100644 --- a/app/Services/Logic/Notice/ConsultReply.php +++ b/app/Services/Logic/Notice/ConsultReply.php @@ -86,6 +86,7 @@ class ConsultReply extends LogicService $task->item_type = TaskModel::TYPE_NOTICE_CONSULT_REPLY; $task->priority = TaskModel::PRIORITY_LOW; $task->status = TaskModel::STATUS_PENDING; + $task->max_try_count = 1; $task->create(); } diff --git a/app/Services/Logic/Notice/LiveBegin.php b/app/Services/Logic/Notice/LiveBegin.php index f125c56c..a0818d54 100644 --- a/app/Services/Logic/Notice/LiveBegin.php +++ b/app/Services/Logic/Notice/LiveBegin.php @@ -92,6 +92,7 @@ class LiveBegin extends LogicService $task->item_type = TaskModel::TYPE_NOTICE_LIVE_BEGIN; $task->priority = TaskModel::PRIORITY_LOW; $task->status = TaskModel::STATUS_PENDING; + $task->max_try_count = 1; $task->create(); } diff --git a/db/migrations/20210215024511_data_202102151130.php b/db/migrations/20210215024511_data_202102151130.php new file mode 100644 index 00000000..e2d0fde5 --- /dev/null +++ b/db/migrations/20210215024511_data_202102151130.php @@ -0,0 +1,47 @@ + 'dingtalk.robot', + 'item_key' => 'enabled', + 'item_value' => '0', + ], + [ + 'section' => 'dingtalk.robot', + 'item_key' => 'app_secret', + 'item_value' => '', + ], + [ + 'section' => 'dingtalk.robot', + 'item_key' => 'app_token', + 'item_value' => '', + ], + [ + 'section' => 'dingtalk.robot', + 'item_key' => 'ts_mobiles', + 'item_value' => '', + ], + [ + 'section' => 'dingtalk.robot', + 'item_key' => 'cs_mobiles', + 'item_value' => '', + ], + ]; + + $this->table('kg_setting')->insert($rows)->save(); + } + + public function down() + { + $this->getQueryBuilder() + ->delete('kg_setting') + ->where(['section' => 'dingtalk.robot']) + ->execute(); + } + +} diff --git a/db/migrations/20210215034511_schema_202102151230.php b/db/migrations/20210215034511_schema_202102151230.php new file mode 100644 index 00000000..77b94e12 --- /dev/null +++ b/db/migrations/20210215034511_schema_202102151230.php @@ -0,0 +1,28 @@ +table('kg_task') + ->addColumn('max_try_count', 'integer', [ + 'null' => false, + 'default' => '0', + 'limit' => MysqlAdapter::INT_REGULAR, + 'signed' => false, + 'comment' => '最大尝试数', + 'after' => 'try_count', + ])->save(); + } + + public function down() + { + $this->table('kg_task') + ->removeColumn('max_try_count') + ->save(); + } + +} diff --git a/public/static/home/js/im.cs.js b/public/static/home/js/im.cs.js index 06c7727d..f86c831f 100644 --- a/public/static/home/js/im.cs.js +++ b/public/static/home/js/im.cs.js @@ -64,7 +64,7 @@ layui.use(['jquery', 'layim'], function () { }); layim.on('sendMessage', function (res) { - sendCsMessage(res); + sendCustomMessage(res); }); showWelcomeMessage(csUser); @@ -77,7 +77,7 @@ layui.use(['jquery', 'layim'], function () { }); } - function sendCsMessage(res) { + function sendCustomMessage(res) { $.ajax({ type: 'POST', url: '/im/msg/cs/send', diff --git a/scheduler.php b/scheduler.php index 04427af1..253ad168 100644 --- a/scheduler.php +++ b/scheduler.php @@ -16,18 +16,24 @@ $scheduler->php($script, $bin, ['--task' => 'deliver', '--action' => 'main']) $scheduler->php($script, $bin, ['--task' => 'notice', '--action' => 'main']) ->at('*/3 * * * *'); -$scheduler->php($script, $bin, ['--task' => 'sync_learning', '--action' => 'main']) - ->at('*/7 * * * *'); - $scheduler->php($script, $bin, ['--task' => 'vod_event', '--action' => 'main']) ->at('*/5 * * * *'); -$scheduler->php($script, $bin, ['--task' => 'close_trade', '--action' => 'main']) - ->at('*/13 * * * *'); +$scheduler->php($script, $bin, ['--task' => 'sync_learning', '--action' => 'main']) + ->at('*/7 * * * *'); + +$scheduler->php($script, $bin, ['--task' => 'teacher_live_notice', '--action' => 'consume']) + ->at('*/10 * * * *'); $scheduler->php($script, $bin, ['--task' => 'point_gift_deliver', '--action' => 'main']) ->at('*/11 * * * *'); +$scheduler->php($script, $bin, ['--task' => 'server_monitor', '--action' => 'main']) + ->at('*/12 * * * *'); + +$scheduler->php($script, $bin, ['--task' => 'close_trade', '--action' => 'main']) + ->at('*/13 * * * *'); + $scheduler->php($script, $bin, ['--task' => 'close_order', '--action' => 'main']) ->hourly(3); @@ -58,7 +64,10 @@ $scheduler->php($script, $bin, ['--task' => 'revoke_vip', '--action' => 'main']) $scheduler->php($script, $bin, ['--task' => 'sitemap', '--action' => 'main']) ->daily(4, 3); -$scheduler->php($script, $bin, ['--task' => 'renew_live_course_demo', '--action' => 'main']) +$scheduler->php($script, $bin, ['--task' => 'teacher_live_notice', '--action' => 'provide']) ->daily(4, 7); +$scheduler->php($script, $bin, ['--task' => 'optimize_table', '--action' => 'main']) + ->weekly(6, 5, 3); + $scheduler->run(); \ No newline at end of file