群推送
This commit is contained in:
@@ -110,6 +110,9 @@ Route::group('v1/', function () {
|
||||
Route::get('getJdSocialMedia', 'app\cunkebao\controller\WorkbenchController@getJdSocialMedia'); // 获取京东联盟导购媒体
|
||||
Route::get('getJdPromotionSite', 'app\cunkebao\controller\WorkbenchController@getJdPromotionSite'); // 获取京东联盟广告位
|
||||
Route::get('changeLink', 'app\cunkebao\controller\WorkbenchController@changeLink'); // 获取京东联盟广告位
|
||||
|
||||
Route::get('group-push-stats', 'app\cunkebao\controller\WorkbenchController@getGroupPushStats'); // 获取群发统计数据
|
||||
Route::get('group-push-history', 'app\cunkebao\controller\WorkbenchController@getGroupPushHistory'); // 获取推送历史记录列表
|
||||
});
|
||||
|
||||
// 内容库相关
|
||||
|
||||
@@ -111,10 +111,16 @@ class ContentLibraryController extends Controller
|
||||
$sourceType = $this->request->param('sourceType', ''); // 新增:来源类型,1=好友,2=群
|
||||
|
||||
$where = [
|
||||
['userId', '=', $this->request->userInfo['id']],
|
||||
['companyId' , '=', $this->request->userInfo['companyId']],
|
||||
['isDel', '=', 0] // 只查询未删除的记录
|
||||
];
|
||||
|
||||
if(empty($this->request->userInfo['isAdmin'])){
|
||||
$where[] = ['userId', '=', $this->request->userInfo['id']];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 添加名称模糊搜索
|
||||
if ($keyword !== '') {
|
||||
$where[] = ['name', 'like', '%' . $keyword . '%'];
|
||||
@@ -307,11 +313,18 @@ class ContentLibraryController extends Controller
|
||||
return json(['code' => 400, 'msg' => '内容库名称不能为空']);
|
||||
}
|
||||
|
||||
|
||||
$where = [
|
||||
['companyId' , '=', $this->request->userInfo['companyId']],
|
||||
['isDel', '=', 0] // 只查询未删除的记录
|
||||
];
|
||||
|
||||
if(empty($this->request->userInfo['isAdmin'])){
|
||||
$where[] = ['userId', '=', $this->request->userInfo['id']];
|
||||
}
|
||||
|
||||
// 查询内容库是否存在
|
||||
$library = ContentLibrary::where([
|
||||
['id', '=', $param['id']],
|
||||
['userId', '=', $this->request->userInfo['id']]
|
||||
])->find();
|
||||
$library = ContentLibrary::where($where)->find();
|
||||
|
||||
if (!$library) {
|
||||
return json(['code' => 500, 'msg' => '内容库不存在']);
|
||||
@@ -766,16 +779,20 @@ class ContentLibraryController extends Controller
|
||||
$content = Request::param('content', '');
|
||||
$companyId = $this->request->userInfo['companyId'];
|
||||
// 简单验证
|
||||
if (empty($id)) {
|
||||
if (empty($id) && empty($content)) {
|
||||
return json(['code' => 400, 'msg' => '参数错误']);
|
||||
}
|
||||
|
||||
// 查询内容项目是否存在并检查权限
|
||||
$item = ContentItem::alias('ci')
|
||||
->join('content_library cl', 'ci.libraryId = cl.id')
|
||||
->where(['ci.id' => $id, 'ci.isDel' => 0, 'cl.isDel' => 0, 'cl.companyId' => $companyId])
|
||||
->field('ci.*')
|
||||
->find();
|
||||
if(!empty($id)) {
|
||||
// 查询内容项目是否存在并检查权限
|
||||
$item = ContentItem::alias('ci')
|
||||
->join('content_library cl', 'ci.libraryId = cl.id')
|
||||
->where(['ci.id' => $id, 'ci.isDel' => 0, 'cl.isDel' => 0, 'cl.companyId' => $companyId])
|
||||
->field('ci.*')
|
||||
->find();
|
||||
}else{
|
||||
$item['content'] = $content;
|
||||
}
|
||||
|
||||
if (empty($item)) {
|
||||
return json(['code' => 500, 'msg' => '内容项目不存在或无权限操作']);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,16 +39,19 @@ class Workbench extends Validate
|
||||
// 群消息推送特有参数
|
||||
'pushType' => 'requireIf:type,3|in:0,1', // 推送方式 0定时 1立即
|
||||
'targetType' => 'requireIf:type,3|in:1,2', // 推送目标类型:1=群推送,2=好友推送
|
||||
'startTime' => 'requireIf:type,3|dateFormat:H:i',
|
||||
'endTime' => 'requireIf:type,3|dateFormat:H:i',
|
||||
'groupPushSubType' => 'checkGroupPushSubType|in:1,2', // 群推送子类型:1=群群发,2=群公告(仅当targetType=1时有效)
|
||||
'maxPerDay' => 'requireIf:type,3|number|min:1',
|
||||
'pushOrder' => 'requireIf:type,3|in:1,2', // 1最早 2最新
|
||||
'isLoop' => 'requireIf:type,3|in:0,1',
|
||||
'status' => 'requireIf:type,3|in:0,1',
|
||||
'wechatGroups' => 'checkGroupPushTarget|array|min:1', // 当targetType=1时必填
|
||||
'wechatFriends' => 'checkFriendPushTarget|array', // 当targetType=2时可选(可以为空)
|
||||
'deviceGroups' => 'checkFriendPushDevice|array|min:1', // 当targetType=2时必填
|
||||
'ownerWechatId' => 'checkFriendPushService', // 当targetType=2且未选择好友/流量池时必填
|
||||
'contentGroups' => 'requireIf:type,3|array|min:1',
|
||||
// 群公告特有参数
|
||||
'announcementContent' => 'checkAnnouncementContent|max:5000', // 群公告内容(当groupPushSubType=2时必填)
|
||||
'enableAiRewrite' => 'checkEnableAiRewrite|in:0,1', // 是否启用AI智能话术改写
|
||||
'aiRewritePrompt' => 'checkAiRewritePrompt|max:500', // AI改写提示词(当enableAiRewrite=1时必填)
|
||||
// 自动建群特有参数
|
||||
'groupNameTemplate' => 'requireIf:type,4|max:50',
|
||||
'maxGroupsPerDay' => 'requireIf:type,4|number|min:1',
|
||||
@@ -61,6 +64,7 @@ class Workbench extends Validate
|
||||
'accountGroups' => 'requireIf:type,5|array|min:1',
|
||||
// 通用参数
|
||||
'deviceGroups' => 'requireIf:type,1,2,5|array',
|
||||
'trafficPools' => 'checkFriendPushPools',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -123,13 +127,20 @@ class Workbench extends Validate
|
||||
'wechatGroups.checkGroupPushTarget' => '群推送时必须选择推送群组',
|
||||
'wechatGroups.array' => '推送群组格式错误',
|
||||
'wechatGroups.min' => '至少选择一个推送群组',
|
||||
'groupPushSubType.checkGroupPushSubType' => '群推送子类型错误',
|
||||
'groupPushSubType.in' => '群推送子类型只能是群群发或群公告',
|
||||
'announcementContent.checkAnnouncementContent' => '群公告必须输入公告内容',
|
||||
'announcementContent.max' => '公告内容最多5000个字符',
|
||||
'enableAiRewrite.checkEnableAiRewrite' => 'AI智能话术改写参数错误',
|
||||
'enableAiRewrite.in' => 'AI智能话术改写参数只能是0或1',
|
||||
'aiRewritePrompt.checkAiRewritePrompt' => '启用AI智能话术改写时,必须输入改写提示词',
|
||||
'aiRewritePrompt.max' => '改写提示词最多500个字符',
|
||||
'wechatFriends.requireIf' => '请选择推送好友',
|
||||
'wechatFriends.checkFriendPushTarget' => '好友推送时必须选择推送好友',
|
||||
'wechatFriends.array' => '推送好友格式错误',
|
||||
'deviceGroups.requireIf' => '请选择设备',
|
||||
'deviceGroups.checkFriendPushDevice' => '好友推送时必须选择设备',
|
||||
'deviceGroups.array' => '设备格式错误',
|
||||
'deviceGroups.min' => '至少选择一个设备',
|
||||
'ownerWechatId.checkFriendPushService' => '好友推送需选择客服或提供好友/流量池',
|
||||
// 自动建群相关提示
|
||||
'groupNameTemplate.requireIf' => '请设置群名称前缀',
|
||||
'groupNameTemplate.max' => '群名称前缀最多50个字符',
|
||||
@@ -160,6 +171,7 @@ class Workbench extends Validate
|
||||
'accountGroups.requireIf' => '流量分发时必须选择分发账号',
|
||||
'accountGroups.array' => '分发账号格式错误',
|
||||
'accountGroups.min' => '至少选择一个分发账号',
|
||||
'trafficPools.checkFriendPushPools' => '好友推送时请选择好友或流量池',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -169,7 +181,8 @@ class Workbench extends Validate
|
||||
'create' => ['name', 'type', 'autoStart', 'deviceGroups', 'targetGroups',
|
||||
'interval', 'maxLikes', 'startTime', 'endTime', 'contentTypes',
|
||||
'syncCount', 'syncType', 'accountGroups',
|
||||
'pushType', 'targetType', 'startTime', 'endTime', 'maxPerDay', 'pushOrder', 'isLoop', 'status', 'wechatGroups', 'wechatFriends', 'contentGroups',
|
||||
'pushType', 'targetType', 'groupPushSubType', 'startTime', 'endTime', 'maxPerDay', 'pushOrder', 'isLoop', 'status', 'wechatGroups', 'wechatFriends', 'trafficPools', 'ownerWechatId', 'contentGroups',
|
||||
'announcementContent', 'enableAiRewrite', 'aiRewritePrompt',
|
||||
'groupNameTemplate', 'maxGroupsPerDay', 'groupSizeMin', 'groupSizeMax',
|
||||
'distributeType', 'timeType', 'accountGroups',
|
||||
],
|
||||
@@ -177,7 +190,8 @@ class Workbench extends Validate
|
||||
'update' => ['name', 'type', 'autoStart', 'deviceGroups', 'targetGroups',
|
||||
'interval', 'maxLikes', 'startTime', 'endTime', 'contentTypes',
|
||||
'syncCount', 'syncType', 'accountGroups',
|
||||
'pushType', 'targetType', 'startTime', 'endTime', 'maxPerDay', 'pushOrder', 'isLoop', 'status', 'wechatGroups', 'wechatFriends', 'deviceGroups', 'contentGroups',
|
||||
'pushType', 'targetType', 'groupPushSubType', 'startTime', 'endTime', 'maxPerDay', 'pushOrder', 'isLoop', 'status', 'wechatGroups', 'wechatFriends', 'trafficPools', 'ownerWechatId', 'contentGroups',
|
||||
'announcementContent', 'enableAiRewrite', 'aiRewritePrompt',
|
||||
'groupNameTemplate', 'maxGroupsPerDay', 'groupSizeMin', 'groupSizeMax',
|
||||
'distributeType', 'timeType', 'accountGroups',
|
||||
]
|
||||
@@ -243,18 +257,126 @@ class Workbench extends Validate
|
||||
/**
|
||||
* 验证好友推送时设备必填(当targetType=2时,deviceGroups必填)
|
||||
*/
|
||||
protected function checkFriendPushDevice($value, $rule, $data)
|
||||
protected function checkFriendPushService($value, $rule, $data)
|
||||
{
|
||||
if (isset($data['type']) && $data['type'] == self::TYPE_GROUP_PUSH) {
|
||||
$targetType = isset($data['targetType']) ? intval($data['targetType']) : 1; // 默认1
|
||||
if ($targetType == 2) {
|
||||
if ($value !== null && $value !== '' && !is_array($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hasFriends = isset($data['wechatFriends']) && is_array($data['wechatFriends']) && count($data['wechatFriends']) > 0;
|
||||
$hasPools = isset($data['trafficPools']) && is_array($data['trafficPools']) && count($data['trafficPools']) > 0;
|
||||
$hasServices = is_array($value) && count(array_filter($value, function ($item) {
|
||||
if (is_array($item)) {
|
||||
return !empty($item['ownerWechatId'] ?? $item['wechatId'] ?? $item['id']);
|
||||
}
|
||||
return $item !== null && $item !== '';
|
||||
})) > 0;
|
||||
|
||||
if (!$hasFriends && !$hasPools && !$hasServices) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证好友推送时是否选择好友或流量池(至少其一)
|
||||
*/
|
||||
protected function checkFriendPushPools($value, $rule, $data)
|
||||
{
|
||||
if (isset($data['type']) && $data['type'] == self::TYPE_GROUP_PUSH) {
|
||||
$targetType = isset($data['targetType']) ? intval($data['targetType']) : 1; // 默认1
|
||||
if ($targetType == 2) {
|
||||
$hasFriends = isset($data['wechatFriends']) && !empty($data['wechatFriends']);
|
||||
$hasPools = isset($value) && $value !== null && $value !== '' && is_array($value) && count($value) > 0;
|
||||
if (!$hasFriends && !$hasPools) {
|
||||
return false;
|
||||
}
|
||||
if (isset($value) && $value !== null && $value !== '') {
|
||||
if (!is_array($value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证群推送子类型(当targetType=1时,groupPushSubType必填且只能是1或2)
|
||||
*/
|
||||
protected function checkGroupPushSubType($value, $rule, $data)
|
||||
{
|
||||
// 如果是群消息推送类型
|
||||
if (isset($data['type']) && $data['type'] == self::TYPE_GROUP_PUSH) {
|
||||
// 如果targetType=2(好友推送),则deviceGroups必填
|
||||
// 如果targetType=1(群推送),则groupPushSubType必填
|
||||
$targetType = isset($data['targetType']) ? intval($data['targetType']) : 1; // 默认1
|
||||
if ($targetType == 2) {
|
||||
if ($targetType == 1) {
|
||||
// 检查值是否存在且有效
|
||||
if (!isset($value) || $value === null || $value === '') {
|
||||
if (!isset($value) || !in_array(intval($value), [1, 2])) {
|
||||
return false;
|
||||
}
|
||||
if (!is_array($value) || count($value) < 1) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证群公告内容(当groupPushSubType=2时,announcementContent必填)
|
||||
*/
|
||||
protected function checkAnnouncementContent($value, $rule, $data)
|
||||
{
|
||||
// 如果是群消息推送类型
|
||||
if (isset($data['type']) && $data['type'] == self::TYPE_GROUP_PUSH) {
|
||||
// 如果targetType=1且groupPushSubType=2(群公告),则announcementContent必填
|
||||
$targetType = isset($data['targetType']) ? intval($data['targetType']) : 1; // 默认1
|
||||
$groupPushSubType = isset($data['groupPushSubType']) ? intval($data['groupPushSubType']) : 1; // 默认1
|
||||
if ($targetType == 1 && $groupPushSubType == 2) {
|
||||
// 检查值是否存在且有效
|
||||
if (!isset($value) || $value === null || trim($value) === '') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证AI智能话术改写(当enableAiRewrite=1时,aiRewritePrompt必填)
|
||||
*/
|
||||
protected function checkEnableAiRewrite($value, $rule, $data)
|
||||
{
|
||||
// 如果是群消息推送类型且是群公告
|
||||
if (isset($data['type']) && $data['type'] == self::TYPE_GROUP_PUSH) {
|
||||
$targetType = isset($data['targetType']) ? intval($data['targetType']) : 1; // 默认1
|
||||
$groupPushSubType = isset($data['groupPushSubType']) ? intval($data['groupPushSubType']) : 1; // 默认1
|
||||
if ($targetType == 1 && $groupPushSubType == 2) {
|
||||
// 检查值是否存在且有效
|
||||
if (!isset($value) || !in_array(intval($value), [0, 1])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证AI改写提示词(当enableAiRewrite=1时,aiRewritePrompt必填)
|
||||
*/
|
||||
protected function checkAiRewritePrompt($value, $rule, $data)
|
||||
{
|
||||
// 如果是群消息推送类型且是群公告
|
||||
if (isset($data['type']) && $data['type'] == self::TYPE_GROUP_PUSH) {
|
||||
$targetType = isset($data['targetType']) ? intval($data['targetType']) : 1; // 默认1
|
||||
$groupPushSubType = isset($data['groupPushSubType']) ? intval($data['groupPushSubType']) : 1; // 默认1
|
||||
$enableAiRewrite = isset($data['enableAiRewrite']) ? intval($data['enableAiRewrite']) : 0; // 默认0
|
||||
if ($targetType == 1 && $groupPushSubType == 2 && $enableAiRewrite == 1) {
|
||||
// 如果启用AI改写,提示词必填
|
||||
if (!isset($value) || $value === null || trim($value) === '') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,11 +58,18 @@ class WorkbenchGroupPushJob
|
||||
{
|
||||
try {
|
||||
// 获取所有工作台
|
||||
$workbenches = Workbench::where(['status' => 1, 'type' => 3, 'isDel' => 0,'id' => 256])->order('id desc')->select();
|
||||
$workbenches = Workbench::where(['status' => 1, 'type' => 3, 'isDel' => 0,'id' => 264])->order('id desc')->select();
|
||||
foreach ($workbenches as $workbench) {
|
||||
// 获取工作台配置
|
||||
$config = WorkbenchGroupPush::where('workbenchId', $workbench->id)->find();
|
||||
if (!$config) {
|
||||
$configModel = WorkbenchGroupPush::where('workbenchId', $workbench->id)->find();
|
||||
if (!$configModel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 标准化配置
|
||||
$config = $this->normalizeConfig($configModel->toArray());
|
||||
if ($config === false) {
|
||||
Log::warning("消息群发:配置无效,工作台ID: {$workbench->id}");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -72,7 +79,16 @@ class WorkbenchGroupPushJob
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取内容库
|
||||
$targetType = intval($config['targetType']);
|
||||
$groupPushSubType = intval($config['groupPushSubType']);
|
||||
|
||||
// 如果是群推送且是群公告,暂时跳过(晚点处理)
|
||||
if ($targetType == 1 && $groupPushSubType == 2) {
|
||||
Log::info("群公告功能暂未实现,工作台ID: {$workbench->id}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取内容库(群群发需要内容库,好友推送也需要内容库)
|
||||
$contentLibrary = $this->getContentLibrary($workbench, $config);
|
||||
if (empty($contentLibrary)) {
|
||||
continue;
|
||||
@@ -93,7 +109,7 @@ class WorkbenchGroupPushJob
|
||||
// 消息拼接 msgType(1:文本 3:图片 43:视频 47:动图表情包(gif、其他表情包) 49:小程序/其他:图文、文件)
|
||||
// 当前,type 为文本、图片、动图表情包的时候,content为string, 其他情况为对象 {type: 'file/link/...', url: '', title: '', thunmbPath: '', desc: ''}
|
||||
|
||||
$targetType = isset($config['targetType']) ? intval($config['targetType']) : 1; // 默认1=群推送
|
||||
$targetType = intval($config['targetType']); // 默认1=群推送
|
||||
|
||||
$toAccountId = '';
|
||||
$username = Env::get('api.username', '');
|
||||
@@ -103,47 +119,56 @@ class WorkbenchGroupPushJob
|
||||
}
|
||||
// 建立WebSocket
|
||||
$wsController = new WebSocketController(['userName' => $username, 'password' => $password, 'accountId' => $toAccountId]);
|
||||
|
||||
$ownerWechatIds = $config['ownerWechatIds'] ?? $this->getOwnerWechatIds($config);
|
||||
if ($targetType == 1) {
|
||||
// 群推送
|
||||
$this->sendToGroups($workbench, $config, $msgConf, $wsController);
|
||||
$this->sendToGroups($workbench, $config, $msgConf, $wsController, $ownerWechatIds);
|
||||
} else {
|
||||
// 好友推送
|
||||
$this->sendToFriends($workbench, $config, $msgConf, $wsController);
|
||||
$this->sendToFriends($workbench, $config, $msgConf, $wsController, $ownerWechatIds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送群消息
|
||||
*/
|
||||
protected function sendToGroups($workbench, $config, $msgConf, $wsController)
|
||||
protected function sendToGroups($workbench, $config, $msgConf, $wsController, array $ownerWechatIds = [])
|
||||
{
|
||||
$groups = json_decode($config['groups'], true);
|
||||
if (empty($groups)) {
|
||||
// 获取群推送子类型:1=群群发,2=群公告
|
||||
$groupPushSubType = intval($config['groupPushSubType'] ?? 1); // 默认1=群群发
|
||||
|
||||
// 如果是群公告,暂时跳过(晚点处理)
|
||||
if ($groupPushSubType == 2) {
|
||||
Log::info("群公告功能暂未实现,工作台ID: {$workbench['id']}");
|
||||
return false;
|
||||
}
|
||||
|
||||
$groupsData = Db::name('wechat_group')->whereIn('id', $groups)->field('id,wechatAccountId,chatroomId,companyId,ownerWechatId')->select();
|
||||
// 群群发:从groups字段获取群ID列表
|
||||
$groups = $config['groups'] ?? [];
|
||||
if (empty($groups)) {
|
||||
Log::warning("群群发:未选择微信群,工作台ID: {$workbench['id']}");
|
||||
return false;
|
||||
}
|
||||
|
||||
$query = Db::name('wechat_group')
|
||||
->whereIn('id', $groups);
|
||||
|
||||
if (!empty($ownerWechatIds)) {
|
||||
$query->whereIn('wechatAccountId', $ownerWechatIds);
|
||||
}
|
||||
|
||||
$groupsData = $query
|
||||
->field('id,wechatAccountId,chatroomId,companyId,ownerWechatId')
|
||||
->select();
|
||||
if (empty($groupsData)) {
|
||||
Log::warning("群群发:未找到微信群数据,工作台ID: {$workbench['id']}");
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($msgConf as $content) {
|
||||
$sendData = [];
|
||||
$sqlData = [];
|
||||
|
||||
foreach ($groupsData as $group) {
|
||||
// msgType(1:文本 3:图片 43:视频 47:动图表情包(gif、其他表情包) 49:小程序/其他:图文、文件)
|
||||
$sqlData[] = [
|
||||
'workbenchId' => $workbench['id'],
|
||||
'contentId' => $content['id'],
|
||||
'groupId' => $group['id'],
|
||||
'friendId' => null,
|
||||
'targetType' => 1,
|
||||
'wechatAccountId' => $group['wechatAccountId'],
|
||||
'createTime' => time()
|
||||
];
|
||||
|
||||
// 构建发送数据
|
||||
$sendData = $this->buildSendData($content, $config, $group['wechatAccountId'], $group['id'], 'group');
|
||||
if (empty($sendData)) {
|
||||
@@ -154,77 +179,71 @@ class WorkbenchGroupPushJob
|
||||
foreach ($sendData as $send) {
|
||||
$wsController->sendCommunity($send);
|
||||
}
|
||||
//插入发送记录
|
||||
|
||||
// 准备插入发送记录
|
||||
$sqlData[] = [
|
||||
'workbenchId' => $workbench['id'],
|
||||
'contentId' => $content['id'],
|
||||
'groupId' => $group['id'],
|
||||
'friendId' => null,
|
||||
'targetType' => 1,
|
||||
'wechatAccountId' => $group['wechatAccountId'],
|
||||
'createTime' => time()
|
||||
];
|
||||
}
|
||||
|
||||
// 批量插入发送记录
|
||||
if (!empty($sqlData)) {
|
||||
Db::name('workbench_group_push_item')->insertAll($sqlData);
|
||||
Log::info("群群发:推送了" . count($sqlData) . "个群,工作台ID: {$workbench['id']}");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送好友消息
|
||||
*/
|
||||
protected function sendToFriends($workbench, $config, $msgConf, $wsController)
|
||||
protected function sendToFriends($workbench, $config, $msgConf, $wsController, array $ownerWechatIds = [])
|
||||
{
|
||||
$friends = json_decode($config['friends'], true);
|
||||
$devices = json_decode($config['devices'] ?? '[]', true);
|
||||
$friends = $config['friends'] ?? [];
|
||||
$trafficPools = $config['trafficPools'] ?? [];
|
||||
$devices = $config['devices'] ?? [];
|
||||
|
||||
// 如果好友列表为空,则根据设备查询所有好友
|
||||
if (empty($friends)) {
|
||||
if (empty($devices)) {
|
||||
// 如果没有选择设备,则无法推送
|
||||
Log::warning('好友推送:未选择设备,无法推送全部好友');
|
||||
return false;
|
||||
}
|
||||
$friendsData = [];
|
||||
|
||||
// 根据设备查询所有好友
|
||||
$friendsData = Db::table('s2_company_account')
|
||||
->alias('ca')
|
||||
->join(['s2_wechat_account' => 'wa'], 'ca.id = wa.deviceAccountId')
|
||||
->join(['s2_wechat_friend' => 'wf'], 'wf.wechatAccountId = wa.id')
|
||||
->where([
|
||||
'ca.status' => 0,
|
||||
'wf.isDeleted' => 0,
|
||||
'wa.deviceAlive' => 1,
|
||||
'wa.wechatAlive' => 1
|
||||
])
|
||||
->whereIn('wa.currentDeviceId', $devices)
|
||||
->field('wf.id,wf.wechatAccountId,wf.wechatId,wf.ownerWechatId')
|
||||
->group('wf.id')
|
||||
->select();
|
||||
} else {
|
||||
// 查询指定的好友信息
|
||||
$friendsData = Db::table('s2_wechat_friend')
|
||||
->whereIn('id', $friends)
|
||||
->where('isDeleted', 0)
|
||||
->field('id,wechatAccountId,wechatId,ownerWechatId')
|
||||
->select();
|
||||
// 指定好友
|
||||
if (!empty($friends)) {
|
||||
$friendsData = array_merge($friendsData, $this->getFriendsByIds($friends, $ownerWechatIds));
|
||||
}
|
||||
|
||||
// 流量池好友
|
||||
if (!empty($trafficPools)) {
|
||||
$friendsData = array_merge($friendsData, $this->getFriendsByTrafficPools($trafficPools, $workbench, $ownerWechatIds));
|
||||
}
|
||||
|
||||
// 如果未选择好友或流量池,则根据设备查询所有好友
|
||||
if (empty($friendsData)) {
|
||||
if (empty($devices)) {
|
||||
Log::warning('好友推送:未选择好友或流量池,且未选择设备,无法推送');
|
||||
return false;
|
||||
}
|
||||
$friendsData = $this->getFriendsByDevices($devices, $ownerWechatIds);
|
||||
}
|
||||
$friendsData = $this->deduplicateFriends($friendsData);
|
||||
if (empty($friendsData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取所有已推送的好友ID列表(去重,不限制时间范围,用于过滤避免重复推送)
|
||||
// 获取已推送的好友ID列表(不限制时间范围,避免重复推送)
|
||||
$sentFriendIds = Db::name('workbench_group_push_item')
|
||||
->where('workbenchId', $workbench->id)
|
||||
->where('targetType', 2)
|
||||
->column('friendId');
|
||||
$sentFriendIds = array_filter($sentFriendIds); // 过滤null值
|
||||
$sentFriendIds = array_unique($sentFriendIds); // 去重
|
||||
$sentFriendIds = array_unique(array_filter($sentFriendIds));
|
||||
|
||||
// 获取今日已推送的好友ID列表(用于计算今日推送人数)
|
||||
$today = date('Y-m-d');
|
||||
$todayStartTimestamp = strtotime($today . ' 00:00:00');
|
||||
$todayEndTimestamp = strtotime($today . ' 23:59:59');
|
||||
$todaySentFriendIds = Db::name('workbench_group_push_item')
|
||||
->where('workbenchId', $workbench->id)
|
||||
->where('targetType', 2)
|
||||
->whereTime('createTime', 'between', [$todayStartTimestamp, $todayEndTimestamp])
|
||||
->column('friendId');
|
||||
$todaySentFriendIds = array_filter($todaySentFriendIds); // 过滤null值
|
||||
$todaySentFriendIds = array_unique($todaySentFriendIds); // 去重
|
||||
|
||||
// 过滤掉所有已推送的好友(不限制时间范围,避免重复推送)
|
||||
// 过滤掉所有已推送的好友
|
||||
$friendsData = array_filter($friendsData, function($friend) use ($sentFriendIds) {
|
||||
return !in_array($friend['id'], $sentFriendIds);
|
||||
});
|
||||
@@ -237,13 +256,13 @@ class WorkbenchGroupPushJob
|
||||
// 重新索引数组
|
||||
$friendsData = array_values($friendsData);
|
||||
|
||||
// 计算剩余可推送人数(基于今日推送人数)
|
||||
$todaySentCount = count($todaySentFriendIds);
|
||||
// 计算剩余可推送人数(基于累计推送人数)
|
||||
$sentFriendCount = count($sentFriendIds);
|
||||
$maxPerDay = intval($config['maxPerDay']);
|
||||
$remainingCount = $maxPerDay - $todaySentCount;
|
||||
$remainingCount = $maxPerDay - $sentFriendCount;
|
||||
|
||||
if ($remainingCount <= 0) {
|
||||
Log::info('好友推送:今日推送人数已达上限');
|
||||
Log::info('好友推送:累计推送人数已达上限');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -416,6 +435,349 @@ class WorkbenchGroupPushJob
|
||||
return $sendData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据好友ID获取好友信息
|
||||
* @param array $friendIds
|
||||
* @return array
|
||||
*/
|
||||
protected function getFriendsByIds(array $friendIds, array $ownerWechatIds = [])
|
||||
{
|
||||
if (empty($friendIds)) {
|
||||
return [];
|
||||
}
|
||||
$query = Db::table('s2_wechat_friend')
|
||||
->whereIn('id', $friendIds)
|
||||
->where('isDeleted', 0);
|
||||
|
||||
if (!empty($ownerWechatIds)) {
|
||||
$query->whereIn('wechatAccountId', $ownerWechatIds);
|
||||
}
|
||||
|
||||
$friends = $query
|
||||
->field('id,wechatAccountId,wechatId,ownerWechatId')
|
||||
->select();
|
||||
if ($friends === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $friends;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据设备获取好友信息
|
||||
* @param array $deviceIds
|
||||
* @return array
|
||||
*/
|
||||
protected function getFriendsByDevices(array $deviceIds, array $ownerWechatIds = [])
|
||||
{
|
||||
if (empty($deviceIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$query = Db::table('s2_company_account')
|
||||
->alias('ca')
|
||||
->join(['s2_wechat_account' => 'wa'], 'ca.id = wa.deviceAccountId')
|
||||
->join(['s2_wechat_friend' => 'wf'], 'wf.wechatAccountId = wa.id')
|
||||
->where([
|
||||
'ca.status' => 0,
|
||||
'wf.isDeleted' => 0,
|
||||
'wa.deviceAlive' => 1,
|
||||
'wa.wechatAlive' => 1
|
||||
])
|
||||
->whereIn('wa.currentDeviceId', $deviceIds);
|
||||
|
||||
if (!empty($ownerWechatIds)) {
|
||||
$query->whereIn('wf.wechatAccountId', $ownerWechatIds);
|
||||
}
|
||||
|
||||
$friends = $query
|
||||
->field('wf.id,wf.wechatAccountId,wf.wechatId,wf.ownerWechatId')
|
||||
->group('wf.id')
|
||||
->select();
|
||||
|
||||
if ($friends === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $friends->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据流量池获取好友信息
|
||||
* @param array $trafficPools
|
||||
* @param Workbench $workbench
|
||||
* @return array
|
||||
*/
|
||||
protected function getFriendsByTrafficPools(array $trafficPools, $workbench, array $ownerWechatIds = [])
|
||||
{
|
||||
if (empty($trafficPools)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$companyId = $workbench->companyId ?? 0;
|
||||
|
||||
$query = Db::name('traffic_source_package_item')
|
||||
->alias('tspi')
|
||||
->leftJoin('traffic_source_package tsp', 'tsp.id = tspi.packageId')
|
||||
->leftJoin('traffic_pool tp', 'tp.identifier = tspi.identifier')
|
||||
->leftJoin(['s2_wechat_friend' => 'wf'], 'wf.wechatId = tp.wechatId')
|
||||
->leftJoin(['s2_wechat_account' => 'wa'], 'wa.id = wf.wechatAccountId')
|
||||
->whereIn('tspi.packageId', $trafficPools)
|
||||
->where('tsp.isDel', 0)
|
||||
->where('wf.isDeleted', 0)
|
||||
->whereNotNull('wf.id')
|
||||
->whereNotNull('wf.wechatAccountId')
|
||||
->where(function ($query) use ($companyId) {
|
||||
$query->whereIn('tsp.companyId', [$companyId, 0]);
|
||||
})
|
||||
->where(function ($query) use ($companyId) {
|
||||
$query->whereIn('tspi.companyId', [$companyId, 0]);
|
||||
});
|
||||
|
||||
if (!empty($ownerWechatIds)) {
|
||||
$query->whereIn('wf.wechatAccountId', $ownerWechatIds);
|
||||
}
|
||||
|
||||
$friends = $query
|
||||
->field('wf.id,wf.wechatAccountId,wf.wechatId,wf.ownerWechatId')
|
||||
->group('wf.id')
|
||||
->select();
|
||||
|
||||
if (empty($friends)) {
|
||||
Log::info('好友推送:流量池未匹配到好友');
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($friends === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $friends;
|
||||
}
|
||||
|
||||
/**
|
||||
* 标准化群推送配置
|
||||
* @param array $config
|
||||
* @return array|false
|
||||
*/
|
||||
protected function normalizeConfig(array $config)
|
||||
{
|
||||
$config['targetType'] = intval($config['targetType'] ?? 1);
|
||||
$config['groupPushSubType'] = intval($config['groupPushSubType'] ?? 1);
|
||||
if (!in_array($config['groupPushSubType'], [1, 2], true)) {
|
||||
$config['groupPushSubType'] = 1;
|
||||
}
|
||||
|
||||
$config['pushType'] = !empty($config['pushType']) ? 1 : 0;
|
||||
$config['status'] = !empty($config['status']) ? 1 : 0;
|
||||
$config['isLoop'] = !empty($config['isLoop']) ? 1 : 0;
|
||||
|
||||
$config['startTime'] = $this->normalizeTimeString($config['startTime'] ?? '00:00');
|
||||
$config['endTime'] = $this->normalizeTimeString($config['endTime'] ?? '23:59');
|
||||
$config['maxPerDay'] = max(0, intval($config['maxPerDay'] ?? 0));
|
||||
|
||||
$config['friendIntervalMin'] = max(0, intval($config['friendIntervalMin'] ?? 0));
|
||||
$config['friendIntervalMax'] = max(0, intval($config['friendIntervalMax'] ?? $config['friendIntervalMin']));
|
||||
if ($config['friendIntervalMin'] > $config['friendIntervalMax']) {
|
||||
$config['friendIntervalMax'] = $config['friendIntervalMin'];
|
||||
}
|
||||
|
||||
$config['messageIntervalMin'] = max(0, intval($config['messageIntervalMin'] ?? 0));
|
||||
$config['messageIntervalMax'] = max(0, intval($config['messageIntervalMax'] ?? $config['messageIntervalMin']));
|
||||
if ($config['messageIntervalMin'] > $config['messageIntervalMax']) {
|
||||
$config['messageIntervalMax'] = $config['messageIntervalMin'];
|
||||
}
|
||||
|
||||
$config['ownerWechatIds'] = $this->deduplicateIds($this->jsonToArray($config['ownerWechatIds'] ?? []));
|
||||
$config['groups'] = $this->deduplicateIds($this->jsonToArray($config['groups'] ?? []));
|
||||
$config['friends'] = $this->deduplicateIds($this->jsonToArray($config['friends'] ?? []));
|
||||
$config['trafficPools'] = $this->deduplicateIds($this->jsonToArray($config['trafficPools'] ?? []));
|
||||
$config['devices'] = $this->deduplicateIds($this->jsonToArray($config['devices'] ?? []));
|
||||
$config['contentLibraries'] = $this->deduplicateIds($this->jsonToArray($config['contentLibraries'] ?? []));
|
||||
$config['postPushTags'] = $this->deduplicateIds($this->jsonToArray($config['postPushTags'] ?? []));
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将混合类型转换为数组
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
protected function jsonToArray($value): array
|
||||
{
|
||||
if (empty($value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
$decoded = json_decode($value, true);
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
return is_array($decoded) ? $decoded : [];
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 归一化时间字符串,保留到分钟
|
||||
* @param string $time
|
||||
* @return string
|
||||
*/
|
||||
protected function normalizeTimeString(string $time): string
|
||||
{
|
||||
if (empty($time)) {
|
||||
return '00:00';
|
||||
}
|
||||
$parts = explode(':', $time);
|
||||
$hour = str_pad(intval($parts[0] ?? 0), 2, '0', STR_PAD_LEFT);
|
||||
$minute = str_pad(intval($parts[1] ?? 0), 2, '0', STR_PAD_LEFT);
|
||||
return "{$hour}:{$minute}";
|
||||
}
|
||||
|
||||
/**
|
||||
* 对ID数组进行去重并清理无效值
|
||||
* @param array $ids
|
||||
* @return array
|
||||
*/
|
||||
protected function deduplicateIds(array $ids)
|
||||
{
|
||||
if (empty($ids)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$normalized = array_map(function ($value) {
|
||||
if (is_array($value) && isset($value['id'])) {
|
||||
return $value['id'];
|
||||
}
|
||||
if (is_object($value) && isset($value->id)) {
|
||||
return $value->id;
|
||||
}
|
||||
return $value;
|
||||
}, $ids);
|
||||
|
||||
$filtered = array_filter($normalized, function ($value) {
|
||||
return $value !== null && $value !== '';
|
||||
});
|
||||
|
||||
if (empty($filtered)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_values(array_unique($filtered));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对内容列表根据内容ID去重
|
||||
* @param mixed $contents
|
||||
* @return array
|
||||
*/
|
||||
protected function deduplicateContentList($contents)
|
||||
{
|
||||
if (empty($contents)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($contents instanceof \think\Collection || $contents instanceof \think\model\Collection) {
|
||||
$contents = $contents->toArray();
|
||||
} elseif ($contents instanceof \think\Model) {
|
||||
$contents = [$contents->toArray()];
|
||||
}
|
||||
|
||||
if (!is_array($contents)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$result = [];
|
||||
$unique = [];
|
||||
|
||||
foreach ($contents as $content) {
|
||||
if ($content instanceof \think\Model) {
|
||||
$content = $content->toArray();
|
||||
} elseif (is_object($content)) {
|
||||
$content = (array)$content;
|
||||
}
|
||||
|
||||
if (!is_array($content)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$contentId = $content['id'] ?? null;
|
||||
if (empty($contentId) || isset($unique[$contentId])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$unique[$contentId] = true;
|
||||
$result[] = $content;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对好友数据进行去重
|
||||
* @param array $friends
|
||||
* @return array
|
||||
*/
|
||||
protected function deduplicateFriends(array $friends)
|
||||
{
|
||||
if (empty($friends)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$unique = [];
|
||||
$result = [];
|
||||
|
||||
foreach ($friends as $friend) {
|
||||
if (empty($friend['id'])) {
|
||||
continue;
|
||||
}
|
||||
if (isset($unique[$friend['id']])) {
|
||||
continue;
|
||||
}
|
||||
$unique[$friend['id']] = true;
|
||||
$result[] = $friend;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置中的客服微信ID列表
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function getOwnerWechatIds($config)
|
||||
{
|
||||
if (empty($config['ownerWechatIds'])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$ownerWechatIds = $config['ownerWechatIds'];
|
||||
|
||||
if (is_string($ownerWechatIds)) {
|
||||
$decoded = json_decode($ownerWechatIds, true);
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
$ownerWechatIds = $decoded;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_array($ownerWechatIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$ownerWechatIds = array_map(function ($id) {
|
||||
return is_numeric($id) ? intval($id) : $id;
|
||||
}, $ownerWechatIds);
|
||||
|
||||
return $this->deduplicateIds($ownerWechatIds);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 记录发送历史
|
||||
@@ -441,10 +803,10 @@ class WorkbenchGroupPushJob
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备列表
|
||||
* 判断是否推送
|
||||
* @param Workbench $workbench 工作台
|
||||
* @param WorkbenchGroupPush $config 配置
|
||||
* @return array|bool
|
||||
* @param array $config 配置
|
||||
* @return bool
|
||||
*/
|
||||
protected function isPush($workbench, $config)
|
||||
{
|
||||
@@ -463,27 +825,34 @@ class WorkbenchGroupPushJob
|
||||
return false;
|
||||
}
|
||||
|
||||
$targetType = isset($config['targetType']) ? intval($config['targetType']) : 1; // 默认1=群推送
|
||||
$targetType = intval($config['targetType']); // 默认1=群推送
|
||||
|
||||
if ($targetType == 2) {
|
||||
// 好友推送:maxPerDay表示每日推送人数
|
||||
// 查询今日已推送的好友ID列表(去重,仅统计今日)
|
||||
// 查询已推送的好友ID列表(去重)
|
||||
$sentFriendIds = Db::name('workbench_group_push_item')
|
||||
->where('workbenchId', $workbench->id)
|
||||
->where('targetType', 2)
|
||||
->whereTime('createTime', 'between', [$startTimestamp, $endTimestamp])
|
||||
->column('friendId');
|
||||
$sentFriendIds = array_filter($sentFriendIds); // 过滤null值
|
||||
$count = count(array_unique($sentFriendIds)); // 去重后统计今日推送人数
|
||||
$count = count(array_unique($sentFriendIds)); // 去重后统计累计推送人数
|
||||
|
||||
if ($count >= $config['maxPerDay']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 计算本次同步的最早允许时间(按人数计算间隔)
|
||||
$interval = floor($totalSeconds / $config['maxPerDay']);
|
||||
$nextSyncTime = $startTimestamp + $count * $interval;
|
||||
if (time() < $nextSyncTime) {
|
||||
// 计算本次同步的最早允许时间(基于好友/消息间隔配置)
|
||||
$friendIntervalMin = max(0, intval($config['friendIntervalMin'] ?? 0));
|
||||
$messageIntervalMin = max(0, intval($config['messageIntervalMin'] ?? 0));
|
||||
$minInterval = max(1, $friendIntervalMin + $messageIntervalMin);
|
||||
|
||||
$lastSendTime = Db::name('workbench_group_push_item')
|
||||
->where('workbenchId', $workbench->id)
|
||||
->where('targetType', 2)
|
||||
->order('id', 'desc')
|
||||
->value('createTime');
|
||||
|
||||
if (!empty($lastSendTime) && (time() - $lastSendTime) < $minInterval) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -513,17 +882,24 @@ class WorkbenchGroupPushJob
|
||||
/**
|
||||
* 获取内容库
|
||||
* @param Workbench $workbench 工作台
|
||||
* @param WorkbenchGroupPush $config 配置
|
||||
* @param array $config 配置
|
||||
* @return array|bool
|
||||
*/
|
||||
protected function getContentLibrary($workbench, $config)
|
||||
{
|
||||
$contentids = json_decode($config['contentLibraries'], true);
|
||||
if (empty($contentids)) {
|
||||
$targetType = intval($config['targetType']); // 默认1=群推送
|
||||
$groupPushSubType = intval($config['groupPushSubType']); // 默认1=群群发
|
||||
|
||||
// 如果是群公告,不需要内容库(晚点处理)
|
||||
if ($targetType == 1 && $groupPushSubType == 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$targetType = isset($config['targetType']) ? intval($config['targetType']) : 1; // 默认1=群推送
|
||||
$contentids = $config['contentLibraries'] ?? [];
|
||||
if (empty($contentids)) {
|
||||
Log::warning("未选择内容库,工作台ID: {$workbench->id}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($config['pushType'] == 1) {
|
||||
$limit = 10;
|
||||
@@ -563,10 +939,12 @@ class WorkbenchGroupPushJob
|
||||
if ($config['isLoop'] == 1) {
|
||||
// 可以循环发送(只有群推送时才能为1)
|
||||
// 1. 优先获取未发送的内容
|
||||
$unsentContent = $query->where('wgpi.id', 'null')
|
||||
->order($order)
|
||||
->limit(0, $limit)
|
||||
->select();
|
||||
$unsentContent = $this->deduplicateContentList(
|
||||
$query->where('wgpi.id', 'null')
|
||||
->order($order)
|
||||
->limit(0, $limit)
|
||||
->select()
|
||||
);
|
||||
if (!empty($unsentContent)) {
|
||||
return $unsentContent;
|
||||
}
|
||||
@@ -585,18 +963,32 @@ class WorkbenchGroupPushJob
|
||||
return [];
|
||||
}
|
||||
|
||||
$sentContent = $query2->where('wgpi.contentId', '<', $lastSendData['contentId'])->order('wgpi.id ASC')->group('wgpi.contentId')->limit(0, $limit)->select();
|
||||
$sentContent = $this->deduplicateContentList(
|
||||
$query2->where('wgpi.contentId', '<', $lastSendData['contentId'])
|
||||
->order('wgpi.id ASC')
|
||||
->group('wgpi.contentId')
|
||||
->limit(0, $limit)
|
||||
->select()
|
||||
);
|
||||
|
||||
if (empty($sentContent)) {
|
||||
$sentContent = $query3->where('wgpi.contentId', '=', $fastSendData['contentId'])->order('wgpi.id ASC')->group('wgpi.contentId')->limit(0, $limit)->select();
|
||||
$sentContent = $this->deduplicateContentList(
|
||||
$query3->where('wgpi.contentId', '=', $fastSendData['contentId'])
|
||||
->order('wgpi.id ASC')
|
||||
->group('wgpi.contentId')
|
||||
->limit(0, $limit)
|
||||
->select()
|
||||
);
|
||||
}
|
||||
return $sentContent;
|
||||
} else {
|
||||
// 不能循环发送,只获取未发送的内容(好友推送时isLoop=0)
|
||||
$list = $query->where('wgpi.id', 'null')
|
||||
->order($order)
|
||||
->limit(0, $limit)
|
||||
->select();
|
||||
$list = $this->deduplicateContentList(
|
||||
$query->where('wgpi.id', 'null')
|
||||
->order($order)
|
||||
->limit(0, $limit)
|
||||
->select()
|
||||
);
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user