1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-30 22:24:55 +08:00

dingtalk通知阶段提交

This commit is contained in:
koogua 2021-02-22 11:31:21 +08:00
parent 6abca790bc
commit d798a5b609
26 changed files with 475 additions and 103 deletions

View File

@ -21,17 +21,13 @@ use Phalcon\Mvc\Model\ResultsetInterface;
class DeliverTask extends Task class DeliverTask extends Task
{ {
const TRY_COUNT = 3;
public function mainAction() public function mainAction()
{ {
$logger = $this->getLogger('order'); $logger = $this->getLogger('order');
$tasks = $this->findTasks(30); $tasks = $this->findTasks(30);
if ($tasks->count() == 0) { if ($tasks->count() == 0) return;
return;
}
$orderRepo = new OrderRepo(); $orderRepo = new OrderRepo();
@ -84,7 +80,7 @@ class DeliverTask extends Task
$task->try_count += 1; $task->try_count += 1;
$task->priority += 1; $task->priority += 1;
if ($task->try_count > self::TRY_COUNT) { if ($task->try_count > $task->max_try_count) {
$task->status = TaskModel::STATUS_FAILED; $task->status = TaskModel::STATUS_FAILED;
} }

View File

@ -3,6 +3,10 @@
namespace App\Console\Tasks; namespace App\Console\Tasks;
use App\Models\Task as TaskModel; 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\AccountLogin as AccountLoginNotice;
use App\Services\Logic\Notice\ConsultReply as ConsultReplyNotice; use App\Services\Logic\Notice\ConsultReply as ConsultReplyNotice;
use App\Services\Logic\Notice\LiveBegin as LiveBeginNotice; use App\Services\Logic\Notice\LiveBegin as LiveBeginNotice;
@ -14,8 +18,6 @@ use Phalcon\Mvc\Model\ResultsetInterface;
class NoticeTask extends Task class NoticeTask extends Task
{ {
const TRY_COUNT = 3;
public function mainAction() public function mainAction()
{ {
$logger = $this->getLogger('notice'); $logger = $this->getLogger('notice');
@ -46,6 +48,18 @@ class NoticeTask extends Task
case TaskModel::TYPE_NOTICE_CONSULT_REPLY: case TaskModel::TYPE_NOTICE_CONSULT_REPLY:
$this->handleConsultReplyNotice($task); $this->handleConsultReplyNotice($task);
break; 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; $task->status = TaskModel::STATUS_FINISHED;
@ -57,7 +71,7 @@ class NoticeTask extends Task
$task->try_count += 1; $task->try_count += 1;
$task->priority += 1; $task->priority += 1;
if ($task->try_count > self::TRY_COUNT) { if ($task->try_count >= $task->max_try_count) {
$task->status = TaskModel::STATUS_FAILED; $task->status = TaskModel::STATUS_FAILED;
} }
@ -108,11 +122,39 @@ class NoticeTask extends Task
return $notice->handleTask($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 * @param int $limit
* @return ResultsetInterface|Resultset|TaskModel[] * @return ResultsetInterface|Resultset|TaskModel[]
*/ */
protected function findTasks($limit = 100) protected function findTasks($limit = 300)
{ {
$itemTypes = [ $itemTypes = [
TaskModel::TYPE_NOTICE_ACCOUNT_LOGIN, TaskModel::TYPE_NOTICE_ACCOUNT_LOGIN,
@ -120,6 +162,10 @@ class NoticeTask extends Task
TaskModel::TYPE_NOTICE_ORDER_FINISH, TaskModel::TYPE_NOTICE_ORDER_FINISH,
TaskModel::TYPE_NOTICE_REFUND_FINISH, TaskModel::TYPE_NOTICE_REFUND_FINISH,
TaskModel::TYPE_NOTICE_CONSULT_REPLY, 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; $status = TaskModel::STATUS_PENDING;

View File

@ -0,0 +1,71 @@
<?php
namespace App\Console\Tasks;
use App\Models\ImMessage as ImMessageModel;
use App\Models\Learning as LearningModel;
use App\Models\Task as TaskModel;
class OptimizeTableTask extends Task
{
public function mainAction()
{
$this->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}");
}
}

View File

@ -13,6 +13,7 @@ use App\Repos\ImGroup as ImGroupRepo;
use App\Repos\ImGroupUser as ImGroupUserRepo; use App\Repos\ImGroupUser as ImGroupUserRepo;
use App\Repos\PointGift as PointGiftRepo; use App\Repos\PointGift as PointGiftRepo;
use App\Repos\PointRedeem as PointRedeemRepo; use App\Repos\PointRedeem as PointRedeemRepo;
use App\Services\DingTalk\Notice\PointRedeem as PointRedeemNotice;
use App\Services\Logic\Point\PointHistory as PointHistoryService; use App\Services\Logic\Point\PointHistory as PointHistoryService;
use Phalcon\Mvc\Model\Resultset; use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface; use Phalcon\Mvc\Model\ResultsetInterface;
@ -20,17 +21,13 @@ use Phalcon\Mvc\Model\ResultsetInterface;
class PointGiftDeliverTask extends Task class PointGiftDeliverTask extends Task
{ {
const TRY_COUNT = 3;
public function mainAction() public function mainAction()
{ {
$logger = $this->getLogger('point'); $logger = $this->getLogger('point');
$tasks = $this->findTasks(30); $tasks = $this->findTasks(30);
if ($tasks->count() == 0) { if ($tasks->count() == 0) return;
return;
}
$redeemRepo = new PointRedeemRepo(); $redeemRepo = new PointRedeemRepo();
@ -77,7 +74,7 @@ class PointGiftDeliverTask extends Task
$task->try_count += 1; $task->try_count += 1;
$task->priority += 1; $task->priority += 1;
if ($task->try_count > self::TRY_COUNT) { if ($task->try_count > $task->max_try_count) {
$task->status = TaskModel::STATUS_FAILED; $task->status = TaskModel::STATUS_FAILED;
} }
@ -167,7 +164,9 @@ class PointGiftDeliverTask extends Task
protected function handleGoodsRedeem(PointRedeemModel $redeem) protected function handleGoodsRedeem(PointRedeemModel $redeem)
{ {
$notice = new PointRedeemNotice();
$notice->createTask($redeem);
} }
protected function handleCashRedeem(PointRedeemModel $redeem) protected function handleCashRedeem(PointRedeemModel $redeem)

View File

@ -20,20 +20,13 @@ use Phalcon\Mvc\Model\ResultsetInterface;
class RefundTask extends Task class RefundTask extends Task
{ {
/**
* 重试次数
*/
const TRY_COUNT = 3;
public function mainAction() public function mainAction()
{ {
$logger = $this->getLogger('refund'); $logger = $this->getLogger('refund');
$tasks = $this->findTasks(30); $tasks = $this->findTasks(30);
if ($tasks->count() == 0) { if ($tasks->count() == 0) return;
return;
}
$tradeRepo = new TradeRepo(); $tradeRepo = new TradeRepo();
$orderRepo = new OrderRepo(); $orderRepo = new OrderRepo();
@ -103,7 +96,7 @@ class RefundTask extends Task
$task->try_count += 1; $task->try_count += 1;
$task->priority += 1; $task->priority += 1;
if ($task->try_count > self::TRY_COUNT) { if ($task->try_count > $task->max_try_count) {
$task->status = TaskModel::STATUS_FAILED; $task->status = TaskModel::STATUS_FAILED;
} }

View File

@ -5,15 +5,19 @@ namespace App\Console\Tasks;
use App\Library\Benchmark; use App\Library\Benchmark;
use App\Library\Utils\ServerInfo; use App\Library\Utils\ServerInfo;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use App\Services\DingTalkNotice; use App\Services\DingTalk\Notice\ServerMonitor as ServerMonitorNotice;
use App\Services\Search\UserSearcher; use App\Services\Search\UserSearcher;
use GatewayClient\Gateway; use GatewayClient\Gateway;
class MonitorTask extends Task class ServerMonitorTask extends Task
{ {
public function mainAction() public function mainAction()
{ {
$robot = $this->getSettings('dingtalk.robot');
if ($robot['enabled'] == 0) return;
$items = [ $items = [
'cpu' => $this->checkCPU(), 'cpu' => $this->checkCPU(),
'disk' => $this->checkDisk(), 'disk' => $this->checkDisk(),
@ -31,20 +35,20 @@ class MonitorTask extends Task
if (empty($items)) return; if (empty($items)) return;
$notice = new DingTalkNotice();
$content = implode("\n", $items); $content = implode("\n", $items);
$notice->atTechSupport($content); $notice = new ServerMonitorNotice();
$notice->createTask($content);
} }
protected function checkCPU() protected function checkCPU()
{ {
$coreCount = $this->getCpuCoreCount(); $coreCount = $this->getCpuCount();
$cpu = ServerInfo::cpu(); $cpu = ServerInfo::cpu();
if ($cpu[1] > $coreCount / 2) { if ($cpu[1] > $coreCount * 0.8) {
return sprintf("cpu负载超过%s", $cpu[1]); return sprintf("cpu负载超过%s", $cpu[1]);
} }
} }
@ -168,13 +172,19 @@ class MonitorTask extends Task
} }
} }
protected function getCpuCoreCount() protected function getCpuCount()
{ {
$cpuInfo = file_get_contents('/proc/cpuinfo'); $cpuInfo = file_get_contents('/proc/cpuinfo');
preg_match_all('/^processor/m', $cpuInfo, $matches); preg_match("/^cpu cores\s:\s(\d+)/m", $cpuInfo, $matches);
return count($matches[0]); $coreCount = intval($matches[1]);
preg_match_all("/^processor/m", $cpuInfo, $matches);
$processorCount = count($matches[0]);
return $coreCount * $processorCount;
} }
} }

View File

@ -3,12 +3,12 @@
namespace App\Console\Tasks; namespace App\Console\Tasks;
use App\Models\ChapterLive as ChapterLiveModel; use App\Models\ChapterLive as ChapterLiveModel;
use App\Repos\Chapter as ChapterRepo; use App\Repos\ChapterLive as ChapterLiveRepo;
use App\Services\DingTalk\Notice\LiveTeacher as LiveTeacherNotice; use App\Services\DingTalk\Notice\TeacherLive as TeacherLiveNotice;
use Phalcon\Mvc\Model\Resultset; use Phalcon\Mvc\Model\Resultset;
use Phalcon\Mvc\Model\ResultsetInterface; use Phalcon\Mvc\Model\ResultsetInterface;
class LiveTeacherNoticeTask extends Task class TeacherLiveNoticeTask extends Task
{ {
/** /**
@ -40,23 +40,23 @@ class LiveTeacherNoticeTask extends Task
$keyName = $this->getCacheKeyName(); $keyName = $this->getCacheKeyName();
$chapterIds = $redis->sMembers($keyName); $liveIds = $redis->sMembers($keyName);
if (count($chapterIds) == 0) return; if (count($liveIds) == 0) return;
$chapterRepo = new ChapterRepo(); $liveRepo = new ChapterLiveRepo();
$notice = new LiveTeacherNotice(); $notice = new TeacherLiveNotice();
foreach ($chapterIds as $chapterId) { foreach ($liveIds as $liveId) {
$live = $chapterRepo->findChapterLive($chapterId); $live = $liveRepo->findById($liveId);
if ($live->start_time - time() < 30 * 60) { if ($live->start_time - time() < 30 * 60) {
$notice->handle($live); $notice->createTask($live);
$redis->sRem($keyName, $chapterId); $redis->sRem($keyName, $liveId);
} }
} }
} }
@ -75,7 +75,7 @@ class LiveTeacherNoticeTask extends Task
protected function getCacheKeyName() protected function getCacheKeyName()
{ {
return 'live_teacher_notice'; return 'teacher_live_notice_task';
} }
} }

View File

@ -6,6 +6,13 @@
<fieldset class="layui-elem-field layui-field-title"> <fieldset class="layui-elem-field layui-field-title">
<legend>钉钉机器人</legend> <legend>钉钉机器人</legend>
</fieldset> </fieldset>
<div class="layui-form-item">
<label class="layui-form-label">启用机器人</label>
<div class="layui-input-block">
<input type="radio" name="enabled" value="1" title="是" {% if robot.enabled == "1" %}checked="checked"{% endif %}>
<input type="radio" name="enabled" value="0" title="否" {% if robot.enabled == "0" %}checked="checked"{% endif %}>
</div>
</div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">App Secret</label> <label class="layui-form-label">App Secret</label>
<div class="layui-input-block"> <div class="layui-input-block">

View File

@ -205,14 +205,14 @@ class ImController extends Controller
/** /**
* @Post("/msg/cs/send", name="home.im.send_cs_msg") * @Post("/msg/cs/send", name="home.im.send_cs_msg")
*/ */
public function sendCsMessageAction() public function sendCustomMessageAction()
{ {
$from = $this->request->getPost('from', 'string'); $from = $this->request->getPost('from', 'string');
$to = $this->request->getPost('to', 'string'); $to = $this->request->getPost('to', 'string');
$service = new ImService(); $service = new ImService();
$service->sendCsMessage($from, $to); $service->sendCustomMessage($from, $to);
return $this->jsonSuccess(); return $this->jsonSuccess();
} }

View File

@ -11,6 +11,7 @@ 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;
use App\Repos\ImUser as ImUserRepo; use App\Repos\ImUser as ImUserRepo;
use App\Services\DingTalk\Notice\CustomService as CustomServiceNotice;
use App\Validators\ImFriendUser as ImFriendUserValidator; use App\Validators\ImFriendUser as ImFriendUserValidator;
use App\Validators\ImGroup as ImGroupValidator; use App\Validators\ImGroup as ImGroupValidator;
use App\Validators\ImGroupUser as ImGroupUserValidator; use App\Validators\ImGroupUser as ImGroupUserValidator;
@ -22,7 +23,7 @@ use GatewayClient\Gateway;
* layim中普通聊天和自定义聊天中接收方用户名使用的字段不一样也够坑爹的 * layim中普通聊天和自定义聊天中接收方用户名使用的字段不一样也够坑爹的
* 普通聊天username,自定义聊天name * 普通聊天username,自定义聊天name
*/ */
Trait ImMessageTrait trait ImMessageTrait
{ {
public function getChatMessages() public function getChatMessages()
@ -166,9 +167,11 @@ Trait ImMessageTrait
} }
$this->eventsManager->fire('ImMessage:afterCreate', $this, $imMessage); $this->eventsManager->fire('ImMessage:afterCreate', $this, $imMessage);
return $imMessage;
} }
public function sendCsMessage($from, $to) public function sendCustomMessage($from, $to)
{ {
$validator = new ImMessageValidator(); $validator = new ImMessageValidator();
@ -214,7 +217,11 @@ Trait ImMessageTrait
unset($to['name']); unset($to['name']);
$this->sendChatMessage($from, $to); $message = $this->sendChatMessage($from, $to);
$this->handleCustomServiceNotice($message);
return $message;
} }
public function pullUnreadFriendMessages($id) public function pullUnreadFriendMessages($id)
@ -334,4 +341,11 @@ Trait ImMessageTrait
$group->update(); $group->update();
} }
protected function handleCustomServiceNotice(ImMessageModel $message)
{
$notice = new CustomServiceNotice();
$notice->createTask($message);
}
} }

View File

@ -13,12 +13,24 @@ class Task extends Model
const TYPE_POINT_GIFT_DELIVER = 3; // 积分礼品派发 const TYPE_POINT_GIFT_DELIVER = 3; // 积分礼品派发
const TYPE_LUCKY_GIFT_DELIVER = 4; // 抽奖礼品派发 const TYPE_LUCKY_GIFT_DELIVER = 4; // 抽奖礼品派发
/**
* 针对外部用户
*/
const TYPE_NOTICE_ACCOUNT_LOGIN = 11; // 帐号登录通知 const TYPE_NOTICE_ACCOUNT_LOGIN = 11; // 帐号登录通知
const TYPE_NOTICE_LIVE_BEGIN = 12; // 直播学员通知 const TYPE_NOTICE_LIVE_BEGIN = 12; // 直播学员通知
const TYPE_NOTICE_ORDER_FINISH = 13; // 订单完成通知 const TYPE_NOTICE_ORDER_FINISH = 13; // 订单完成通知
const TYPE_NOTICE_REFUND_FINISH = 14; // 退款完成通知 const TYPE_NOTICE_REFUND_FINISH = 14; // 退款完成通知
const TYPE_NOTICE_CONSULT_REPLY = 15; // 咨询回复通知 const TYPE_NOTICE_CONSULT_REPLY = 15; // 咨询回复通知
const TYPE_NOTICE_LIVE_TEACHER = 16; // 直播讲师通知
/**
* 针对内部人员
*/
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; // 抽奖兑换通知
/** /**
* 优先级 * 优先级
@ -84,6 +96,13 @@ class Task extends Model
*/ */
public $try_count = 0; public $try_count = 0;
/**
* 最大重试次数
*
* @var int
*/
public $max_try_count = 3;
/** /**
* 创建时间 * 创建时间
* *

View File

@ -5,6 +5,7 @@ namespace App\Repos;
use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder; use App\Library\Paginator\Adapter\QueryBuilder as PagerQueryBuilder;
use App\Models\Chapter as ChapterModel; use App\Models\Chapter as ChapterModel;
use App\Models\ChapterLive as ChapterLiveModel; use App\Models\ChapterLive as ChapterLiveModel;
use Phalcon\Mvc\Model;
class ChapterLive extends Repository class ChapterLive extends Repository
{ {
@ -54,4 +55,28 @@ class ChapterLive extends Repository
return $pager->paginate(); 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],
]);
}
} }

View File

@ -3,6 +3,8 @@
namespace App\Services\DingTalk\Notice; namespace App\Services\DingTalk\Notice;
use App\Models\Consult as ConsultModel; use App\Models\Consult as ConsultModel;
use App\Models\Task as TaskModel;
use App\Repos\Consult as ConsultRepo;
use App\Repos\Course as CourseRepo; use App\Repos\Course as CourseRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\DingTalkNotice; use App\Services\DingTalkNotice;
@ -10,8 +12,12 @@ use App\Services\DingTalkNotice;
class ConsultCreate extends DingTalkNotice class ConsultCreate extends DingTalkNotice
{ {
public function handle(ConsultModel $consult) public function handleTask(TaskModel $task)
{ {
$consultRepo = new ConsultRepo();
$consult = $consultRepo->findById($task->item_id);
$userRepo = new UserRepo(); $userRepo = new UserRepo();
$user = $userRepo->findById($consult->owner_id); $user = $userRepo->findById($consult->owner_id);
@ -26,7 +32,34 @@ class ConsultCreate extends DingTalkNotice
'consult.question' => $consult->question, 'consult.question' => $consult->question,
]); ]);
$this->atCourseTeacher($course->id, $content); 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();
} }
} }

View File

@ -3,15 +3,35 @@
namespace App\Services\DingTalk\Notice; namespace App\Services\DingTalk\Notice;
use App\Models\ImMessage as ImMessageModel; use App\Models\ImMessage as ImMessageModel;
use App\Models\Task as TaskModel;
use App\Repos\ImMessage as ImMessageRepo;
use App\Repos\User as UserRepo; use App\Repos\User as UserRepo;
use App\Services\DingTalkNotice; use App\Services\DingTalkNotice;
class CustomService extends DingTalkNotice class CustomService extends DingTalkNotice
{ {
public function handle(ImMessageModel $message) public function handleTask(TaskModel $task)
{ {
$keyName = "dingtalk_cs_notice:{$message->sender_id}"; $messageRepo = new ImMessageRepo();
$message = $messageRepo->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(); $cache = $this->getCache();
@ -21,16 +41,19 @@ class CustomService extends DingTalkNotice
$cache->save($keyName, 1, 3600); $cache->save($keyName, 1, 3600);
$userRepo = new UserRepo(); $task = new TaskModel();
$sender = $userRepo->findById($message->sender_id); $itemInfo = [
'im_message' => ['id' => $message->id],
];
$content = kg_ph_replace("{user} 通过在线客服给你发送了消息:{message}", [ $task->item_id = $message->id;
'user' => $sender->name, $task->item_info = $itemInfo;
'message' => $message->content, $task->item_type = TaskModel::TYPE_NOTICE_CUSTOM_SERVICE;
]); $task->priority = TaskModel::PRIORITY_MIDDLE;
$task->status = TaskModel::STATUS_PENDING;
$this->atCustomService($content); $task->create();
} }
} }

View File

@ -3,14 +3,20 @@
namespace App\Services\DingTalk\Notice; namespace App\Services\DingTalk\Notice;
use App\Models\ChapterLive as ChapterLiveModel; use App\Models\ChapterLive as ChapterLiveModel;
use App\Models\Task as TaskModel;
use App\Repos\ChapterLive as ChapterLiveRepo;
use App\Repos\Course as CourseRepo; use App\Repos\Course as CourseRepo;
use App\Services\DingTalkNotice; use App\Services\DingTalkNotice;
class LiveTeacher extends DingTalkNotice class TeacherLive extends DingTalkNotice
{ {
public function handle(ChapterLiveModel $live) public function handleTask(TaskModel $task)
{ {
$liveRepo = new ChapterLiveRepo();
$live = $liveRepo->findById($task->item_id);
$courseRepo = new CourseRepo(); $courseRepo = new CourseRepo();
$course = $courseRepo->findById($live->course_id); $course = $courseRepo->findById($live->course_id);
@ -20,7 +26,24 @@ class LiveTeacher extends DingTalkNotice
'live.start_time' => date('Y-m-d H:i', $live->start_time), 'live.start_time' => date('Y-m-d H:i', $live->start_time),
]); ]);
$this->atCourseTeacher($course->id, $content); 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();
} }
} }

View File

@ -1,27 +0,0 @@
<?php
namespace App\Services\DingTalk\Notice;
use App\Models\Order as OrderModel;
use App\Repos\User as UserRepo;
use App\Services\DingTalkNotice;
class OrderFinish extends DingTalkNotice
{
public function handle(OrderModel $order)
{
$userRepo = new UserRepo();
$user = $userRepo->findById($order->owner_id);
$text = kg_ph_replace("开单啦,{user.name} 同学完成了订单!\n订单名称:{order.subject}\n订单金额:¥{order.amount}", [
'user.name' => $user->name,
'order.subject' => $order->subject,
'order.amount' => $order->amount,
]);
$this->send(['text' => $text]);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace App\Services\DingTalk\Notice;
use App\Models\PointGift as PointGiftModel;
use App\Models\PointRedeem as PointRedeemModel;
use App\Models\Task as TaskModel;
use App\Repos\PointRedeem as PointRedeemRepo;
use App\Services\DingTalkNotice;
class PointRedeem extends DingTalkNotice
{
public function handleTask(TaskModel $task)
{
$redeemRepo = new PointRedeemRepo();
$redeem = $redeemRepo->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();
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace App\Services\DingTalk\Notice;
use App\Models\Task as TaskModel;
use App\Services\DingTalkNotice;
class ServerMonitor extends DingTalkNotice
{
public function handleTask(TaskModel $task)
{
$notice = new DingTalkNotice();
$content = $task->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();
}
}

View File

@ -6,6 +6,7 @@ use App\Models\Chapter as ChapterModel;
use App\Models\Consult as ConsultModel; use App\Models\Consult as ConsultModel;
use App\Models\Course as CourseModel; use App\Models\Course as CourseModel;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use App\Services\DingTalk\Notice\ConsultCreate as ConsultCreateNotice;
use App\Services\Logic\ChapterTrait; use App\Services\Logic\ChapterTrait;
use App\Services\Logic\CourseTrait; use App\Services\Logic\CourseTrait;
use App\Services\Logic\Service; use App\Services\Logic\Service;
@ -75,6 +76,8 @@ class ConsultCreate extends Service
$this->incrUserDailyConsultCount($user); $this->incrUserDailyConsultCount($user);
$this->handleConsultCreateNotice($consult);
return $consult; return $consult;
} }
@ -111,6 +114,8 @@ class ConsultCreate extends Service
$this->incrUserDailyConsultCount($user); $this->incrUserDailyConsultCount($user);
$this->handleConsultCreateNotice($consult);
return $consult; return $consult;
} }
@ -150,4 +155,11 @@ class ConsultCreate extends Service
$this->eventsManager->fire('UserDailyCounter:incrConsultCount', $this, $user); $this->eventsManager->fire('UserDailyCounter:incrConsultCount', $this, $user);
} }
protected function handleConsultCreateNotice(ConsultModel $consult)
{
$notice = new ConsultCreateNotice();
$notice->createTask($consult);
}
} }

View File

@ -54,6 +54,7 @@ class AccountLogin extends LogicService
$task->item_type = TaskModel::TYPE_NOTICE_ACCOUNT_LOGIN; $task->item_type = TaskModel::TYPE_NOTICE_ACCOUNT_LOGIN;
$task->priority = TaskModel::PRIORITY_LOW; $task->priority = TaskModel::PRIORITY_LOW;
$task->status = TaskModel::STATUS_PENDING; $task->status = TaskModel::STATUS_PENDING;
$task->max_try_count = 1;
$task->create(); $task->create();
} }

View File

@ -86,6 +86,7 @@ class ConsultReply extends LogicService
$task->item_type = TaskModel::TYPE_NOTICE_CONSULT_REPLY; $task->item_type = TaskModel::TYPE_NOTICE_CONSULT_REPLY;
$task->priority = TaskModel::PRIORITY_LOW; $task->priority = TaskModel::PRIORITY_LOW;
$task->status = TaskModel::STATUS_PENDING; $task->status = TaskModel::STATUS_PENDING;
$task->max_try_count = 1;
$task->create(); $task->create();
} }

View File

@ -92,6 +92,7 @@ class LiveBegin extends LogicService
$task->item_type = TaskModel::TYPE_NOTICE_LIVE_BEGIN; $task->item_type = TaskModel::TYPE_NOTICE_LIVE_BEGIN;
$task->priority = TaskModel::PRIORITY_LOW; $task->priority = TaskModel::PRIORITY_LOW;
$task->status = TaskModel::STATUS_PENDING; $task->status = TaskModel::STATUS_PENDING;
$task->max_try_count = 1;
$task->create(); $task->create();
} }

View File

@ -6,6 +6,11 @@ class Data202102151130 extends Phinx\Migration\AbstractMigration
public function up() public function up()
{ {
$rows = [ $rows = [
[
'section' => 'dingtalk.robot',
'item_key' => 'enabled',
'item_value' => '0',
],
[ [
'section' => 'dingtalk.robot', 'section' => 'dingtalk.robot',
'item_key' => 'app_secret', 'item_key' => 'app_secret',

View File

@ -0,0 +1,28 @@
<?php
use Phinx\Db\Adapter\MysqlAdapter;
class Schema202102151230 extends Phinx\Migration\AbstractMigration
{
public function up()
{
$this->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();
}
}

View File

@ -64,7 +64,7 @@ layui.use(['jquery', 'layim'], function () {
}); });
layim.on('sendMessage', function (res) { layim.on('sendMessage', function (res) {
sendCsMessage(res); sendCustomMessage(res);
}); });
showWelcomeMessage(csUser); showWelcomeMessage(csUser);
@ -77,7 +77,7 @@ layui.use(['jquery', 'layim'], function () {
}); });
} }
function sendCsMessage(res) { function sendCustomMessage(res) {
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: '/im/msg/cs/send', url: '/im/msg/cs/send',

View File

@ -16,21 +16,24 @@ $scheduler->php($script, $bin, ['--task' => 'deliver', '--action' => 'main'])
$scheduler->php($script, $bin, ['--task' => 'notice', '--action' => 'main']) $scheduler->php($script, $bin, ['--task' => 'notice', '--action' => 'main'])
->at('*/3 * * * *'); ->at('*/3 * * * *');
$scheduler->php($script, $bin, ['--task' => 'sync_learning', '--action' => 'main'])
->at('*/7 * * * *');
$scheduler->php($script, $bin, ['--task' => 'vod_event', '--action' => 'main']) $scheduler->php($script, $bin, ['--task' => 'vod_event', '--action' => 'main'])
->at('*/5 * * * *'); ->at('*/5 * * * *');
$scheduler->php($script, $bin, ['--task' => 'close_trade', '--action' => 'main']) $scheduler->php($script, $bin, ['--task' => 'sync_learning', '--action' => 'main'])
->at('*/13 * * * *'); ->at('*/7 * * * *');
$scheduler->php($script, $bin, ['--task' => 'monitor', '--action' => 'main']) $scheduler->php($script, $bin, ['--task' => 'teacher_live_notice', '--action' => 'consume'])
->at('*/12 * * * *'); ->at('*/10 * * * *');
$scheduler->php($script, $bin, ['--task' => 'point_gift_deliver', '--action' => 'main']) $scheduler->php($script, $bin, ['--task' => 'point_gift_deliver', '--action' => 'main'])
->at('*/11 * * * *'); ->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']) $scheduler->php($script, $bin, ['--task' => 'close_order', '--action' => 'main'])
->hourly(3); ->hourly(3);
@ -61,4 +64,10 @@ $scheduler->php($script, $bin, ['--task' => 'revoke_vip', '--action' => 'main'])
$scheduler->php($script, $bin, ['--task' => 'sitemap', '--action' => 'main']) $scheduler->php($script, $bin, ['--task' => 'sitemap', '--action' => 'main'])
->daily(4, 3); ->daily(4, 3);
$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(); $scheduler->run();