Files
cunkebao_v3/Server/application/cunkebao/controller/WorkbenchController.php

3122 lines
131 KiB
PHP
Raw Normal View History

2025-04-10 16:40:30 +08:00
<?php
namespace app\cunkebao\controller;
2025-07-06 00:17:24 +08:00
use app\common\model\Device as DeviceModel;
use app\common\model\DeviceWechatLogin as DeviceWechatLoginModel;
use app\common\model\WechatCustomer as WechatCustomerModel;
2025-04-10 16:40:30 +08:00
use app\cunkebao\model\Workbench;
use app\cunkebao\model\WorkbenchAutoLike;
2025-09-10 11:43:47 +08:00
use app\cunkebao\model\WorkbenchImportContact;
2025-04-10 16:40:30 +08:00
use app\cunkebao\model\WorkbenchMomentsSync;
use app\cunkebao\model\WorkbenchGroupPush;
use app\cunkebao\model\WorkbenchGroupCreate;
use app\cunkebao\validate\Workbench as WorkbenchValidate;
use think\Controller;
use think\Db;
use app\cunkebao\model\WorkbenchTrafficConfig;
use app\cunkebao\model\ContentLibrary;
2025-09-02 11:24:23 +08:00
use think\facade\Env;
2025-04-10 16:40:30 +08:00
/**
* 工作台控制器
*/
class WorkbenchController extends Controller
{
/**
* 工作台类型定义
*/
const TYPE_AUTO_LIKE = 1; // 自动点赞
const TYPE_MOMENTS_SYNC = 2; // 朋友圈同步
const TYPE_GROUP_PUSH = 3; // 群消息推送
const TYPE_GROUP_CREATE = 4; // 自动建群
const TYPE_TRAFFIC_DISTRIBUTION = 5; // 流量分发
2025-09-10 11:43:47 +08:00
const TYPE_IMPORT_CONTACT = 6; // 联系人导入
2025-04-10 16:40:30 +08:00
/**
* 创建工作台
* @return \think\response\Json
*/
public function create()
{
if (!$this->request->isPost()) {
return json(['code' => 400, 'msg' => '请求方式错误']);
}
// 获取登录用户信息
$userInfo = request()->userInfo;
// 获取请求参数
$param = $this->request->post();
2025-11-13 16:10:47 +08:00
// 根据业务默认值补全参数
if (
isset($param['type']) &&
intval($param['type']) === self::TYPE_GROUP_PUSH
) {
if (empty($param['startTime'])) {
$param['startTime'] = '09:00';
}
if (empty($param['endTime'])) {
$param['endTime'] = '21:00';
}
}
2025-04-10 16:40:30 +08:00
// 验证数据
$validate = new WorkbenchValidate;
if (!$validate->scene('create')->check($param)) {
return json(['code' => 400, 'msg' => $validate->getError()]);
}
Db::startTrans();
try {
// 创建工作台基本信息
$workbench = new Workbench;
$workbench->name = $param['name'];
$workbench->type = $param['type'];
2025-08-22 10:23:05 +08:00
$workbench->status = !empty($param['status']) ? 1 : 0;
2025-04-10 16:40:30 +08:00
$workbench->autoStart = !empty($param['autoStart']) ? 1 : 0;
$workbench->userId = $userInfo['id'];
$workbench->companyId = $userInfo['companyId'];
$workbench->createTime = time();
$workbench->updateTime = time();
$workbench->save();
// 根据类型创建对应的配置
switch ($param['type']) {
case self::TYPE_AUTO_LIKE: // 自动点赞
$config = new WorkbenchAutoLike;
$config->workbenchId = $workbench->id;
$config->interval = $param['interval'];
$config->maxLikes = $param['maxLikes'];
$config->startTime = $param['startTime'];
$config->endTime = $param['endTime'];
$config->contentTypes = json_encode($param['contentTypes']);
2025-09-11 15:16:04 +08:00
$config->devices = json_encode($param['deviceGroups']);
2025-12-04 11:10:55 +08:00
$config->friends = json_encode($param['wechatFriends']);
2025-05-09 09:22:31 +08:00
// $config->targetGroups = json_encode($param['targetGroups']);
// $config->tagOperator = $param['tagOperator'];
2025-05-16 09:43:04 +08:00
$config->friendMaxLikes = $param['friendMaxLikes'];
$config->friendTags = $param['friendTags'];
$config->enableFriendTags = $param['enableFriendTags'];
2025-04-10 16:40:30 +08:00
$config->createTime = time();
$config->updateTime = time();
$config->save();
break;
case self::TYPE_MOMENTS_SYNC: // 朋友圈同步
$config = new WorkbenchMomentsSync;
$config->workbenchId = $workbench->id;
$config->syncInterval = $param['syncInterval'];
$config->syncCount = $param['syncCount'];
$config->syncType = $param['syncType'];
2025-04-11 16:15:48 +08:00
$config->startTime = $param['startTime'];
$config->endTime = $param['endTime'];
$config->accountType = $param['accountType'];
2025-09-11 15:16:04 +08:00
$config->devices = json_encode($param['deviceGroups']);
2025-08-12 09:28:57 +08:00
$config->contentLibraries = json_encode($param['contentGroups'] ?? []);
2025-04-10 16:40:30 +08:00
$config->createTime = time();
$config->updateTime = time();
$config->save();
break;
case self::TYPE_GROUP_PUSH: // 群消息推送
2025-11-13 16:10:47 +08:00
$ownerWechatIds = $this->normalizeOwnerWechatIds($param['ownerWechatIds'] ?? []);
$groupPushData = $this->prepareGroupPushData($param, $ownerWechatIds);
$groupPushData['workbenchId'] = $workbench->id;
$groupPushData['createTime'] = time();
$groupPushData['updateTime'] = time();
2025-04-10 16:40:30 +08:00
$config = new WorkbenchGroupPush;
2025-11-13 16:10:47 +08:00
$config->save($groupPushData);
2025-04-10 16:40:30 +08:00
break;
case self::TYPE_GROUP_CREATE: // 自动建群
$config = new WorkbenchGroupCreate;
$config->workbenchId = $workbench->id;
2025-09-11 15:16:04 +08:00
$config->devices = json_encode($param['deviceGroups'], JSON_UNESCAPED_UNICODE);
$config->startTime = $param['startTime'];
$config->endTime = $param['endTime'];
$config->groupSizeMin = $param['groupSizeMin'];
$config->groupSizeMax = $param['groupSizeMax'];
$config->maxGroupsPerDay = $param['maxGroupsPerDay'];
$config->groupNameTemplate = $param['groupNameTemplate'];
$config->groupDescription = $param['groupDescription'];
2025-08-22 10:23:05 +08:00
$config->poolGroups = json_encode($param['poolGroups'] ?? []);
$config->wechatGroups = json_encode($param['wechatGroups'] ?? []);
2025-04-10 16:40:30 +08:00
$config->createTime = time();
$config->updateTime = time();
$config->save();
break;
case self::TYPE_TRAFFIC_DISTRIBUTION: // 流量分发
$config = new WorkbenchTrafficConfig;
$config->workbenchId = $workbench->id;
$config->distributeType = $param['distributeType'];
$config->maxPerDay = $param['maxPerDay'];
$config->timeType = $param['timeType'];
$config->startTime = $param['startTime'];
$config->endTime = $param['endTime'];
2025-09-11 15:16:04 +08:00
$config->devices = json_encode($param['deviceGroups'], JSON_UNESCAPED_UNICODE);
2025-09-22 18:03:45 +08:00
$config->pools = json_encode($param['poolGroups'], JSON_UNESCAPED_UNICODE);
2025-08-12 09:28:57 +08:00
$config->account = json_encode($param['accountGroups'], JSON_UNESCAPED_UNICODE);
$config->createTime = time();
$config->updateTime = time();
$config->save();
break;
2025-09-10 11:43:47 +08:00
case self::TYPE_IMPORT_CONTACT: //联系人导入
$config = new WorkbenchImportContact;
$config->workbenchId = $workbench->id;
2025-09-11 15:16:04 +08:00
$config->devices = json_encode($param['deviceGroups'], JSON_UNESCAPED_UNICODE);
2025-09-22 18:03:45 +08:00
$config->pools = json_encode($param['poolGroups'], JSON_UNESCAPED_UNICODE);
2025-09-10 11:43:47 +08:00
$config->num = $param['num'];
$config->clearContact = $param['clearContact'];
$config->remark = $param['remark'];
$config->startTime = $param['startTime'];
$config->endTime = $param['endTime'];
$config->createTime = time();
$config->save();
break;
2025-04-10 16:40:30 +08:00
}
Db::commit();
return json(['code' => 200, 'msg' => '创建成功', 'data' => ['id' => $workbench->id]]);
} catch (\Exception $e) {
Db::rollback();
return json(['code' => 500, 'msg' => '创建失败:' . $e->getMessage()]);
}
}
/**
* 获取工作台列表
* @return \think\response\Json
*/
public function getList()
{
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$type = $this->request->param('type', '');
$keyword = $this->request->param('keyword', '');
2025-04-10 16:40:30 +08:00
$where = [
2025-11-17 17:34:46 +08:00
['companyId', '=', $this->request->userInfo['companyId']],
2025-04-10 16:40:30 +08:00
['isDel', '=', 0]
];
2025-08-12 09:28:57 +08:00
2025-11-17 17:34:46 +08:00
if (empty($this->request->userInfo['isAdmin'])) {
$where[] = ['userId', '=', $this->request->userInfo['id']];
}
2025-04-10 16:40:30 +08:00
// 添加类型筛选
if ($type !== '') {
$where[] = ['type', '=', $type];
}
2025-08-12 09:28:57 +08:00
2025-04-10 16:40:30 +08:00
// 添加名称模糊搜索
if ($keyword !== '') {
$where[] = ['name', 'like', '%' . $keyword . '%'];
}
// 定义关联关系
$with = [
2025-08-12 09:28:57 +08:00
'autoLike' => function ($query) {
2025-05-09 09:22:31 +08:00
$query->field('workbenchId,interval,maxLikes,startTime,endTime,contentTypes,devices,friends');
2025-04-10 16:40:30 +08:00
},
2025-08-12 09:28:57 +08:00
'momentsSync' => function ($query) {
2025-04-11 16:15:48 +08:00
$query->field('workbenchId,syncInterval,syncCount,syncType,startTime,endTime,accountType,devices,contentLibraries');
},
2025-08-12 09:28:57 +08:00
'trafficConfig' => function ($query) {
$query->field('workbenchId,distributeType,maxPerDay,timeType,startTime,endTime,devices,pools,account');
},
2025-08-12 09:28:57 +08:00
'groupPush' => function ($query) {
2025-11-13 16:10:47 +08:00
$query->field('workbenchId,pushType,targetType,groupPushSubType,startTime,endTime,maxPerDay,pushOrder,isLoop,status,groups,friends,ownerWechatIds,trafficPools,contentLibraries,friendIntervalMin,friendIntervalMax,messageIntervalMin,messageIntervalMax,isRandomTemplate,postPushTags,announcementContent,enableAiRewrite,aiRewritePrompt');
},
2025-11-13 16:10:47 +08:00
'groupCreate' => function ($query) {
2025-08-22 10:23:05 +08:00
$query->field('workbenchId,devices,startTime,endTime,groupSizeMin,groupSizeMax,maxGroupsPerDay,groupNameTemplate,groupDescription,poolGroups,wechatGroups');
},
2025-11-13 16:10:47 +08:00
'importContact' => function ($query) {
2025-09-10 11:43:47 +08:00
$query->field('workbenchId,devices,pools,num,remarkType,remark,clearContact,startTime,endTime');
},
2025-08-12 09:28:57 +08:00
'user' => function ($query) {
$query->field('id,username');
}
2025-04-10 16:40:30 +08:00
];
$list = Workbench::where($where)
->with($with)
->field('id,companyId,name,type,status,autoStart,userId,createTime,updateTime')
2025-04-10 16:40:30 +08:00
->order('id', 'desc')
->page($page, $limit)
->select()
->each(function ($item) {
// 处理配置信息
switch ($item->type) {
case self::TYPE_AUTO_LIKE:
if (!empty($item->autoLike)) {
$item->config = $item->autoLike;
$item->config->devices = json_decode($item->config->devices, true);
2025-08-12 09:28:57 +08:00
$item->config->contentTypes = json_decode($item->config->contentTypes, true);
2025-05-09 09:22:31 +08:00
$item->config->friends = json_decode($item->config->friends, true);
2025-08-12 09:28:57 +08:00
// 添加今日点赞数
$startTime = strtotime(date('Y-m-d') . ' 00:00:00');
$endTime = strtotime(date('Y-m-d') . ' 23:59:59');
$todayLikeCount = Db::name('workbench_auto_like_item')
->where('workbenchId', $item->id)
->whereTime('createTime', 'between', [$startTime, $endTime])
->count();
2025-08-12 09:28:57 +08:00
// 添加总点赞数
$totalLikeCount = Db::name('workbench_auto_like_item')
->where('workbenchId', $item->id)
->count();
2025-08-12 09:28:57 +08:00
$item->config->todayLikeCount = $todayLikeCount;
$item->config->totalLikeCount = $totalLikeCount;
2025-04-10 16:40:30 +08:00
}
2025-08-12 09:28:57 +08:00
unset($item->autoLike, $item->auto_like);
2025-04-10 16:40:30 +08:00
break;
case self::TYPE_MOMENTS_SYNC:
if (!empty($item->momentsSync)) {
$item->config = $item->momentsSync;
$item->config->devices = json_decode($item->config->devices, true);
2025-08-29 09:51:00 +08:00
$item->config->contentGroups = json_decode($item->config->contentLibraries, true);
2025-07-06 00:17:24 +08:00
//同步记录
$sendNum = Db::name('workbench_moments_sync_item')->where(['workbenchId' => $item->id])->count();
$item->syncCount = $sendNum;
$lastTime = Db::name('workbench_moments_sync_item')->where(['workbenchId' => $item->id])->order('id DESC')->value('createTime');
2025-08-12 09:28:57 +08:00
$item->lastSyncTime = !empty($lastTime) ? date('Y-m-d H:i', $lastTime) : '--';
2025-07-06 00:17:24 +08:00
2025-07-11 11:09:48 +08:00
// 获取内容库名称
2025-08-29 09:51:00 +08:00
if (!empty($item->config->contentGroups)) {
$libraryNames = ContentLibrary::where('id', 'in', $item->config->contentGroups)->select();
$item->config->contentGroupsOptions = $libraryNames;
} else {
2025-08-29 09:51:00 +08:00
$item->config->contentGroupsOptions = [];
}
2025-04-10 16:40:30 +08:00
}
2025-11-13 16:10:47 +08:00
unset($item->momentsSync, $item->moments_sync, $item->config->contentLibraries);
2025-04-10 16:40:30 +08:00
break;
case self::TYPE_GROUP_PUSH:
if (!empty($item->groupPush)) {
$item->config = $item->groupPush;
$item->config->pushType = $item->config->pushType;
2025-11-07 15:25:50 +08:00
$item->config->targetType = isset($item->config->targetType) ? intval($item->config->targetType) : 1; // 默认1=群推送
2025-11-13 16:10:47 +08:00
$item->config->groupPushSubType = isset($item->config->groupPushSubType) ? intval($item->config->groupPushSubType) : 1; // 默认1=群群发
$item->config->startTime = $item->config->startTime;
$item->config->endTime = $item->config->endTime;
$item->config->maxPerDay = $item->config->maxPerDay;
$item->config->pushOrder = $item->config->pushOrder;
$item->config->isLoop = $item->config->isLoop;
$item->config->status = $item->config->status;
2025-11-13 16:10:47 +08:00
$item->config->ownerWechatIds = json_decode($item->config->ownerWechatIds ?? '[]', true) ?: [];
2025-11-07 15:25:50 +08:00
// 根据targetType解析不同的数据
if ($item->config->targetType == 1) {
// 群推送
$item->config->wechatGroups = json_decode($item->config->groups, true) ?: [];
$item->config->wechatFriends = [];
2025-11-13 16:10:47 +08:00
// 群推送不需要devices字段
// 群公告相关字段
if ($item->config->groupPushSubType == 2) {
$item->config->announcementContent = isset($item->config->announcementContent) ? $item->config->announcementContent : '';
$item->config->enableAiRewrite = isset($item->config->enableAiRewrite) ? intval($item->config->enableAiRewrite) : 0;
$item->config->aiRewritePrompt = isset($item->config->aiRewritePrompt) ? $item->config->aiRewritePrompt : '';
}
$item->config->trafficPools = [];
2025-11-07 15:25:50 +08:00
} else {
// 好友推送
$item->config->wechatFriends = json_decode($item->config->friends, true) ?: [];
$item->config->wechatGroups = [];
2025-11-13 16:10:47 +08:00
$item->config->trafficPools = json_decode($item->config->trafficPools ?? '[]', true) ?: [];
2025-11-07 15:25:50 +08:00
}
$item->config->contentLibraries = json_decode($item->config->contentLibraries, true);
2025-11-13 16:10:47 +08:00
$item->config->postPushTags = json_decode($item->config->postPushTags ?? '[]', true) ?: [];
2025-08-22 10:23:05 +08:00
$item->config->lastPushTime = '';
2025-11-13 16:10:47 +08:00
if (!empty($item->config->ownerWechatIds)) {
$ownerWechatOptions = Db::name('wechat_account')
->whereIn('id', $item->config->ownerWechatIds)
->field('id,wechatId,nickName,avatar,alias')
->select();
$item->config->ownerWechatOptions = $ownerWechatOptions;
} else {
$item->config->ownerWechatOptions = [];
}
2025-04-10 16:40:30 +08:00
}
2025-08-12 09:28:57 +08:00
unset($item->groupPush, $item->group_push);
2025-04-10 16:40:30 +08:00
break;
case self::TYPE_GROUP_CREATE:
if (!empty($item->groupCreate)) {
$item->config = $item->groupCreate;
$item->config->devices = json_decode($item->config->devices, true);
2025-08-22 10:23:05 +08:00
$item->config->poolGroups = json_decode($item->config->poolGroups, true);
$item->config->wechatGroups = json_decode($item->config->wechatGroups, true);
2025-04-10 16:40:30 +08:00
}
2025-08-12 09:28:57 +08:00
unset($item->groupCreate, $item->group_create);
2025-04-10 16:40:30 +08:00
break;
case self::TYPE_TRAFFIC_DISTRIBUTION:
if (!empty($item->trafficConfig)) {
$item->config = $item->trafficConfig;
$item->config->devices = json_decode($item->config->devices, true);
2025-09-22 18:03:45 +08:00
$item->config->poolGroups = json_decode($item->config->pools, true);
$item->config->account = json_decode($item->config->account, true);
$config_item = Db::name('workbench_traffic_config_item')->where(['workbenchId' => $item->id])->order('id DESC')->find();
2025-08-12 09:28:57 +08:00
$item->config->lastUpdated = !empty($config_item) ? date('Y-m-d H:i', $config_item['createTime']) : '--';
//统计
2025-09-22 18:03:45 +08:00
$labels = $item->config->poolGroups;
$totalUsers = Db::table('s2_wechat_friend')->alias('wf')
->join(['s2_company_account' => 'sa'], 'sa.id = wf.accountId', 'left')
->join(['s2_wechat_account' => 'wa'], 'wa.id = wf.wechatAccountId', 'left')
->where([
['wf.isDeleted', '=', 0],
['sa.departmentId', '=', $item->companyId]
])
2025-06-11 15:31:46 +08:00
->whereIn('wa.currentDeviceId', $item->config->devices);
2025-08-12 09:28:57 +08:00
if (!empty($labels) && count($labels) > 0) {
2025-06-11 15:31:46 +08:00
$totalUsers = $totalUsers->where(function ($q) use ($labels) {
foreach ($labels as $label) {
$q->whereOrRaw("JSON_CONTAINS(wf.labels, '\"{$label}\"')");
}
});
}
$totalUsers = $totalUsers->count();
$totalAccounts = count($item->config->account);
$dailyAverage = Db::name('workbench_traffic_config_item')
2025-08-12 09:28:57 +08:00
->where('workbenchId', $item->id)
->count();
$day = (time() - strtotime($item->createTime)) / 86400;
$day = intval($day);
2025-08-12 09:28:57 +08:00
if ($dailyAverage > 0 && $totalAccounts > 0 && $day > 0) {
$dailyAverage = $dailyAverage / $totalAccounts / $day;
}
$item->config->total = [
'dailyAverage' => intval($dailyAverage),
'totalAccounts' => $totalAccounts,
'deviceCount' => count($item->config->devices),
2025-09-22 18:03:45 +08:00
'poolCount' => !empty($item->config->poolGroups) ? count($item->config->poolGroups) : 'ALL',
'totalUsers' => $totalUsers >> 0
];
}
2025-08-12 09:28:57 +08:00
unset($item->trafficConfig, $item->traffic_config);
break;
2025-09-10 11:43:47 +08:00
case self::TYPE_IMPORT_CONTACT:
if (!empty($item->importContact)) {
$item->config = $item->importContact;
$item->config->devices = json_decode($item->config->devices, true);
2025-09-22 18:03:45 +08:00
$item->config->poolGroups = json_decode($item->config->pools, true);
2025-09-10 11:43:47 +08:00
}
unset($item->importContact, $item->import_contact);
break;
2025-04-10 16:40:30 +08:00
}
// 添加创建人名称
$item['creatorName'] = $item->user ? $item->user->username : '';
unset($item['user']); // 移除关联数据
2025-04-10 16:40:30 +08:00
return $item;
});
$total = Workbench::where($where)->count();
return json([
'code' => 200,
'msg' => '获取成功',
'data' => [
'list' => $list,
'total' => $total,
'page' => $page,
'limit' => $limit
]
]);
}
/**
* 获取工作台详情
* @param int $id 工作台ID
* @return \think\response\Json
*/
2025-04-11 16:15:48 +08:00
public function detail()
2025-04-10 16:40:30 +08:00
{
2025-04-11 16:15:48 +08:00
$id = $this->request->param('id', '');
2025-04-10 16:40:30 +08:00
if (empty($id)) {
return json(['code' => 400, 'msg' => '参数错误']);
}
// 定义关联关系
$with = [
2025-08-12 09:28:57 +08:00
'autoLike' => function ($query) {
2025-05-16 09:43:04 +08:00
$query->field('workbenchId,interval,maxLikes,startTime,endTime,contentTypes,devices,friends,friendMaxLikes,friendTags,enableFriendTags');
2025-04-10 16:40:30 +08:00
},
2025-08-12 09:28:57 +08:00
'momentsSync' => function ($query) {
2025-04-11 16:15:48 +08:00
$query->field('workbenchId,syncInterval,syncCount,syncType,startTime,endTime,accountType,devices,contentLibraries');
2025-04-10 16:40:30 +08:00
},
2025-08-12 09:28:57 +08:00
'trafficConfig' => function ($query) {
$query->field('workbenchId,distributeType,maxPerDay,timeType,startTime,endTime,devices,pools,account');
},
2025-08-12 09:28:57 +08:00
'groupPush' => function ($query) {
2025-11-13 16:10:47 +08:00
$query->field('workbenchId,pushType,targetType,groupPushSubType,startTime,endTime,maxPerDay,pushOrder,isLoop,status,groups,friends,ownerWechatIds,trafficPools,contentLibraries,friendIntervalMin,friendIntervalMax,messageIntervalMin,messageIntervalMax,isRandomTemplate,postPushTags,announcementContent,enableAiRewrite,aiRewritePrompt');
},
'groupCreate' => function ($query) {
$query->field('workbenchId,devices,startTime,endTime,groupSizeMin,groupSizeMax,maxGroupsPerDay,groupNameTemplate,groupDescription,poolGroups,wechatGroups');
},
2025-11-13 16:10:47 +08:00
'importContact' => function ($query) {
2025-09-10 11:43:47 +08:00
$query->field('workbenchId,devices,pools,num,remarkType,remark,clearContact,startTime,endTime');
},
2025-04-10 16:40:30 +08:00
];
2025-11-17 17:34:46 +08:00
$where = [
2025-04-10 16:40:30 +08:00
['id', '=', $id],
2025-11-17 17:34:46 +08:00
['companyId', '=', $this->request->userInfo['companyId']],
2025-04-10 16:40:30 +08:00
['isDel', '=', 0]
2025-11-17 17:34:46 +08:00
];
if (empty($this->request->userInfo['isAdmin'])) {
$where[] = ['userId', '=', $this->request->userInfo['id']];
}
$workbench = Workbench::where($where)
2025-08-12 09:28:57 +08:00
->field('id,name,type,status,autoStart,createTime,updateTime,companyId')
->with($with)
->find();
2025-04-10 16:40:30 +08:00
if (empty($workbench)) {
return json(['code' => 404, 'msg' => '工作台不存在']);
}
// 处理配置信息
switch ($workbench->type) {
2025-08-12 09:28:57 +08:00
//自动点赞
2025-04-10 16:40:30 +08:00
case self::TYPE_AUTO_LIKE:
if (!empty($workbench->autoLike)) {
$workbench->config = $workbench->autoLike;
2025-09-11 15:16:04 +08:00
$workbench->config->deviceGroups = json_decode($workbench->config->devices, true);
2025-12-04 11:10:55 +08:00
$workbench->config->wechatFriends = json_decode($workbench->config->friends, true);
$workbench->config->targetType = 2;
2025-05-09 09:22:31 +08:00
//$workbench->config->targetGroups = json_decode($workbench->config->targetGroups, true);
2025-04-11 16:15:48 +08:00
$workbench->config->contentTypes = json_decode($workbench->config->contentTypes, true);
2025-08-12 09:28:57 +08:00
// 添加今日点赞数
$startTime = strtotime(date('Y-m-d') . ' 00:00:00');
$endTime = strtotime(date('Y-m-d') . ' 23:59:59');
$todayLikeCount = Db::name('workbench_auto_like_item')
->where('workbenchId', $workbench->id)
->whereTime('createTime', 'between', [$startTime, $endTime])
->count();
2025-08-12 09:28:57 +08:00
// 添加总点赞数
$totalLikeCount = Db::name('workbench_auto_like_item')
->where('workbenchId', $workbench->id)
->count();
2025-08-12 09:28:57 +08:00
$workbench->config->todayLikeCount = $todayLikeCount;
$workbench->config->totalLikeCount = $totalLikeCount;
2025-08-12 09:28:57 +08:00
unset($workbench->autoLike, $workbench->auto_like);
2025-04-10 16:40:30 +08:00
}
break;
2025-08-12 09:28:57 +08:00
//自动同步朋友圈
2025-04-10 16:40:30 +08:00
case self::TYPE_MOMENTS_SYNC:
if (!empty($workbench->momentsSync)) {
$workbench->config = $workbench->momentsSync;
2025-09-11 15:16:04 +08:00
$workbench->config->deviceGroups = json_decode($workbench->config->devices, true);
2025-08-12 09:28:57 +08:00
$workbench->config->contentGroups = json_decode($workbench->config->contentLibraries, true);
2025-07-06 00:17:24 +08:00
//同步记录
$sendNum = Db::name('workbench_moments_sync_item')->where(['workbenchId' => $workbench->id])->count();
$workbench->syncCount = $sendNum;
$lastTime = Db::name('workbench_moments_sync_item')->where(['workbenchId' => $workbench->id])->order('id DESC')->value('createTime');
2025-08-12 09:28:57 +08:00
$workbench->lastSyncTime = !empty($lastTime) ? date('Y-m-d H:i', $lastTime) : '--';
unset($workbench->momentsSync, $workbench->moments_sync);
2025-04-10 16:40:30 +08:00
}
break;
2025-08-12 09:28:57 +08:00
//群推送
2025-04-10 16:40:30 +08:00
case self::TYPE_GROUP_PUSH:
if (!empty($workbench->groupPush)) {
$workbench->config = $workbench->groupPush;
2025-11-07 15:25:50 +08:00
$workbench->config->targetType = isset($workbench->config->targetType) ? intval($workbench->config->targetType) : 1; // 默认1=群推送
2025-11-13 16:10:47 +08:00
$workbench->config->groupPushSubType = isset($workbench->config->groupPushSubType) ? intval($workbench->config->groupPushSubType) : 1; // 默认1=群群发
$workbench->config->ownerWechatIds = json_decode($workbench->config->ownerWechatIds ?? '[]', true) ?: [];
2025-11-07 15:25:50 +08:00
// 根据targetType解析不同的数据
if ($workbench->config->targetType == 1) {
// 群推送
$workbench->config->wechatGroups = json_decode($workbench->config->groups, true) ?: [];
$workbench->config->wechatFriends = [];
2025-11-13 16:10:47 +08:00
$workbench->config->trafficPools = [];
// 群推送不需要devices字段
// 群公告相关字段
if ($workbench->config->groupPushSubType == 2) {
$workbench->config->announcementContent = isset($workbench->config->announcementContent) ? $workbench->config->announcementContent : '';
$workbench->config->enableAiRewrite = isset($workbench->config->enableAiRewrite) ? intval($workbench->config->enableAiRewrite) : 0;
$workbench->config->aiRewritePrompt = isset($workbench->config->aiRewritePrompt) ? $workbench->config->aiRewritePrompt : '';
}
2025-11-07 15:25:50 +08:00
} else {
// 好友推送
$workbench->config->wechatFriends = json_decode($workbench->config->friends, true) ?: [];
$workbench->config->wechatGroups = [];
2025-11-13 16:10:47 +08:00
$workbench->config->trafficPools = json_decode($workbench->config->trafficPools ?? '[]', true) ?: [];
2025-11-07 15:25:50 +08:00
}
$workbench->config->contentLibraries = json_decode($workbench->config->contentLibraries, true);
2025-11-13 16:10:47 +08:00
$workbench->config->postPushTags = json_decode($workbench->config->postPushTags ?? '[]', true) ?: [];
unset($workbench->groupPush, $workbench->group_push);
2025-04-10 16:40:30 +08:00
}
break;
2025-08-12 09:28:57 +08:00
//建群助手
2025-04-10 16:40:30 +08:00
case self::TYPE_GROUP_CREATE:
if (!empty($workbench->groupCreate)) {
$workbench->config = $workbench->groupCreate;
2025-09-11 15:16:04 +08:00
$workbench->config->deviceGroups = json_decode($workbench->config->devices, true);
2025-08-22 10:23:05 +08:00
$workbench->config->poolGroups = json_decode($workbench->config->poolGroups, true);
$workbench->config->wechatGroups = json_decode($workbench->config->wechatGroups, true);
unset($workbench->groupCreate, $workbench->group_create);
2025-04-10 16:40:30 +08:00
}
break;
2025-08-12 09:28:57 +08:00
//流量分发
case self::TYPE_TRAFFIC_DISTRIBUTION:
if (!empty($workbench->trafficConfig)) {
$workbench->config = $workbench->trafficConfig;
2025-09-11 15:16:04 +08:00
$workbench->config->deviceGroups = json_decode($workbench->config->devices, true);
2025-08-12 09:28:57 +08:00
$workbench->config->accountGroups = json_decode($workbench->config->account, true);
2025-09-22 18:03:45 +08:00
$workbench->config->poolGroups = json_decode($workbench->config->pools, true);
$config_item = Db::name('workbench_traffic_config_item')->where(['workbenchId' => $workbench->id])->order('id DESC')->find();
2025-08-12 09:28:57 +08:00
$workbench->config->lastUpdated = !empty($config_item) ? date('Y-m-d H:i', $config_item['createTime']) : '--';
//统计
2025-09-22 18:03:45 +08:00
$labels = $workbench->config->poolGroups;
$totalUsers = Db::table('s2_wechat_friend')->alias('wf')
->join(['s2_company_account' => 'sa'], 'sa.id = wf.accountId', 'left')
->join(['s2_wechat_account' => 'wa'], 'wa.id = wf.wechatAccountId', 'left')
->where([
['wf.isDeleted', '=', 0],
['sa.departmentId', '=', $workbench->companyId]
])
2025-09-11 15:16:04 +08:00
->whereIn('wa.currentDeviceId', $workbench->config->deviceGroups)
->field('wf.id,wf.wechatAccountId,wf.wechatId,wf.labels,sa.userName,wa.currentDeviceId as deviceId')
->where(function ($q) use ($labels) {
2025-08-12 09:28:57 +08:00
foreach ($labels as $label) {
$q->whereOrRaw("JSON_CONTAINS(wf.labels, '\"{$label}\"')");
}
})->count();
$totalAccounts = Db::table('s2_company_account')
2025-08-12 09:28:57 +08:00
->alias('a')
->where(['a.departmentId' => $workbench->companyId, 'a.status' => 0])
->whereNotLike('a.userName', '%_offline%')
->whereNotLike('a.userName', '%_delete%')
->group('a.id')
->count();
$dailyAverage = Db::name('workbench_traffic_config_item')
2025-08-12 09:28:57 +08:00
->where('workbenchId', $workbench->id)
->count();
$day = (time() - strtotime($workbench->createTime)) / 86400;
$day = intval($day);
2025-08-12 09:28:57 +08:00
if ($dailyAverage > 0) {
$dailyAverage = $dailyAverage / $totalAccounts / $day;
}
$workbench->config->total = [
'dailyAverage' => intval($dailyAverage),
'totalAccounts' => $totalAccounts,
2025-09-11 15:16:04 +08:00
'deviceCount' => count($workbench->config->deviceGroups),
2025-09-22 18:03:45 +08:00
'poolCount' => count($workbench->config->poolGroups),
'totalUsers' => $totalUsers >> 0
];
2025-08-12 09:28:57 +08:00
unset($workbench->trafficConfig, $workbench->traffic_config);
}
break;
2025-09-10 11:43:47 +08:00
case self::TYPE_IMPORT_CONTACT:
2025-09-11 10:08:26 +08:00
if (!empty($workbench->importContact)) {
$workbench->config = $workbench->importContact;
2025-09-11 15:16:04 +08:00
$workbench->config->deviceGroups = json_decode($workbench->config->devices, true);
2025-09-22 18:03:45 +08:00
$workbench->config->poolGroups = json_decode($workbench->config->pools, true);
2025-09-10 11:43:47 +08:00
}
2025-09-11 10:08:26 +08:00
unset($workbench->importContact, $workbench->import_contact);
2025-09-10 11:43:47 +08:00
break;
2025-04-10 16:40:30 +08:00
}
2025-08-12 09:28:57 +08:00
unset(
$workbench->autoLike,
$workbench->momentsSync,
$workbench->groupPush,
$workbench->groupCreate,
$workbench->config->devices,
$workbench->config->friends,
$workbench->config->groups,
$workbench->config->contentLibraries,
$workbench->config->account,
);
//获取设备信息
2025-09-11 15:16:04 +08:00
if (!empty($workbench->config->deviceGroups)) {
2025-08-12 09:28:57 +08:00
$deviceList = DeviceModel::alias('d')
->field([
'd.id', 'd.imei', 'd.memo', 'd.alive',
'l.wechatId',
'a.nickname', 'a.alias', 'a.avatar', 'a.alias', '0 totalFriend'
2025-08-12 09:28:57 +08:00
])
->leftJoin('device_wechat_login l', 'd.id = l.deviceId and l.alive =' . DeviceWechatLoginModel::ALIVE_WECHAT_ACTIVE . ' and l.companyId = d.companyId')
->leftJoin('wechat_account a', 'l.wechatId = a.wechatId')
2025-09-11 15:16:04 +08:00
->whereIn('d.id', $workbench->config->deviceGroups)
2025-08-12 09:28:57 +08:00
->order('d.id desc')
->select();
foreach ($deviceList as &$device) {
2025-11-13 16:10:47 +08:00
$curstomer = WechatCustomerModel::field('friendShip')->where(['wechatId' => $device['wechatId']])->find();
$device['totalFriend'] = $curstomer->friendShip->totalFriend ?? 0;
}
unset($device);
2025-09-11 15:16:04 +08:00
$workbench->config->deviceGroupsOptions = $deviceList;
2025-08-12 09:28:57 +08:00
} else {
2025-09-11 15:16:04 +08:00
$workbench->config->deviceGroupsOptions = [];
2025-08-12 09:28:57 +08:00
}
2025-11-07 15:25:50 +08:00
// 获取群当targetType=1时
2025-11-13 16:10:47 +08:00
if (!empty($workbench->config->wechatGroups) && isset($workbench->config->targetType) && $workbench->config->targetType == 1) {
2025-08-12 09:28:57 +08:00
$groupList = Db::name('wechat_group')->alias('wg')
->join('wechat_account wa', 'wa.wechatId = wg.ownerWechatId')
2025-11-07 15:25:50 +08:00
->where('wg.id', 'in', $workbench->config->wechatGroups)
2025-08-12 09:28:57 +08:00
->order('wg.id', 'desc')
->field('wg.id,wg.name as groupName,wg.ownerWechatId,wa.nickName,wa.avatar,wa.alias,wg.avatar as groupAvatar')
->select();
$workbench->config->wechatGroupsOptions = $groupList;
2025-11-13 16:10:47 +08:00
} else {
2025-08-12 09:28:57 +08:00
$workbench->config->wechatGroupsOptions = [];
}
2025-11-07 15:25:50 +08:00
// 获取好友当targetType=2时
2025-11-13 16:10:47 +08:00
if (!empty($workbench->config->wechatFriends) && isset($workbench->config->targetType) && $workbench->config->targetType == 2) {
2025-11-07 15:25:50 +08:00
$friendList = Db::table('s2_wechat_friend')->alias('wf')
2025-12-04 11:10:55 +08:00
->join(['s2_wechat_account' => 'wa'], 'wa.id = wf.wechatAccountId', 'left')
2025-11-07 15:25:50 +08:00
->where('wf.id', 'in', $workbench->config->wechatFriends)
->order('wf.id', 'desc')
->field('wf.id,wf.wechatId,wf.nickname as friendName,wf.avatar as friendAvatar,wf.conRemark,wf.ownerWechatId,wa.nickName as accountName,wa.avatar as accountAvatar')
->select();
$workbench->config->wechatFriendsOptions = $friendList;
2025-11-13 16:10:47 +08:00
} else {
2025-11-07 15:25:50 +08:00
$workbench->config->wechatFriendsOptions = [];
}
2025-11-13 16:10:47 +08:00
// 获取流量池当targetType=2时
if (!empty($workbench->config->trafficPools) && isset($workbench->config->targetType) && $workbench->config->targetType == 2) {
$poolList = Db::name('traffic_source_package')->alias('tsp')
->leftJoin('traffic_source_package_item tspi', 'tspi.packageId = tsp.id and tspi.isDel = 0')
->whereIn('tsp.id', $workbench->config->trafficPools)
->where('tsp.isDel', 0)
->whereIn('tsp.companyId', [$this->request->userInfo['companyId'], 0])
->field('tsp.id,tsp.name,tsp.description,tsp.pic,COUNT(tspi.id) as itemCount')
->group('tsp.id')
->order('tsp.id', 'desc')
->select();
$workbench->config->trafficPoolsOptions = $poolList;
} else {
$workbench->config->trafficPoolsOptions = [];
}
2025-08-12 09:28:57 +08:00
// 获取内容库名称
if (!empty($workbench->config->contentGroups)) {
$libraryNames = ContentLibrary::where('id', 'in', $workbench->config->contentGroups)->select();
$workbench->config->contentGroupsOptions = $libraryNames;
} else {
$workbench->config->contentGroupsOptions = [];
}
//账号
2025-11-13 16:10:47 +08:00
if (!empty($workbench->config->accountGroups)) {
2025-08-12 09:28:57 +08:00
$account = Db::table('s2_company_account')->alias('a')
->where(['a.departmentId' => $this->request->userInfo['companyId'], 'a.status' => 0])
->whereIn('a.id', $workbench->config->accountGroups)
->whereNotLike('a.userName', '%_offline%')
->whereNotLike('a.userName', '%_delete%')
->field('a.id,a.userName,a.realName,a.nickname,a.memo')
->select();
2025-11-13 16:10:47 +08:00
$workbench->config->accountGroupsOptions = $account;
} else {
2025-08-12 09:28:57 +08:00
$workbench->config->accountGroupsOptions = [];
}
2025-04-10 16:40:30 +08:00
2025-11-13 16:10:47 +08:00
if (!empty($workbench->config->poolGroups)) {
2025-08-22 10:23:05 +08:00
$poolGroupsOptions = Db::name('traffic_source_package')->alias('tsp')
2025-11-13 16:10:47 +08:00
->join('traffic_source_package_item tspi', 'tspi.packageId=tsp.id', 'left')
->whereIn('tsp.companyId', [$this->request->userInfo['companyId'], 0])
2025-08-22 10:23:05 +08:00
->whereIn('tsp.id', $workbench->config->poolGroups)
->field('tsp.id,tsp.name,tsp.description,tsp.createTime,count(tspi.id) as num')
->group('tsp.id')
->select();
$workbench->config->poolGroupsOptions = $poolGroupsOptions;
2025-11-13 16:10:47 +08:00
} else {
2025-08-22 10:23:05 +08:00
$workbench->config->poolGroupsOptions = [];
}
2025-11-13 16:10:47 +08:00
if (!empty($workbench->config->ownerWechatIds)) {
$ownerWechatOptions = Db::name('wechat_account')
->whereIn('id', $workbench->config->ownerWechatIds)
->field('id,wechatId,nickName,avatar,alias')
->select();
$workbench->config->ownerWechatOptions = $ownerWechatOptions;
} else {
$workbench->config->ownerWechatOptions = [];
}
2025-08-22 10:23:05 +08:00
2025-04-10 16:40:30 +08:00
return json(['code' => 200, 'msg' => '获取成功', 'data' => $workbench]);
}
2025-04-11 16:15:48 +08:00
/**
* 更新工作台
* @return \think\response\Json
*/
public function update()
{
if (!$this->request->isPost()) {
return json(['code' => 400, 'msg' => '请求方式错误']);
}
// 获取请求参数
$param = $this->request->post();
// 验证数据
$validate = new WorkbenchValidate;
if (!$validate->scene('update')->check($param)) {
return json(['code' => 400, 'msg' => $validate->getError()]);
}
2025-11-17 17:34:46 +08:00
$where = [
2025-04-11 16:15:48 +08:00
['id', '=', $param['id']],
2025-11-17 17:34:46 +08:00
['companyId', '=', $this->request->userInfo['companyId']],
2025-04-11 16:15:48 +08:00
['isDel', '=', 0]
2025-11-17 17:34:46 +08:00
];
if (empty($this->request->userInfo['isAdmin'])) {
$where[] = ['userId', '=', $this->request->userInfo['id']];
}
// 查询工作台是否存在
$workbench = Workbench::where($where)->find();
2025-04-11 16:15:48 +08:00
if (!$workbench) {
return json(['code' => 404, 'msg' => '工作台不存在']);
}
Db::startTrans();
try {
// 更新工作台基本信息
$workbench->name = $param['name'];
2025-08-22 10:23:05 +08:00
$workbench->status = !empty($param['status']) ? 1 : 0;
2025-04-11 16:15:48 +08:00
$workbench->autoStart = !empty($param['autoStart']) ? 1 : 0;
$workbench->updateTime = time();
$workbench->save();
// 根据类型更新对应的配置
switch ($workbench->type) {
case self::TYPE_AUTO_LIKE:
$config = WorkbenchAutoLike::where('workbenchId', $param['id'])->find();
if ($config) {
$config->interval = $param['interval'];
$config->maxLikes = $param['maxLikes'];
$config->startTime = $param['startTime'];
$config->endTime = $param['endTime'];
$config->contentTypes = json_encode($param['contentTypes']);
2025-09-11 15:16:04 +08:00
$config->devices = json_encode($param['deviceGroups']);
2025-12-04 11:10:55 +08:00
$config->friends = json_encode($param['wechatFriends']);
2025-05-09 09:22:31 +08:00
// $config->targetGroups = json_encode($param['targetGroups']);
// $config->tagOperator = $param['tagOperator'];
2025-05-16 09:43:04 +08:00
$config->friendMaxLikes = $param['friendMaxLikes'];
$config->friendTags = $param['friendTags'];
$config->enableFriendTags = $param['enableFriendTags'];
2025-04-11 16:15:48 +08:00
$config->updateTime = time();
$config->save();
}
break;
case self::TYPE_MOMENTS_SYNC:
$config = WorkbenchMomentsSync::where('workbenchId', $param['id'])->find();
if ($config) {
2025-08-12 09:28:57 +08:00
if (!empty($param['contentGroups'])) {
foreach ($param['contentGroups'] as $library) {
if (isset($library['id']) && !empty($library['id'])) {
2025-07-11 11:09:48 +08:00
$contentLibraries[] = $library['id'];
2025-08-12 09:28:57 +08:00
} else {
2025-07-11 11:09:48 +08:00
$contentLibraries[] = $library;
}
}
2025-08-12 09:28:57 +08:00
} else {
2025-07-11 11:09:48 +08:00
$contentLibraries = [];
}
2025-08-12 09:28:57 +08:00
2025-04-11 16:15:48 +08:00
$config->syncInterval = $param['syncInterval'];
$config->syncCount = $param['syncCount'];
$config->syncType = $param['syncType'];
$config->startTime = $param['startTime'];
$config->endTime = $param['endTime'];
$config->accountType = $param['accountType'];
2025-09-11 15:16:04 +08:00
$config->devices = json_encode($param['deviceGroups']);
2025-07-11 11:09:48 +08:00
$config->contentLibraries = json_encode($contentLibraries);
2025-04-11 16:15:48 +08:00
$config->updateTime = time();
$config->save();
}
break;
case self::TYPE_GROUP_PUSH:
$config = WorkbenchGroupPush::where('workbenchId', $param['id'])->find();
if ($config) {
2025-11-13 16:10:47 +08:00
$ownerWechatIds = $this->normalizeOwnerWechatIds($param['ownerWechatIds'] ?? null, $config);
$groupPushData = $this->prepareGroupPushData($param, $ownerWechatIds, $config);
$groupPushData['updateTime'] = time();
$config->save($groupPushData);
2025-04-11 16:15:48 +08:00
}
break;
case self::TYPE_GROUP_CREATE:
$config = WorkbenchGroupCreate::where('workbenchId', $param['id'])->find();
if ($config) {
2025-09-11 15:16:04 +08:00
$config->devices = json_encode($param['deviceGroups'], JSON_UNESCAPED_UNICODE);
$config->startTime = $param['startTime'];
$config->endTime = $param['endTime'];
$config->groupSizeMin = $param['groupSizeMin'];
$config->groupSizeMax = $param['groupSizeMax'];
$config->maxGroupsPerDay = $param['maxGroupsPerDay'];
$config->groupNameTemplate = $param['groupNameTemplate'];
$config->groupDescription = $param['groupDescription'];
2025-08-22 10:23:05 +08:00
$config->poolGroups = json_encode($param['poolGroups'] ?? []);
$config->wechatGroups = json_encode($param['wechatGroups'] ?? []);
2025-04-11 16:15:48 +08:00
$config->updateTime = time();
$config->save();
}
break;
case self::TYPE_TRAFFIC_DISTRIBUTION:
$config = WorkbenchTrafficConfig::where('workbenchId', $param['id'])->find();
if ($config) {
$config->distributeType = $param['distributeType'];
$config->maxPerDay = $param['maxPerDay'];
$config->timeType = $param['timeType'];
$config->startTime = $param['startTime'];
$config->endTime = $param['endTime'];
2025-09-11 15:16:04 +08:00
$config->devices = json_encode($param['deviceGroups']);
2025-09-22 18:03:45 +08:00
$config->pools = json_encode($param['poolGroups']);
2025-08-12 09:28:57 +08:00
$config->account = json_encode($param['accountGroups']);
$config->updateTime = time();
$config->save();
}
break;
2025-09-10 11:43:47 +08:00
case self::TYPE_IMPORT_CONTACT: //联系人导入
2025-11-13 16:10:47 +08:00
$config = WorkbenchImportContact::where('workbenchId', $param['id'])->find();;
2025-09-10 11:43:47 +08:00
if ($config) {
2025-09-11 15:16:04 +08:00
$config->devices = json_encode($param['deviceGroups']);
2025-09-22 18:03:45 +08:00
$config->pools = json_encode($param['poolGroups']);
2025-09-10 11:43:47 +08:00
$config->num = $param['num'];
$config->clearContact = $param['clearContact'];
$config->remark = $param['remark'];
$config->startTime = $param['startTime'];
$config->endTime = $param['endTime'];
$config->save();
}
break;
2025-04-11 16:15:48 +08:00
}
Db::commit();
return json(['code' => 200, 'msg' => '更新成功']);
} catch (\Exception $e) {
Db::rollback();
return json(['code' => 500, 'msg' => '更新失败:' . $e->getMessage()]);
}
}
2025-04-10 16:40:30 +08:00
/**
* 更新工作台状态
* @return \think\response\Json
*/
public function updateStatus()
{
if (!$this->request->isPost()) {
return json(['code' => 400, 'msg' => '请求方式错误']);
}
2025-08-12 09:28:57 +08:00
$id = $this->request->param('id', '');
2025-04-10 16:40:30 +08:00
2025-08-12 09:28:57 +08:00
if (empty($id)) {
2025-06-10 09:53:01 +08:00
return json(['code' => 400, 'msg' => '参数错误']);
2025-04-10 16:40:30 +08:00
}
2025-11-17 17:34:46 +08:00
$where = [
2025-06-10 09:53:01 +08:00
['id', '=', $id],
2025-11-17 17:34:46 +08:00
['companyId', '=', $this->request->userInfo['companyId']],
['isDel', '=', 0]
];
if (empty($this->request->userInfo['isAdmin'])) {
$where[] = ['userId', '=', $this->request->userInfo['id']];
}
$workbench = Workbench::where($where)->find();
2025-04-10 16:40:30 +08:00
if (empty($workbench)) {
return json(['code' => 404, 'msg' => '工作台不存在']);
}
$workbench->status = !$workbench['status'];
$workbench->save();
return json(['code' => 200, 'msg' => '更新成功']);
}
/**
* 删除工作台(软删除)
*/
2025-04-11 16:15:48 +08:00
public function delete()
2025-04-10 16:40:30 +08:00
{
2025-04-11 16:15:48 +08:00
$id = $this->request->param('id');
2025-04-10 16:40:30 +08:00
if (empty($id)) {
return json(['code' => 400, 'msg' => '参数错误']);
}
2025-11-17 17:34:46 +08:00
$where = [
2025-04-10 16:40:30 +08:00
['id', '=', $id],
2025-11-17 17:34:46 +08:00
['companyId', '=', $this->request->userInfo['companyId']],
2025-04-10 16:40:30 +08:00
['isDel', '=', 0]
2025-11-17 17:34:46 +08:00
];
if (empty($this->request->userInfo['isAdmin'])) {
$where[] = ['userId', '=', $this->request->userInfo['id']];
}
$workbench = Workbench::where($where)->find();
2025-04-10 16:40:30 +08:00
if (!$workbench) {
return json(['code' => 404, 'msg' => '工作台不存在']);
}
// 软删除
$workbench->isDel = 1;
$workbench->deleteTime = time();
2025-04-10 16:40:30 +08:00
$workbench->save();
return json(['code' => 200, 'msg' => '删除成功']);
}
/**
* 拷贝工作台
* @return \think\response\Json
*/
public function copy()
{
if (!$this->request->isPost()) {
return json(['code' => 400, 'msg' => '请求方式错误']);
}
$id = $this->request->post('id');
if (empty($id)) {
return json(['code' => 400, 'msg' => '参数错误']);
}
// 验证权限并获取原数据
$workbench = Workbench::where([
['id', '=', $id],
['userId', '=', $this->request->userInfo['id']]
])->find();
if (empty($workbench)) {
return json(['code' => 404, 'msg' => '工作台不存在']);
}
Db::startTrans();
try {
// 创建新的工作台基本信息
$newWorkbench = new Workbench;
$newWorkbench->name = $workbench->name . ' copy';
$newWorkbench->type = $workbench->type;
$newWorkbench->status = 1; // 新拷贝的默认启用
$newWorkbench->autoStart = $workbench->autoStart;
$newWorkbench->userId = $this->request->userInfo['id'];
2025-04-11 16:15:48 +08:00
$newWorkbench->companyId = $this->request->userInfo['companyId'];
2025-04-10 16:40:30 +08:00
$newWorkbench->save();
// 根据类型拷贝对应的配置
switch ($workbench->type) {
case self::TYPE_AUTO_LIKE:
$config = WorkbenchAutoLike::where('workbenchId', $id)->find();
if ($config) {
$newConfig = new WorkbenchAutoLike;
$newConfig->workbenchId = $newWorkbench->id;
$newConfig->interval = $config->interval;
$newConfig->maxLikes = $config->maxLikes;
$newConfig->startTime = $config->startTime;
$newConfig->endTime = $config->endTime;
$newConfig->contentTypes = $config->contentTypes;
$newConfig->devices = $config->devices;
2025-05-09 09:22:31 +08:00
$newConfig->friends = $config->friends;
2025-08-22 10:23:05 +08:00
$newConfig->createTime = time();
$newConfig->updateTime = time();
2025-04-10 16:40:30 +08:00
$newConfig->save();
}
break;
case self::TYPE_MOMENTS_SYNC:
$config = WorkbenchMomentsSync::where('workbenchId', $id)->find();
if ($config) {
$newConfig = new WorkbenchMomentsSync;
$newConfig->workbenchId = $newWorkbench->id;
$newConfig->syncInterval = $config->syncInterval;
$newConfig->syncCount = $config->syncCount;
$newConfig->syncType = $config->syncType;
2025-04-11 16:15:48 +08:00
$newConfig->startTime = $config->startTime;
$newConfig->endTime = $config->endTime;
$newConfig->accountType = $config->accountType;
2025-04-10 16:40:30 +08:00
$newConfig->devices = $config->devices;
2025-04-11 16:15:48 +08:00
$newConfig->contentLibraries = $config->contentLibraries;
2025-08-22 10:23:05 +08:00
$newConfig->createTime = time();
$newConfig->updateTime = time();
2025-04-10 16:40:30 +08:00
$newConfig->save();
}
break;
case self::TYPE_GROUP_PUSH:
$config = WorkbenchGroupPush::where('workbenchId', $id)->find();
if ($config) {
$newConfig = new WorkbenchGroupPush;
$newConfig->workbenchId = $newWorkbench->id;
$newConfig->pushType = $config->pushType;
2025-11-07 15:25:50 +08:00
$newConfig->targetType = isset($config->targetType) ? $config->targetType : 1; // 默认1=群推送
$newConfig->startTime = $config->startTime;
$newConfig->endTime = $config->endTime;
$newConfig->maxPerDay = $config->maxPerDay;
$newConfig->pushOrder = $config->pushOrder;
$newConfig->isLoop = $config->isLoop;
$newConfig->status = $config->status;
$newConfig->groups = $config->groups;
2025-11-07 15:25:50 +08:00
$newConfig->friends = $config->friends;
$newConfig->contentLibraries = $config->contentLibraries;
2025-11-13 16:10:47 +08:00
$newConfig->trafficPools = property_exists($config, 'trafficPools') ? $config->trafficPools : json_encode([], JSON_UNESCAPED_UNICODE);
2025-11-07 15:25:50 +08:00
$newConfig->socialMediaId = $config->socialMediaId;
$newConfig->promotionSiteId = $config->promotionSiteId;
2025-11-13 16:10:47 +08:00
$newConfig->ownerWechatIds = $config->ownerWechatIds;
2025-08-22 10:23:05 +08:00
$newConfig->createTime = time();
$newConfig->updateTime = time();
2025-04-10 16:40:30 +08:00
$newConfig->save();
}
break;
case self::TYPE_GROUP_CREATE:
$config = WorkbenchGroupCreate::where('workbenchId', $id)->find();
if ($config) {
$newConfig = new WorkbenchGroupCreate;
$newConfig->workbenchId = $newWorkbench->id;
$newConfig->devices = $config->devices;
$newConfig->startTime = $config->startTime;
$newConfig->endTime = $config->endTime;
$newConfig->groupSizeMin = $config->groupSizeMin;
$newConfig->groupSizeMax = $config->groupSizeMax;
$newConfig->maxGroupsPerDay = $config->maxGroupsPerDay;
$newConfig->groupNameTemplate = $config->groupNameTemplate;
$newConfig->groupDescription = $config->groupDescription;
2025-11-13 16:10:47 +08:00
$newConfig->poolGroups = $config->poolGroups;
$newConfig->wechatGroups = $config->wechatGroups;
$newConfig->createTime = time();
$newConfig->updateTime = time();
2025-04-10 16:40:30 +08:00
$newConfig->save();
}
break;
2025-09-10 11:43:47 +08:00
case self::TYPE_IMPORT_CONTACT: //联系人导入
2025-11-13 16:10:47 +08:00
$config = WorkbenchImportContact::where('workbenchId', $id)->find();
2025-09-10 11:43:47 +08:00
if ($config) {
$newConfig = new WorkbenchImportContact;
2025-09-11 10:08:26 +08:00
$newConfig->workbenchId = $newWorkbench->id;
$newConfig->devices = $config->devices;
$newConfig->pools = $config->pools;
2025-09-10 11:43:47 +08:00
$newConfig->num = $config->num;
$newConfig->clearContact = $config->clearContact;
$newConfig->remark = $config->remark;
$newConfig->startTime = $config->startTime;
$newConfig->endTime = $config->endTime;
$newConfig->createTime = time();
$newConfig->save();
}
break;
2025-04-10 16:40:30 +08:00
}
Db::commit();
return json(['code' => 200, 'msg' => '拷贝成功', 'data' => ['id' => $newWorkbench->id]]);
} catch (\Exception $e) {
Db::rollback();
return json(['code' => 500, 'msg' => '拷贝失败:' . $e->getMessage()]);
}
}
2025-05-16 15:12:49 +08:00
/**
* 获取点赞记录列表
* @return \think\response\Json
*/
public function getLikeRecords()
{
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$workbenchId = $this->request->param('workbenchId', 0);
$where = [
['wali.workbenchId', '=', $workbenchId]
];
// 查询点赞记录
$list = Db::name('workbench_auto_like_item')->alias('wali')
2025-07-02 15:48:22 +08:00
->join(['s2_wechat_moments' => 'wm'], 'wali.snsId = wm.snsId')
2025-05-16 15:12:49 +08:00
->field([
'wali.id',
'wali.workbenchId',
'wali.momentsId',
'wali.snsId',
'wali.wechatAccountId',
'wali.wechatFriendId',
'wali.createTime as likeTime',
'wm.content',
'wm.resUrls',
'wm.createTime as momentTime',
'wm.userName',
])
->where($where)
->order('wali.createTime', 'desc')
2025-07-02 15:48:22 +08:00
->group('wali.id')
2025-05-16 15:12:49 +08:00
->page($page, $limit)
->select();
2025-05-16 15:12:49 +08:00
// 处理数据
foreach ($list as &$item) {
//处理用户信息
$friend = Db::table('s2_wechat_friend')
->where(['id' => $item['wechatFriendId']])
->field('nickName,avatar')
->find();
2025-11-13 16:10:47 +08:00
if (!empty($friend)) {
$item['friendName'] = $friend['nickName'];
$item['friendAvatar'] = $friend['avatar'];
2025-11-13 16:10:47 +08:00
} else {
$item['friendName'] = '';
$item['friendAvatar'] = '';
}
//处理客服
$friend = Db::table('s2_wechat_account')
->where(['id' => $item['wechatAccountId']])
->field('nickName,avatar')
->find();
2025-11-13 16:10:47 +08:00
if (!empty($friend)) {
$item['operatorName'] = $friend['nickName'];
$item['operatorAvatar'] = $friend['avatar'];
2025-11-13 16:10:47 +08:00
} else {
$item['operatorName'] = '';
$item['operatorAvatar'] = '';
}
2025-05-16 15:12:49 +08:00
// 处理时间格式
$item['likeTime'] = date('Y-m-d H:i:s', $item['likeTime']);
$item['momentTime'] = !empty($item['momentTime']) ? date('Y-m-d H:i:s', $item['momentTime']) : '';
2025-08-12 09:28:57 +08:00
2025-05-16 15:12:49 +08:00
// 处理资源链接
if (!empty($item['resUrls'])) {
$item['resUrls'] = json_decode($item['resUrls'], true);
} else {
$item['resUrls'] = [];
}
}
// 获取总记录数
$total = Db::name('workbench_auto_like_item')->alias('wali')
->where($where)
->count();
return json([
'code' => 200,
'msg' => '获取成功',
'data' => [
'list' => $list,
'total' => $total,
'page' => $page,
'limit' => $limit
]
]);
}
/**
* 获取朋友圈发布记录列表
* @return \think\response\Json
*/
public function getMomentsRecords()
{
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$workbenchId = $this->request->param('workbenchId', 0);
$where = [
['wmsi.workbenchId', '=', $workbenchId]
];
// 查询发布记录
$list = Db::name('workbench_moments_sync_item')->alias('wmsi')
->join('content_item ci', 'ci.id = wmsi.contentId', 'left')
->join(['s2_wechat_account' => 'wa'], 'wa.id = wmsi.wechatAccountId', 'left')
->field([
'wmsi.id',
'wmsi.workbenchId',
'wmsi.createTime as publishTime',
'ci.contentType',
'ci.content',
'ci.resUrls',
'ci.urls',
'wa.nickName as operatorName',
'wa.avatar as operatorAvatar'
])
->where($where)
->order('wmsi.createTime', 'desc')
->page($page, $limit)
->select();
2025-08-12 09:28:57 +08:00
foreach ($list as &$item) {
$item['resUrls'] = json_decode($item['resUrls'], true);
$item['urls'] = json_decode($item['urls'], true);
}
// 获取总记录数
$total = Db::name('workbench_moments_sync_item')->alias('wmsi')
->where($where)
->count();
return json([
'code' => 200,
'msg' => '获取成功',
'data' => [
'list' => $list,
'total' => $total,
'page' => $page,
'limit' => $limit
]
]);
}
/**
* 获取朋友圈发布统计
* @return \think\response\Json
*/
public function getMomentsStats()
{
$workbenchId = $this->request->param('workbenchId', 0);
if (empty($workbenchId)) {
return json(['code' => 400, 'msg' => '参数错误']);
}
// 获取今日数据
$todayStart = strtotime(date('Y-m-d') . ' 00:00:00');
$todayEnd = strtotime(date('Y-m-d') . ' 23:59:59');
2025-08-12 09:28:57 +08:00
$todayStats = Db::name('workbench_moments_sync_item')
->where([
['workbenchId', '=', $workbenchId],
['createTime', 'between', [$todayStart, $todayEnd]]
])
->field([
'COUNT(*) as total',
'SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as success',
'SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) as failed'
])
->find();
// 获取总数据
$totalStats = Db::name('workbench_moments_sync_item')
->where('workbenchId', $workbenchId)
->field([
'COUNT(*) as total',
'SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as success',
'SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) as failed'
])
->find();
return json([
'code' => 200,
'msg' => '获取成功',
'data' => [
'today' => [
'total' => intval($todayStats['total']),
'success' => intval($todayStats['success']),
'failed' => intval($todayStats['failed'])
],
'total' => [
'total' => intval($totalStats['total']),
'success' => intval($totalStats['success']),
'failed' => intval($totalStats['failed'])
]
]
]);
}
/**
* 获取流量分发记录列表
* @return \think\response\Json
*/
public function getTrafficDistributionRecords()
{
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$workbenchId = $this->request->param('workbenchId', 0);
$where = [
['wtdi.workbenchId', '=', $workbenchId]
];
// 查询分发记录
$list = Db::name('workbench_traffic_distribution_item')->alias('wtdi')
->join(['s2_wechat_account' => 'wa'], 'wa.id = wtdi.wechatAccountId', 'left')
->join(['s2_wechat_friend' => 'wf'], 'wf.id = wtdi.wechatFriendId', 'left')
->field([
'wtdi.id',
'wtdi.workbenchId',
'wtdi.wechatAccountId',
'wtdi.wechatFriendId',
'wtdi.createTime as distributeTime',
'wtdi.status',
'wtdi.errorMsg',
'wa.nickName as operatorName',
'wa.avatar as operatorAvatar',
'wf.nickName as friendName',
'wf.avatar as friendAvatar',
'wf.gender',
'wf.province',
'wf.city'
])
->where($where)
->order('wtdi.createTime', 'desc')
->page($page, $limit)
->select();
// 处理数据
foreach ($list as &$item) {
// 处理时间格式
$item['distributeTime'] = date('Y-m-d H:i:s', $item['distributeTime']);
2025-08-12 09:28:57 +08:00
// 处理性别
$genderMap = [
0 => '未知',
1 => '男',
2 => '女'
];
$item['genderText'] = $genderMap[$item['gender']] ?? '未知';
// 处理状态文字
$statusMap = [
0 => '待分发',
1 => '分发成功',
2 => '分发失败'
];
$item['statusText'] = $statusMap[$item['status']] ?? '未知状态';
}
// 获取总记录数
$total = Db::name('workbench_traffic_distribution_item')->alias('wtdi')
->where($where)
->count();
return json([
'code' => 200,
'msg' => '获取成功',
'data' => [
'list' => $list,
'total' => $total,
'page' => $page,
'limit' => $limit
]
]);
}
/**
* 获取流量分发统计
* @return \think\response\Json
*/
public function getTrafficDistributionStats()
{
$workbenchId = $this->request->param('workbenchId', 0);
if (empty($workbenchId)) {
return json(['code' => 400, 'msg' => '参数错误']);
}
// 获取今日数据
$todayStart = strtotime(date('Y-m-d') . ' 00:00:00');
$todayEnd = strtotime(date('Y-m-d') . ' 23:59:59');
2025-08-12 09:28:57 +08:00
$todayStats = Db::name('workbench_traffic_distribution_item')
->where([
['workbenchId', '=', $workbenchId],
['createTime', 'between', [$todayStart, $todayEnd]]
])
->field([
'COUNT(*) as total',
'SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as success',
'SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) as failed'
])
->find();
// 获取总数据
$totalStats = Db::name('workbench_traffic_distribution_item')
->where('workbenchId', $workbenchId)
->field([
'COUNT(*) as total',
'SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as success',
'SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) as failed'
])
->find();
return json([
'code' => 200,
'msg' => '获取成功',
'data' => [
'today' => [
'total' => intval($todayStats['total']),
'success' => intval($todayStats['success']),
'failed' => intval($todayStats['failed'])
],
'total' => [
'total' => intval($totalStats['total']),
'success' => intval($totalStats['success']),
'failed' => intval($totalStats['failed'])
]
]
]);
}
/**
* 获取流量分发详情
* @return \think\response\Json
*/
public function getTrafficDistributionDetail()
{
$id = $this->request->param('id', 0);
if (empty($id)) {
return json(['code' => 400, 'msg' => '参数错误']);
}
$detail = Db::name('workbench_traffic_distribution_item')->alias('wtdi')
->join(['s2_wechat_account' => 'wa'], 'wa.id = wtdi.wechatAccountId', 'left')
->join(['s2_wechat_friend' => 'wf'], 'wf.id = wtdi.wechatFriendId', 'left')
->field([
'wtdi.id',
'wtdi.workbenchId',
'wtdi.wechatAccountId',
'wtdi.wechatFriendId',
'wtdi.createTime as distributeTime',
'wtdi.status',
'wtdi.errorMsg',
'wa.nickName as operatorName',
'wa.avatar as operatorAvatar',
'wf.nickName as friendName',
'wf.avatar as friendAvatar',
'wf.gender',
'wf.province',
'wf.city',
'wf.signature',
'wf.remark'
])
->where('wtdi.id', $id)
->find();
if (empty($detail)) {
return json(['code' => 404, 'msg' => '记录不存在']);
}
// 处理数据
$detail['distributeTime'] = date('Y-m-d H:i:s', $detail['distributeTime']);
2025-08-12 09:28:57 +08:00
// 处理性别
$genderMap = [
0 => '未知',
1 => '男',
2 => '女'
];
$detail['genderText'] = $genderMap[$detail['gender']] ?? '未知';
// 处理状态文字
$statusMap = [
0 => '待分发',
1 => '分发成功',
2 => '分发失败'
];
$detail['statusText'] = $statusMap[$detail['status']] ?? '未知状态';
return json([
'code' => 200,
'msg' => '获取成功',
'data' => $detail
]);
}
/**
* 创建流量分发计划
* @return \think\response\Json
*/
public function createTrafficPlan()
{
$param = $this->request->post();
Db::startTrans();
try {
// 1. 创建主表
$planId = Db::name('ck_workbench')->insertGetId([
'name' => $param['name'],
'type' => self::TYPE_TRAFFIC_DISTRIBUTION,
'status' => 1,
'autoStart' => $param['autoStart'] ?? 0,
'userId' => $this->request->userInfo['id'],
'companyId' => $this->request->userInfo['companyId'],
'createTime' => time(),
'updateTime' => time()
]);
// 2. 创建扩展表
Db::name('ck_workbench_traffic_config')->insert([
'workbenchId' => $planId,
'distributeType' => $param['distributeType'],
'maxPerDay' => $param['maxPerDay'],
'timeType' => $param['timeType'],
'startTime' => $param['startTime'],
'endTime' => $param['endTime'],
'targets' => json_encode($param['targets'], JSON_UNESCAPED_UNICODE),
2025-09-22 18:03:45 +08:00
'pools' => json_encode($param['poolGroups'], JSON_UNESCAPED_UNICODE),
'createTime' => time(),
'updateTime' => time()
]);
Db::commit();
2025-08-12 09:28:57 +08:00
return json(['code' => 200, 'msg' => '创建成功']);
} catch (\Exception $e) {
Db::rollback();
2025-08-12 09:28:57 +08:00
return json(['code' => 500, 'msg' => '创建失败:' . $e->getMessage()]);
}
}
/**
* 获取所有微信好友标签及数量统计
* @return \think\response\Json
*/
public function getDeviceLabels()
{
$deviceIds = $this->request->param('deviceIds', '');
$companyId = $this->request->userInfo['companyId'];
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$keyword = $this->request->param('keyword', '');
$where = [
['wc.companyId', '=', $companyId],
];
if (!empty($deviceIds)) {
$deviceIds = explode(',', $deviceIds);
$where[] = ['dwl.deviceId', 'in', $deviceIds];
}
$wechatAccounts = Db::name('wechat_customer')->alias('wc')
->join('device_wechat_login dwl', 'dwl.wechatId = wc.wechatId AND dwl.companyId = wc.companyId AND dwl.alive = 1')
->join(['s2_wechat_account' => 'wa'], 'wa.wechatId = wc.wechatId')
->where($where)
->field('wa.id,wa.wechatId,wa.nickName,wa.labels')
->select();
$labels = [];
$wechatIds = [];
foreach ($wechatAccounts as $account) {
$labelArr = json_decode($account['labels'], true);
if (is_array($labelArr)) {
foreach ($labelArr as $label) {
if ($label !== '' && $label !== null) {
$labels[] = $label;
}
}
}
$wechatIds[] = $account['wechatId'];
}
// 去重(只保留一个)
$labels = array_values(array_unique($labels));
$wechatIds = array_unique($wechatIds);
// 搜索过滤
if (!empty($keyword)) {
2025-08-12 09:28:57 +08:00
$labels = array_filter($labels, function ($label) use ($keyword) {
return mb_stripos($label, $keyword) !== false;
});
$labels = array_values($labels); // 重新索引数组
}
// 分页处理
$labels2 = array_slice($labels, ($page - 1) * $limit, $limit);
// 统计数量
$newLabel = [];
foreach ($labels2 as $label) {
$friendCount = Db::table('s2_wechat_friend')
2025-08-12 09:28:57 +08:00
->whereIn('ownerWechatId', $wechatIds)
->where('labels', 'like', '%"' . $label . '"%')
->count();
$newLabel[] = [
'label' => $label,
'count' => $friendCount
];
}
// 返回结果
return json([
2025-08-12 09:28:57 +08:00
'code' => 200,
'msg' => '获取成功',
'data' => [
'list' => $newLabel,
'total' => count($labels),
]
]);
}
/**
* 获取群列表
* @return \think\response\Json
*/
public function getGroupList()
{
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$keyword = $this->request->param('keyword', '');
$where = [
['wg.deleteTime', '=', 0],
['wg.companyId', '=', $this->request->userInfo['companyId']],
];
if (!empty($keyword)) {
$where[] = ['wg.name', 'like', '%' . $keyword . '%'];
}
$query = Db::name('wechat_group')->alias('wg')
->join('wechat_account wa', 'wa.wechatId = wg.ownerWechatId')
->where($where);
$total = $query->count();
$list = $query->order('wg.id', 'desc')
2025-08-12 09:28:57 +08:00
->field('wg.id,wg.name as groupName,wg.ownerWechatId,wa.nickName,wg.createTime,wa.avatar,wa.alias,wg.avatar as groupAvatar')
->page($page, $limit)
->select();
// 优化:格式化时间,头像兜底
$defaultGroupAvatar = '';
$defaultAvatar = '';
foreach ($list as &$item) {
$item['createTime'] = $item['createTime'] ? date('Y-m-d H:i:s', $item['createTime']) : '';
$item['groupAvatar'] = $item['groupAvatar'] ?: $defaultGroupAvatar;
$item['avatar'] = $item['avatar'] ?: $defaultAvatar;
}
2025-08-12 09:28:57 +08:00
return json(['code' => 200, 'msg' => '获取成功', 'data' => ['total' => $total, 'list' => $list]]);
}
2025-11-13 16:10:47 +08:00
/**
* 获取流量池列表
* @return \think\response\Json
*/
public function getTrafficPoolList()
{
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$keyword = $this->request->param('keyword', '');
$companyId = $this->request->userInfo['companyId'];
$baseQuery = Db::name('traffic_source_package')->alias('tsp')
->where('tsp.isDel', 0)
->whereIn('tsp.companyId', [$companyId, 0]);
if (!empty($keyword)) {
$baseQuery->whereLike('tsp.name', '%' . $keyword . '%');
}
$total = (clone $baseQuery)->count();
$list = $baseQuery
->leftJoin('traffic_source_package_item tspi', 'tspi.packageId = tsp.id and tspi.isDel = 0')
->field('tsp.id,tsp.name,tsp.description,tsp.pic,tsp.companyId,COUNT(tspi.id) as itemCount,max(tspi.createTime) as latestImportTime')
->group('tsp.id')
->order('tsp.id', 'desc')
->page($page, $limit)
->select();
foreach ($list as &$item) {
$item['latestImportTime'] = !empty($item['latestImportTime']) ? date('Y-m-d H:i:s', $item['latestImportTime']) : '';
}
unset($item);
return json(['code' => 200, 'msg' => '获取成功', 'data' => ['total' => $total, 'list' => $list]]);
}
public function getAccountList()
{
$companyId = $this->request->userInfo['companyId'];
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$query = Db::table('s2_company_account')
2025-08-12 09:28:57 +08:00
->alias('a')
->where(['a.departmentId' => $companyId, 'a.status' => 0])
->whereNotLike('a.userName', '%_offline%')
->whereNotLike('a.userName', '%_delete%');
$total = $query->count();
$list = $query->field('a.id,a.userName,a.realName,a.nickname,a.memo')
2025-08-12 09:28:57 +08:00
->page($page, $limit)
->select();
2025-08-12 09:28:57 +08:00
return json(['code' => 200, 'msg' => '获取成功', 'data' => ['total' => $total, 'list' => $list]]);
}
2025-08-06 18:02:03 +08:00
/**
* 获取京东联盟导购媒体
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getJdSocialMedia()
{
$data = Db::name('jd_social_media')->order('id DESC')->select();
return json(['code' => 200, 'msg' => '获取成功', 'data' => $data]);
}
/**
* 获取京东联盟广告位
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getJdPromotionSite()
{
$id = $this->request->param('id', '');
if (empty($id)) {
return json(['code' => 500, 'msg' => '参数缺失']);
}
2025-08-12 09:28:57 +08:00
$data = Db::name('jd_promotion_site')->where('jdSocialMediaId', $id)->order('id DESC')->select();
2025-08-06 18:02:03 +08:00
return json(['code' => 200, 'msg' => '获取成功', 'data' => $data]);
}
2025-09-02 11:24:23 +08:00
//京东转链-京推推
2025-11-13 16:10:47 +08:00
public function changeLink($content = '', $positionid = '')
2025-09-02 11:24:23 +08:00
{
$unionId = Env::get('jd.unionId', '');
$jttAppId = Env::get('jd.jttAppId', '');
$appKey = Env::get('jd.appKey', '');
$apiUrl = Env::get('jd.apiUrl', '');
$content = !empty($content) ? $content : $this->request->param('content', '');
$positionid = !empty($positionid) ? $positionid : $this->request->param('positionid', '');
2025-11-13 16:10:47 +08:00
if (empty($content)) {
return json_encode(['code' => 500, 'msg' => '转链的内容为空']);
2025-09-02 11:24:23 +08:00
}
2025-11-13 16:10:47 +08:00
2025-09-02 11:24:23 +08:00
// 验证是否包含链接
if (!$this->containsLink($content)) {
2025-11-13 16:10:47 +08:00
return json_encode(['code' => 500, 'msg' => '内容中未检测到有效链接']);
2025-09-02 11:24:23 +08:00
}
2025-11-13 16:10:47 +08:00
if (empty($unionId) || empty($jttAppId) || empty($appKey) || empty($apiUrl)) {
return json_encode(['code' => 500, 'msg' => '参数缺失']);
2025-09-02 11:24:23 +08:00
}
$params = [
'unionid' => $unionId,
'content' => $content,
'appid' => $jttAppId,
'appkey' => $appKey,
'v' => 'v2'
];
if (!empty($positionid)) {
$params['positionid'] = $positionid;
}
2025-11-13 16:10:47 +08:00
$res = requestCurl($apiUrl, $params, 'GET', [], 'json');
$res = json_decode($res, true);
if (empty($res)) {
return json_encode(['code' => 500, 'msg' => '未知错误']);
2025-09-02 11:24:23 +08:00
}
$result = $res['result'];
2025-11-13 16:10:47 +08:00
if ($res['return'] == 0) {
return json_encode(['code' => 200, 'data' => $result['chain_content'], 'msg' => $result['msg']]);
} else {
return json_encode(['code' => 500, 'msg' => $result['msg']]);
2025-09-02 11:24:23 +08:00
}
}
public function getTrafficList()
{
$companyId = $this->request->userInfo['companyId'];
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$keyword = $this->request->param('keyword', '');
$workbenchId = $this->request->param('workbenchId', '');
if (empty($workbenchId)) {
return json(['code' => 400, 'msg' => '参数错误']);
}
2025-11-13 16:10:47 +08:00
$workbench = Db::name('workbench')->where(['id' => $workbenchId, 'isDel' => 0, 'companyId' => $companyId, 'type' => 5])->find();
2025-11-13 16:10:47 +08:00
if (empty($workbench)) {
return json(['code' => 400, 'msg' => '该任务不存在或已删除']);
}
$query = Db::name('workbench_traffic_config_item')->alias('wtc')
2025-11-13 16:10:47 +08:00
->join(['s2_wechat_friend' => 'wf'], 'wtc.wechatFriendId = wf.id')
->join('users u', 'wtc.wechatAccountId = u.s2_accountId', 'left')
->field([
2025-11-13 16:10:47 +08:00
'wtc.id', 'wtc.isRecycle', 'wtc.isRecycle', 'wtc.createTime',
'wf.wechatId', 'wf.alias', 'wf.nickname', 'wf.avatar', 'wf.gender', 'wf.phone',
'u.account', 'u.username'
])
->where(['wtc.workbenchId' => $workbenchId])
->order('wtc.id DESC');
2025-11-13 16:10:47 +08:00
if (!empty($keyword)) {
$query->where('wf.wechatId|wf.alias|wf.nickname|wf.phone|u.account|u.username', 'like', '%' . $keyword . '%');
}
$total = $query->count();
$list = $query->page($page, $limit)->select();
foreach ($list as &$item) {
$item['createTime'] = date('Y-m-d H:i:s', $item['createTime']);
}
unset($item);
$data = [
'total' => $total,
'list' => $list,
];
return json(['code' => 200, 'msg' => '获取成功', 'data' => $data]);
}
2025-11-13 16:10:47 +08:00
/**
* 规范化客服微信ID列表
* @param mixed $ownerWechatIds
* @param WorkbenchGroupPush|null $originalConfig
* @return array
* @throws \Exception
*/
private function normalizeOwnerWechatIds($ownerWechatIds, WorkbenchGroupPush $originalConfig = null): array
{
if ($ownerWechatIds === null) {
$existing = $originalConfig ? $this->decodeJsonArray($originalConfig->ownerWechatIds ?? []) : [];
if (empty($existing)) {
throw new \Exception('请至少选择一个客服微信');
}
return $existing;
}
if (!is_array($ownerWechatIds)) {
throw new \Exception('客服参数格式错误');
}
$normalized = $this->extractIdList($ownerWechatIds, '客服参数格式错误');
if (empty($normalized)) {
throw new \Exception('请至少选择一个客服微信');
}
return $normalized;
}
/**
* 构建群推送配置数据
* @param array $param
* @param array $ownerWechatIds
* @param WorkbenchGroupPush|null $originalConfig
* @return array
* @throws \Exception
*/
private function prepareGroupPushData(array $param, array $ownerWechatIds, WorkbenchGroupPush $originalConfig = null): array
{
$targetTypeDefault = $originalConfig ? intval($originalConfig->targetType) : 1;
$targetType = intval($this->getParamValue($param, 'targetType', $targetTypeDefault)) ?: 1;
$groupPushSubTypeDefault = $originalConfig ? intval($originalConfig->groupPushSubType) : 1;
$groupPushSubType = intval($this->getParamValue($param, 'groupPushSubType', $groupPushSubTypeDefault)) ?: 1;
if (!in_array($groupPushSubType, [1, 2], true)) {
$groupPushSubType = 1;
}
$data = [
'pushType' => $this->toBoolInt($this->getParamValue($param, 'pushType', $originalConfig->pushType ?? 0)),
'targetType' => $targetType,
'startTime' => $this->getParamValue($param, 'startTime', $originalConfig->startTime ?? ''),
'endTime' => $this->getParamValue($param, 'endTime', $originalConfig->endTime ?? ''),
'maxPerDay' => intval($this->getParamValue($param, 'maxPerDay', $originalConfig->maxPerDay ?? 0)),
'pushOrder' => $this->getParamValue($param, 'pushOrder', $originalConfig->pushOrder ?? 1),
'groupPushSubType' => $groupPushSubType,
'status' => $this->toBoolInt($this->getParamValue($param, 'status', $originalConfig->status ?? 0)),
'socialMediaId' => $this->getParamValue($param, 'socialMediaId', $originalConfig->socialMediaId ?? ''),
'promotionSiteId' => $this->getParamValue($param, 'promotionSiteId', $originalConfig->promotionSiteId ?? ''),
'friendIntervalMin' => intval($this->getParamValue($param, 'friendIntervalMin', $originalConfig->friendIntervalMin ?? 10)),
'friendIntervalMax' => intval($this->getParamValue($param, 'friendIntervalMax', $originalConfig->friendIntervalMax ?? 20)),
'messageIntervalMin' => intval($this->getParamValue($param, 'messageIntervalMin', $originalConfig->messageIntervalMin ?? 1)),
'messageIntervalMax' => intval($this->getParamValue($param, 'messageIntervalMax', $originalConfig->messageIntervalMax ?? 12)),
'isRandomTemplate' => $this->toBoolInt($this->getParamValue($param, 'isRandomTemplate', $originalConfig->isRandomTemplate ?? 0)),
'ownerWechatIds' => json_encode($ownerWechatIds, JSON_UNESCAPED_UNICODE),
];
if ($data['friendIntervalMin'] > $data['friendIntervalMax']) {
throw new \Exception('目标间最小间隔不能大于最大间隔');
}
if ($data['messageIntervalMin'] > $data['messageIntervalMax']) {
throw new \Exception('消息间最小间隔不能大于最大间隔');
}
$contentGroupsExisting = $originalConfig ? $this->decodeJsonArray($originalConfig->contentLibraries ?? []) : [];
$contentGroupsParam = $this->getParamValue($param, 'contentGroups', null);
$contentGroups = $contentGroupsParam !== null
? $this->extractIdList($contentGroupsParam, '内容库参数格式错误')
: $contentGroupsExisting;
$data['contentLibraries'] = json_encode($contentGroups, JSON_UNESCAPED_UNICODE);
$postPushTagsExisting = $originalConfig ? $this->decodeJsonArray($originalConfig->postPushTags ?? []) : [];
$postPushTagsParam = $this->getParamValue($param, 'postPushTags', null);
$postPushTags = $postPushTagsParam !== null
? $this->extractIdList($postPushTagsParam, '推送标签参数格式错误')
: $postPushTagsExisting;
$data['postPushTags'] = json_encode($postPushTags, JSON_UNESCAPED_UNICODE);
if ($targetType === 1) {
$data['isLoop'] = $this->toBoolInt($this->getParamValue($param, 'isLoop', $originalConfig->isLoop ?? 0));
$groupsExisting = $originalConfig ? $this->decodeJsonArray($originalConfig->groups ?? []) : [];
$wechatGroups = array_key_exists('wechatGroups', $param)
? $this->extractIdList($param['wechatGroups'], '群参数格式错误')
: $groupsExisting;
if (empty($wechatGroups)) {
throw new \Exception('群推送必须选择微信群');
}
$data['groups'] = json_encode($wechatGroups, JSON_UNESCAPED_UNICODE);
$data['friends'] = json_encode([], JSON_UNESCAPED_UNICODE);
$data['trafficPools'] = json_encode([], JSON_UNESCAPED_UNICODE);
if ($groupPushSubType === 2) {
$announcementContent = $this->getParamValue($param, 'announcementContent', $originalConfig->announcementContent ?? '');
if (empty($announcementContent)) {
throw new \Exception('群公告必须输入公告内容');
}
$enableAiRewrite = $this->toBoolInt($this->getParamValue($param, 'enableAiRewrite', $originalConfig->enableAiRewrite ?? 0));
$aiRewritePrompt = trim((string)$this->getParamValue($param, 'aiRewritePrompt', $originalConfig->aiRewritePrompt ?? ''));
if ($enableAiRewrite === 1 && $aiRewritePrompt === '') {
throw new \Exception('启用AI智能话术改写时必须输入改写提示词');
}
$data['announcementContent'] = $announcementContent;
$data['enableAiRewrite'] = $enableAiRewrite;
$data['aiRewritePrompt'] = $aiRewritePrompt;
} else {
$data['groupPushSubType'] = 1;
$data['announcementContent'] = '';
$data['enableAiRewrite'] = 0;
$data['aiRewritePrompt'] = '';
}
} else {
$data['isLoop'] = 0;
$friendsExisting = $originalConfig ? $this->decodeJsonArray($originalConfig->friends ?? []) : [];
$trafficPoolsExisting = $originalConfig ? $this->decodeJsonArray($originalConfig->trafficPools ?? []) : [];
$friendTargets = array_key_exists('wechatFriends', $param)
? $this->extractIdList($param['wechatFriends'], '好友参数格式错误')
: $friendsExisting;
$trafficPools = array_key_exists('trafficPools', $param)
? $this->extractIdList($param['trafficPools'], '流量池参数格式错误')
: $trafficPoolsExisting;
if (empty($friendTargets) && empty($trafficPools)) {
throw new \Exception('好友推送需至少选择好友或流量池');
}
$data['friends'] = json_encode($friendTargets, JSON_UNESCAPED_UNICODE);
$data['trafficPools'] = json_encode($trafficPools, JSON_UNESCAPED_UNICODE);
$data['groups'] = json_encode([], JSON_UNESCAPED_UNICODE);
$data['groupPushSubType'] = 1;
$data['announcementContent'] = '';
$data['enableAiRewrite'] = 0;
$data['aiRewritePrompt'] = '';
}
return $data;
}
/**
* 获取参数值,若不存在则返回默认值
* @param array $param
* @param string $key
* @param mixed $default
* @return mixed
*/
private function getParamValue(array $param, string $key, $default)
{
return array_key_exists($key, $param) ? $param[$key] : $default;
}
/**
* 将值转换为整型布尔
* @param mixed $value
* @return int
*/
private function toBoolInt($value): int
{
return empty($value) ? 0 : 1;
}
/**
* 从参数中提取ID列表
* @param mixed $items
* @param string $errorMessage
* @return array
* @throws \Exception
*/
private function extractIdList($items, string $errorMessage = '参数格式错误'): array
{
if (!is_array($items)) {
throw new \Exception($errorMessage);
}
$ids = [];
foreach ($items as $item) {
if (is_array($item) && isset($item['id'])) {
$item = $item['id'];
}
if ($item === '' || $item === null) {
continue;
}
$ids[] = $item;
}
return array_values(array_unique($ids));
}
/**
* 解码JSON数组
* @param mixed $value
* @return array
*/
private function decodeJsonArray($value): array
{
if (empty($value)) {
return [];
}
if (is_array($value)) {
return $value;
}
$decoded = json_decode($value, true);
return is_array($decoded) ? $decoded : [];
}
2025-09-02 11:24:23 +08:00
/**
* 验证内容是否包含链接
* @param string $content 要检测的内容
* @return bool
*/
private function containsLink($content)
{
// 定义各种链接的正则表达式模式
$patterns = [
// HTTP/HTTPS链接
'/https?:\/\/[^\s]+/i',
// 京东商品链接
'/item\.jd\.com\/\d+/i',
// 京东短链接
'/u\.jd\.com\/[a-zA-Z0-9]+/i',
// 淘宝商品链接
'/item\.taobao\.com\/item\.htm\?id=\d+/i',
// 天猫商品链接
'/detail\.tmall\.com\/item\.htm\?id=\d+/i',
// 淘宝短链接
'/m\.tb\.cn\/[a-zA-Z0-9]+/i',
// 拼多多链接
'/mobile\.yangkeduo\.com\/goods\.html\?goods_id=\d+/i',
// 苏宁易购链接
'/product\.suning\.com\/\d+\/\d+\.html/i',
// 通用域名模式(包含常见电商域名)
'/(?:jd|taobao|tmall|yangkeduo|suning|amazon|dangdang)\.com[^\s]*/i',
// 通用短链接模式
'/[a-zA-Z0-9-]+\.[a-zA-Z]{2,}\/[a-zA-Z0-9\-._~:\/?#\[\]@!$&\'()*+,;=]+/i'
];
2025-11-13 16:10:47 +08:00
2025-09-02 11:24:23 +08:00
// 遍历所有模式进行匹配
foreach ($patterns as $pattern) {
if (preg_match($pattern, $content)) {
return true;
}
}
2025-11-13 16:10:47 +08:00
2025-09-02 11:24:23 +08:00
return false;
}
2025-09-12 10:25:19 +08:00
/**
* 获取通讯录导入记录列表
* @return \think\response\Json
*/
public function getImportContact()
{
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$workbenchId = $this->request->param('workbenchId', 0);
$where = [
['wici.workbenchId', '=', $workbenchId]
];
// 查询发布记录
$list = Db::name('workbench_import_contact_item')->alias('wici')
->join('traffic_pool tp', 'tp.id = wici.poolId', 'left')
->join('traffic_source tc', 'tc.identifier = tp.identifier', 'left')
->join('wechat_account wa', 'wa.wechatId = tp.wechatId', 'left')
->field([
'wici.id',
'wici.workbenchId',
'wici.createTime',
'tp.identifier',
'tp.mobile',
'tp.wechatId',
'tc.name',
'wa.nickName',
'wa.avatar',
'wa.alias',
])
->where($where)
->order('tc.name DESC,wici.createTime DESC')
->group('tp.identifier')
->page($page, $limit)
->select();
foreach ($list as &$item) {
$item['createTime'] = date('Y-m-d H:i:s', $item['createTime']);
}
// 获取总记录数
$total = Db::name('workbench_import_contact_item')->alias('wici')
->where($where)
->count();
return json([
'code' => 200,
'msg' => '获取成功',
'data' => [
'list' => $list,
'total' => $total,
]
]);
}
2025-11-13 16:10:47 +08:00
/**
* 获取群发统计数据
* @return \think\response\Json
*/
public function getGroupPushStats()
{
$workbenchId = $this->request->param('workbenchId', 0);
$timeRange = $this->request->param('timeRange', '7'); // 默认最近7天
$contentLibraryIds = $this->request->param('contentLibraryIds', ''); // 话术组筛选
$userId = $this->request->userInfo['id'];
// 如果指定了工作台ID则验证权限
if (!empty($workbenchId)) {
$workbench = Workbench::where([
['id', '=', $workbenchId],
['userId', '=', $userId],
['type', '=', self::TYPE_GROUP_PUSH],
['isDel', '=', 0]
])->find();
if (empty($workbench)) {
return json(['code' => 404, 'msg' => '工作台不存在']);
}
}
// 计算时间范围
$days = intval($timeRange);
$startTime = strtotime(date('Y-m-d 00:00:00', strtotime("-{$days} days")));
$endTime = time();
// 构建查询条件
$where = [
['wgpi.createTime', '>=', $startTime],
['wgpi.createTime', '<=', $endTime]
];
// 如果指定了工作台ID则限制查询范围
if (!empty($workbenchId)) {
$where[] = ['wgpi.workbenchId', '=', $workbenchId];
} else {
// 如果没有指定工作台ID则查询当前用户的所有群推送工作台
$workbenchIds = Workbench::where([
['userId', '=', $userId],
['type', '=', self::TYPE_GROUP_PUSH],
['isDel', '=', 0]
])->column('id');
if (empty($workbenchIds)) {
// 如果没有工作台,返回空结果
$workbenchIds = [-1];
}
$where[] = ['wgpi.workbenchId', 'in', $workbenchIds];
}
// 话术组筛选 - 先获取符合条件的内容ID列表
$contentIds = null;
if (!empty($contentLibraryIds)) {
$libraryIds = is_array($contentLibraryIds) ? $contentLibraryIds : explode(',', $contentLibraryIds);
$libraryIds = array_filter(array_map('intval', $libraryIds));
if (!empty($libraryIds)) {
// 查询符合条件的内容ID
$contentIds = Db::name('content_item')
->whereIn('libraryId', $libraryIds)
->column('id');
if (empty($contentIds)) {
// 如果没有符合条件的内容,返回空结果
$contentIds = [-1]; // 使用不存在的ID确保查询结果为空
}
}
}
// 1. 基础统计:触达率、回复率、平均回复时间、链接点击率
$stats = $this->calculateBasicStats($workbenchId, $where, $startTime, $endTime, $contentIds);
// 2. 话术组对比
$contentLibraryComparison = $this->getContentLibraryComparison($workbenchId, $where, $startTime, $endTime, $contentIds);
// 3. 时段分析
$timePeriodAnalysis = $this->getTimePeriodAnalysis($workbenchId, $where, $startTime, $endTime, $contentIds);
// 4. 互动深度(可选,需要更多数据)
$interactionDepth = $this->getInteractionDepth($workbenchId, $where, $startTime, $endTime, $contentIds);
return json([
'code' => 200,
'msg' => '获取成功',
'data' => [
'basicStats' => $stats,
'contentLibraryComparison' => $contentLibraryComparison,
'timePeriodAnalysis' => $timePeriodAnalysis,
'interactionDepth' => $interactionDepth
]
]);
}
/**
* 计算基础统计数据
*/
private function calculateBasicStats($workbenchId, $where, $startTime, $endTime, $contentIds = null)
{
// 获取工作台配置,计算计划发送数
// 如果 workbenchId 为空,则查询所有工作台的配置
$configQuery = WorkbenchGroupPush::alias('wgp')
->join('workbench w', 'w.id = wgp.workbenchId', 'left')
->where('w.type', self::TYPE_GROUP_PUSH)
->where('w.isDel', 0);
if (!empty($workbenchId)) {
$configQuery->where('wgp.workbenchId', $workbenchId);
} else {
// 如果没有指定工作台ID需要从 where 条件中获取 workbenchId 列表
$workbenchIdCondition = null;
foreach ($where as $condition) {
if (is_array($condition) && isset($condition[0]) && $condition[0] === 'wgpi.workbenchId') {
if ($condition[1] === 'in' && is_array($condition[2])) {
$workbenchIdCondition = $condition[2];
break;
} elseif ($condition[1] === '=') {
$workbenchIdCondition = [$condition[2]];
break;
}
}
}
if ($workbenchIdCondition) {
$configQuery->whereIn('wgp.workbenchId', $workbenchIdCondition);
}
}
$configs = $configQuery->select();
$targetType = 1; // 默认值
if (!empty($configs)) {
// 如果只有一个配置,使用它的 targetType如果有多个默认使用1
$targetType = intval($configs[0]->targetType ?? 1);
}
// 计划发送数(根据配置计算)
$plannedSend = 0;
if (!empty($configs)) {
$days = ceil(($endTime - $startTime) / 86400);
foreach ($configs as $config) {
$maxPerDay = intval($config->maxPerDay ?? 0);
$configTargetType = intval($config->targetType ?? 1);
if ($configTargetType == 1) {
// 群推送:计划发送数 = 每日推送次数 * 天数 * 群数量
$groups = $this->decodeJsonArray($config->groups ?? []);
$plannedSend += $maxPerDay * $days * count($groups);
} else {
// 好友推送:计划发送数 = 每日推送人数 * 天数
$plannedSend += $maxPerDay * $days;
}
}
}
// 构建查询条件
$queryWhere = $where;
if ($contentIds !== null) {
$queryWhere[] = ['wgpi.contentId', 'in', $contentIds];
}
// 实际成功发送数(从推送记录表统计)
$successSend = Db::name('workbench_group_push_item')
->alias('wgpi')
->where($queryWhere)
->count();
// 触达率 = 成功发送数 / 计划发送数
$reachRate = $plannedSend > 0 ? round(($successSend / $plannedSend) * 100, 1) : 0;
// 获取发送记录列表,用于查询回复
$sentItemIds = Db::name('workbench_group_push_item')
->alias('wgpi')
->where($queryWhere)
->field('wgpi.id, wgpi.groupId, wgpi.friendId, wgpi.wechatAccountId, wgpi.createTime, wgpi.targetType, wgpi.contentId')
->select();
// 回复统计(通过消息表查询)
$replyStats = $this->calculateReplyStats($sentItemIds, $targetType, $startTime, $endTime);
// 链接点击统计
$clickStats = $this->calculateClickStats($sentItemIds, $targetType, $startTime, $endTime);
// 计算本月对比数据(简化处理,实际应该查询上个月同期数据)
$currentMonthStart = strtotime(date('Y-m-01 00:00:00'));
$lastMonthStart = strtotime(date('Y-m-01 00:00:00', strtotime('-1 month')));
$lastMonthEnd = $currentMonthStart - 1;
// 获取本月统计数据(避免递归调用)
$currentMonthWhere = [
['wgpi.createTime', '>=', $currentMonthStart]
];
// 复制 workbenchId 条件
foreach ($where as $condition) {
if (is_array($condition) && isset($condition[0]) && $condition[0] === 'wgpi.workbenchId') {
$currentMonthWhere[] = $condition;
break;
}
}
if ($contentIds !== null) {
$currentMonthWhere[] = ['wgpi.contentId', 'in', $contentIds];
}
$currentMonthSend = Db::name('workbench_group_push_item')
->alias('wgpi')
->where($currentMonthWhere)
->count();
// 获取本月配置
$currentMonthConfigQuery = WorkbenchGroupPush::alias('wgp')
->join('workbench w', 'w.id = wgp.workbenchId', 'left')
->where('w.type', self::TYPE_GROUP_PUSH)
->where('w.isDel', 0);
if (!empty($workbenchId)) {
$currentMonthConfigQuery->where('wgp.workbenchId', $workbenchId);
} else {
foreach ($where as $condition) {
if (is_array($condition) && isset($condition[0]) && $condition[0] === 'wgpi.workbenchId' && $condition[1] === 'in') {
$currentMonthConfigQuery->whereIn('wgp.workbenchId', $condition[2]);
break;
}
}
}
$currentMonthConfigs = $currentMonthConfigQuery->select();
$currentMonthPlanned = 0;
if (!empty($currentMonthConfigs)) {
$currentMonthDays = ceil(($endTime - $currentMonthStart) / 86400);
foreach ($currentMonthConfigs as $currentMonthConfig) {
$currentMonthMaxPerDay = intval($currentMonthConfig->maxPerDay ?? 0);
$currentMonthTargetType = intval($currentMonthConfig->targetType ?? 1);
if ($currentMonthTargetType == 1) {
$currentMonthGroups = $this->decodeJsonArray($currentMonthConfig->groups ?? []);
$currentMonthPlanned += $currentMonthMaxPerDay * $currentMonthDays * count($currentMonthGroups);
} else {
$currentMonthPlanned += $currentMonthMaxPerDay * $currentMonthDays;
}
}
}
$currentMonthReachRate = $currentMonthPlanned > 0 ? round(($currentMonthSend / $currentMonthPlanned) * 100, 1) : 0;
// 获取上个月统计数据
$lastMonthWhere = [
['wgpi.createTime', '>=', $lastMonthStart],
['wgpi.createTime', '<=', $lastMonthEnd]
];
// 复制 workbenchId 条件
foreach ($where as $condition) {
if (is_array($condition) && isset($condition[0]) && $condition[0] === 'wgpi.workbenchId') {
$lastMonthWhere[] = $condition;
break;
}
}
if ($contentIds !== null) {
$lastMonthWhere[] = ['wgpi.contentId', 'in', $contentIds];
}
$lastMonthSend = Db::name('workbench_group_push_item')
->alias('wgpi')
->where($lastMonthWhere)
->count();
// 获取上个月配置
$lastMonthConfigQuery = WorkbenchGroupPush::alias('wgp')
->join('workbench w', 'w.id = wgp.workbenchId', 'left')
->where('w.type', self::TYPE_GROUP_PUSH)
->where('w.isDel', 0);
if (!empty($workbenchId)) {
$lastMonthConfigQuery->where('wgp.workbenchId', $workbenchId);
} else {
foreach ($where as $condition) {
if (is_array($condition) && isset($condition[0]) && $condition[0] === 'wgpi.workbenchId' && $condition[1] === 'in') {
$lastMonthConfigQuery->whereIn('wgp.workbenchId', $condition[2]);
break;
}
}
}
$lastMonthConfigs = $lastMonthConfigQuery->select();
$lastMonthPlanned = 0;
if (!empty($lastMonthConfigs)) {
$lastMonthDays = ceil(($lastMonthEnd - $lastMonthStart) / 86400);
foreach ($lastMonthConfigs as $lastMonthConfig) {
$lastMonthMaxPerDay = intval($lastMonthConfig->maxPerDay ?? 0);
$lastMonthTargetType = intval($lastMonthConfig->targetType ?? 1);
if ($lastMonthTargetType == 1) {
$lastMonthGroups = $this->decodeJsonArray($lastMonthConfig->groups ?? []);
$lastMonthPlanned += $lastMonthMaxPerDay * $lastMonthDays * count($lastMonthGroups);
} else {
$lastMonthPlanned += $lastMonthMaxPerDay * $lastMonthDays;
}
}
}
$lastMonthReachRate = $lastMonthPlanned > 0 ? round(($lastMonthSend / $lastMonthPlanned) * 100, 1) : 0;
// 获取上个月的回复和点击统计(简化处理)
$lastMonthSentItems = Db::name('workbench_group_push_item')
->alias('wgpi')
->where($lastMonthWhere)
->field('wgpi.id, wgpi.groupId, wgpi.friendId, wgpi.wechatAccountId, wgpi.createTime, wgpi.targetType, wgpi.contentId')
->select();
$lastMonthReplyStats = $this->calculateReplyStats($lastMonthSentItems, $targetType, $lastMonthStart, $lastMonthEnd);
$lastMonthClickStats = $this->calculateClickStats($lastMonthSentItems, $targetType, $lastMonthStart, $lastMonthEnd);
return [
'reachRate' => [
'value' => $reachRate,
'trend' => round($reachRate - $lastMonthReachRate, 1),
'unit' => '%',
'description' => '成功发送/计划发送'
],
'replyRate' => [
'value' => $replyStats['replyRate'],
'trend' => round($replyStats['replyRate'] - $lastMonthReplyStats['replyRate'], 1),
'unit' => '%',
'description' => '收到回复/成功发送'
],
'avgReplyTime' => [
'value' => $replyStats['avgReplyTime'],
'trend' => round($lastMonthReplyStats['avgReplyTime'] - $replyStats['avgReplyTime'], 0),
'unit' => '分钟',
'description' => '从发送到回复的平均时长'
],
'clickRate' => [
'value' => $clickStats['clickRate'],
'trend' => round($clickStats['clickRate'] - $lastMonthClickStats['clickRate'], 1),
'unit' => '%',
'description' => '点击链接/成功发送'
],
'plannedSend' => $plannedSend,
'successSend' => $successSend,
'replyCount' => $replyStats['replyCount'],
'clickCount' => $clickStats['clickCount']
];
}
/**
* 计算回复统计
*/
private function calculateReplyStats($sentItems, $targetType, $startTime, $endTime)
{
if (empty($sentItems)) {
return ['replyRate' => 0, 'avgReplyTime' => 0, 'replyCount' => 0];
}
$replyCount = 0;
$totalReplyTime = 0;
$replyTimes = [];
foreach ($sentItems as $item) {
$itemArray = is_array($item) ? $item : (array)$item;
$sendTime = $itemArray['createTime'] ?? 0;
$accountId = $itemArray['wechatAccountId'] ?? 0;
if ($targetType == 1) {
// 群推送:查找群内回复消息
$groupId = $itemArray['groupId'] ?? 0;
$group = Db::name('wechat_group')->where('id', $groupId)->find();
if ($group) {
$replyMsg = Db::table('s2_wechat_message')
->where('wechatChatroomId', $group['chatroomId'])
->where('wechatAccountId', $accountId)
->where('isSend', 0) // 接收的消息
->where('wechatTime', '>', $sendTime)
->where('wechatTime', '<=', $sendTime + 86400) // 24小时内回复
->order('wechatTime', 'asc')
->find();
if ($replyMsg) {
$replyCount++;
$replyTime = $replyMsg['wechatTime'] - $sendTime;
$replyTimes[] = $replyTime;
$totalReplyTime += $replyTime;
}
}
} else {
// 好友推送:查找好友回复消息
$friendId = $itemArray['friendId'] ?? 0;
$friend = Db::table('s2_wechat_friend')->where('id', $friendId)->find();
if ($friend) {
$replyMsg = Db::table('s2_wechat_message')
->where('wechatFriendId', $friendId)
->where('wechatAccountId', $accountId)
->where('isSend', 0) // 接收的消息
->where('wechatTime', '>', $sendTime)
->where('wechatTime', '<=', $sendTime + 86400) // 24小时内回复
->order('wechatTime', 'asc')
->find();
if ($replyMsg) {
$replyCount++;
$replyTime = $replyMsg['wechatTime'] - $sendTime;
$replyTimes[] = $replyTime;
$totalReplyTime += $replyTime;
}
}
}
}
$successSend = count($sentItems);
$replyRate = $successSend > 0 ? round(($replyCount / $successSend) * 100, 1) : 0;
$avgReplyTime = $replyCount > 0 ? round(($totalReplyTime / $replyCount) / 60, 0) : 0; // 转换为分钟
return [
'replyRate' => $replyRate,
'avgReplyTime' => $avgReplyTime,
'replyCount' => $replyCount
];
}
/**
* 计算链接点击统计
*/
private function calculateClickStats($sentItems, $targetType, $startTime, $endTime)
{
if (empty($sentItems)) {
return ['clickRate' => 0, 'clickCount' => 0];
}
$clickCount = 0;
$linkContentIds = [];
// 获取所有发送的内容ID
foreach ($sentItems as $item) {
$itemArray = is_array($item) ? $item : (array)$item;
$contentId = $itemArray['contentId'] ?? 0;
if ($contentId > 0) {
$linkContentIds[] = $contentId;
}
}
if (empty($linkContentIds)) {
return ['clickRate' => 0, 'clickCount' => 0];
}
// 查询包含链接的内容
$linkContents = Db::name('content_item')
->whereIn('id', array_unique($linkContentIds))
->where('contentType', 2) // 链接类型
->column('id');
// 统计发送了链接内容的记录数
$linkSendCount = 0;
foreach ($sentItems as $item) {
$itemArray = is_array($item) ? $item : (array)$item;
$contentId = $itemArray['contentId'] ?? 0;
if (in_array($contentId, $linkContents)) {
$linkSendCount++;
}
}
// 简化处理:假设点击率基于链接消息的发送(实际应该从点击追踪系统获取)
// 这里可以根据业务需求调整,比如通过消息中的链接点击事件统计
$clickCount = $linkSendCount; // 简化处理,实际需要真实的点击数据
$successSend = count($sentItems);
$clickRate = $successSend > 0 ? round(($clickCount / $successSend) * 100, 1) : 0;
return [
'clickRate' => $clickRate,
'clickCount' => $clickCount
];
}
/**
* 获取话术组对比数据
*/
private function getContentLibraryComparison($workbenchId, $where, $startTime, $endTime, $contentIds = null)
{
$queryWhere = $where;
if ($contentIds !== null) {
$queryWhere[] = ['wgpi.contentId', 'in', $contentIds];
}
$comparison = Db::name('workbench_group_push_item')
->alias('wgpi')
->join('content_item ci', 'ci.id = wgpi.contentId', 'left')
->join('content_library cl', 'cl.id = ci.libraryId', 'left')
->where($queryWhere)
->where('cl.id', '<>', null)
->field([
'cl.id as libraryId',
'cl.name as libraryName',
'COUNT(DISTINCT wgpi.id) as pushCount'
])
->group('cl.id, cl.name')
->select();
$result = [];
foreach ($comparison as $item) {
$libraryId = $item['libraryId'];
$pushCount = intval($item['pushCount']);
// 获取该内容库的详细统计
$libraryContentIds = Db::name('content_item')
->where('libraryId', $libraryId)
->column('id');
if (empty($libraryContentIds)) {
$libraryContentIds = [-1];
}
$libraryWhere = array_merge($where, [['wgpi.contentId', 'in', $libraryContentIds]]);
$librarySentItems = Db::name('workbench_group_push_item')
->alias('wgpi')
->where($libraryWhere)
->field('wgpi.id, wgpi.groupId, wgpi.friendId, wgpi.wechatAccountId, wgpi.createTime, wgpi.targetType, wgpi.contentId')
->select();
$config = WorkbenchGroupPush::where('workbenchId', $workbenchId)->find();
$targetType = $config ? intval($config->targetType) : 1;
$replyStats = $this->calculateReplyStats($librarySentItems, $targetType, $startTime, $endTime);
$clickStats = $this->calculateClickStats($librarySentItems, $targetType, $startTime, $endTime);
// 计算转化率(简化处理,实际需要根据业务定义)
$conversionRate = $pushCount > 0 ? round(($replyStats['replyCount'] / $pushCount) * 100, 1) : 0;
$result[] = [
'libraryId' => $libraryId,
'libraryName' => $item['libraryName'],
'pushCount' => $pushCount,
'reachRate' => 100, // 简化处理,实际应该计算
'replyRate' => $replyStats['replyRate'],
'clickRate' => $clickStats['clickRate'],
'conversionRate' => $conversionRate,
'avgReplyTime' => $replyStats['avgReplyTime'],
'level' => $this->getPerformanceLevel($replyStats['replyRate'], $clickStats['clickRate'], $conversionRate)
];
}
// 按回复率排序
usort($result, function($a, $b) {
return $b['replyRate'] <=> $a['replyRate'];
});
return $result;
}
/**
* 获取性能等级
*/
private function getPerformanceLevel($replyRate, $clickRate, $conversionRate)
{
$score = ($replyRate * 0.4) + ($clickRate * 0.3) + ($conversionRate * 0.3);
if ($score >= 40) {
return '优秀';
} elseif ($score >= 25) {
return '良好';
} elseif ($score >= 15) {
return '一般';
} else {
return '待提升';
}
}
/**
* 获取时段分析数据
*/
private function getTimePeriodAnalysis($workbenchId, $where, $startTime, $endTime, $contentIds = null)
{
$queryWhere = $where;
if ($contentIds !== null) {
$queryWhere[] = ['wgpi.contentId', 'in', $contentIds];
}
$analysis = Db::name('workbench_group_push_item')
->alias('wgpi')
->where($queryWhere)
->field([
'FROM_UNIXTIME(wgpi.createTime, "%H") as hour',
'COUNT(*) as count'
])
->group('hour')
->order('hour', 'asc')
->select();
$result = [];
foreach ($analysis as $item) {
$result[] = [
'hour' => intval($item['hour']),
'count' => intval($item['count'])
];
}
return $result;
}
/**
* 获取互动深度数据
*/
private function getInteractionDepth($workbenchId, $where, $startTime, $endTime, $contentIds = null)
{
// 简化处理,实际需要更复杂的统计逻辑
return [
'singleReply' => 0, // 单次回复
'multipleReply' => 0, // 多次回复
'deepInteraction' => 0 // 深度互动
];
}
/**
* 获取推送历史记录列表
* @return \think\response\Json
*/
public function getGroupPushHistory()
{
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$workbenchId = $this->request->param('workbenchId', 0);
$keyword = $this->request->param('keyword', '');
2025-11-20 16:07:57 +08:00
$pushType = $this->request->param('pushType', ''); // 推送类型筛选:''=全部, 'friend'=好友消息, 'group'=群消息, 'announcement'=群公告
$status = $this->request->param('status', ''); // 状态筛选:''=全部, 'success'=已完成, 'progress'=进行中, 'failed'=失败
2025-11-13 16:10:47 +08:00
$userId = $this->request->userInfo['id'];
// 构建工作台查询条件
$workbenchWhere = [
['w.userId', '=', $userId],
['w.type', '=', self::TYPE_GROUP_PUSH],
['w.isDel', '=', 0]
];
// 如果指定了工作台ID则验证权限并限制查询范围
if (!empty($workbenchId)) {
$workbench = Workbench::where([
['id', '=', $workbenchId],
['userId', '=', $userId],
['type', '=', self::TYPE_GROUP_PUSH],
['isDel', '=', 0]
])->find();
if (empty($workbench)) {
return json(['code' => 404, 'msg' => '工作台不存在']);
}
$workbenchWhere[] = ['w.id', '=', $workbenchId];
}
2025-11-20 16:07:57 +08:00
// 1. 先查询所有已执行的推送记录(按推送时间分组)
$pushHistoryQuery = Db::name('workbench_group_push_item')
2025-11-13 16:10:47 +08:00
->alias('wgpi')
->join('workbench w', 'w.id = wgpi.workbenchId', 'left')
2025-11-20 16:07:57 +08:00
->join('workbench_group_push wgp', 'wgp.workbenchId = wgpi.workbenchId', 'left')
2025-11-13 16:10:47 +08:00
->join('content_item ci', 'ci.id = wgpi.contentId', 'left')
->join('content_library cl', 'cl.id = ci.libraryId', 'left')
->where($workbenchWhere)
->field([
'wgpi.workbenchId',
'w.name as workbenchName',
'wgpi.contentId',
'FROM_UNIXTIME(wgpi.createTime, "%Y-%m-%d %H:00:00") as pushTime',
'wgpi.targetType',
2025-11-20 16:07:57 +08:00
'wgp.groupPushSubType',
2025-11-13 16:10:47 +08:00
'MIN(wgpi.createTime) as createTime',
'COUNT(DISTINCT wgpi.id) as totalCount',
'cl.name as contentLibraryName'
])
2025-11-20 16:07:57 +08:00
->group('wgpi.workbenchId, wgpi.contentId, pushTime, wgpi.targetType, wgp.groupPushSubType');
2025-11-13 16:10:47 +08:00
if (!empty($keyword)) {
2025-11-20 16:07:57 +08:00
$pushHistoryQuery->where('w.name|cl.name|ci.content', 'like', '%' . $keyword . '%');
2025-11-13 16:10:47 +08:00
}
2025-11-20 16:07:57 +08:00
$pushHistoryList = $pushHistoryQuery->order('createTime', 'desc')->select();
// 2. 查询所有任务(包括未执行的)
$allTasksQuery = Db::name('workbench')
->alias('w')
->join('workbench_group_push wgp', 'wgp.workbenchId = w.id', 'left')
->where($workbenchWhere)
->field([
'w.id as workbenchId',
'w.name as workbenchName',
'w.createTime',
'wgp.targetType',
'wgp.groupPushSubType',
'wgp.groups',
'wgp.friends',
'wgp.trafficPools'
]);
2025-11-13 16:10:47 +08:00
if (!empty($keyword)) {
2025-11-20 16:07:57 +08:00
$allTasksQuery->where('w.name', 'like', '%' . $keyword . '%');
2025-11-13 16:10:47 +08:00
}
2025-11-20 16:07:57 +08:00
$allTasks = $allTasksQuery->select();
// 3. 合并数据:已执行的推送记录 + 未执行的任务
$resultList = [];
$executedWorkbenchIds = [];
// 处理已执行的推送记录
foreach ($pushHistoryList as $item) {
2025-11-13 16:10:47 +08:00
$itemWorkbenchId = $item['workbenchId'];
$contentId = $item['contentId'];
$pushTime = $item['pushTime'];
$targetType = intval($item['targetType']);
2025-11-20 16:07:57 +08:00
$groupPushSubType = isset($item['groupPushSubType']) ? intval($item['groupPushSubType']) : 1;
// 标记该工作台已有执行记录
if (!in_array($itemWorkbenchId, $executedWorkbenchIds)) {
$executedWorkbenchIds[] = $itemWorkbenchId;
}
2025-11-13 16:10:47 +08:00
// 将时间字符串转换为时间戳范围(小时级别)
$pushTimeStart = strtotime($pushTime);
$pushTimeEnd = $pushTimeStart + 3600; // 一小时后
// 获取该次推送的详细统计
$pushWhere = [
['wgpi.workbenchId', '=', $itemWorkbenchId],
['wgpi.contentId', '=', $contentId],
['wgpi.createTime', '>=', $pushTimeStart],
['wgpi.createTime', '<', $pushTimeEnd],
['wgpi.targetType', '=', $targetType]
];
// 目标数量
if ($targetType == 1) {
// 群推送:统计群数量
$targetCount = Db::name('workbench_group_push_item')
->alias('wgpi')
->where($pushWhere)
->where('wgpi.groupId', '<>', null)
->distinct(true)
->count('wgpi.groupId');
} else {
// 好友推送:统计好友数量
$targetCount = Db::name('workbench_group_push_item')
->alias('wgpi')
->where($pushWhere)
->where('wgpi.friendId', '<>', null)
->distinct(true)
->count('wgpi.friendId');
}
// 成功数和失败数(简化处理,实际需要根据发送状态判断)
$successCount = intval($item['totalCount']); // 简化处理
$failCount = 0; // 简化处理,实际需要从发送状态获取
// 状态判断
2025-11-20 16:07:57 +08:00
$itemStatus = $successCount > 0 ? 'success' : 'failed';
2025-11-13 16:10:47 +08:00
if ($failCount > 0 && $successCount > 0) {
2025-11-20 16:07:57 +08:00
$itemStatus = 'partial';
2025-11-13 16:10:47 +08:00
}
2025-11-20 16:07:57 +08:00
// 推送类型判断
$pushTypeText = '';
$pushTypeCode = '';
if ($targetType == 1) {
// 群推送
if ($groupPushSubType == 2) {
$pushTypeText = '群公告';
$pushTypeCode = 'announcement';
} else {
$pushTypeText = '群消息';
$pushTypeCode = 'group';
}
} else {
// 好友推送
$pushTypeText = '好友消息';
$pushTypeCode = 'friend';
}
$resultList[] = [
'workbenchId' => $itemWorkbenchId,
'taskName' => $item['workbenchName'] ?? '',
'pushType' => $pushTypeText,
'pushTypeCode' => $pushTypeCode,
'targetCount' => $targetCount,
'successCount' => $successCount,
'failCount' => $failCount,
'status' => $itemStatus,
'statusText' => $this->getStatusText($itemStatus),
'createTime' => date('Y-m-d H:i:s', $item['createTime']),
'contentLibraryName' => $item['contentLibraryName'] ?? ''
];
2025-11-13 16:10:47 +08:00
}
2025-11-20 16:07:57 +08:00
// 处理未执行的任务
foreach ($allTasks as $task) {
$taskWorkbenchId = $task['workbenchId'];
// 如果该任务已有执行记录,跳过(避免重复)
if (in_array($taskWorkbenchId, $executedWorkbenchIds)) {
continue;
}
$targetType = isset($task['targetType']) ? intval($task['targetType']) : 1;
$groupPushSubType = isset($task['groupPushSubType']) ? intval($task['groupPushSubType']) : 1;
// 计算目标数量(从配置中获取)
$targetCount = 0;
if ($targetType == 1) {
// 群推送:统计配置的群数量
$groups = json_decode($task['groups'] ?? '[]', true);
$targetCount = is_array($groups) ? count($groups) : 0;
} else {
// 好友推送:统计配置的好友数量或流量池数量
$friends = json_decode($task['friends'] ?? '[]', true);
$trafficPools = json_decode($task['trafficPools'] ?? '[]', true);
$friendCount = is_array($friends) ? count($friends) : 0;
$poolCount = is_array($trafficPools) ? count($trafficPools) : 0;
// 如果配置了流量池,目标数量暂时显示为流量池数量(实际数量需要从流量池中统计)
$targetCount = $friendCount > 0 ? $friendCount : $poolCount;
}
// 推送类型判断
$pushTypeText = '';
$pushTypeCode = '';
if ($targetType == 1) {
// 群推送
if ($groupPushSubType == 2) {
$pushTypeText = '群公告';
$pushTypeCode = 'announcement';
} else {
$pushTypeText = '群消息';
$pushTypeCode = 'group';
}
} else {
// 好友推送
$pushTypeText = '好友消息';
$pushTypeCode = 'friend';
}
$resultList[] = [
'workbenchId' => $taskWorkbenchId,
'taskName' => $task['workbenchName'] ?? '',
'pushType' => $pushTypeText,
'pushTypeCode' => $pushTypeCode,
'targetCount' => $targetCount,
'successCount' => 0,
'failCount' => 0,
'status' => 'pending',
'statusText' => '进行中',
'createTime' => date('Y-m-d H:i:s', $task['createTime']),
'contentLibraryName' => ''
];
}
// 应用筛选条件
$filteredList = [];
foreach ($resultList as $item) {
// 推送类型筛选
if (!empty($pushType)) {
if ($pushType === 'friend' && $item['pushTypeCode'] !== 'friend') {
continue;
}
if ($pushType === 'group' && $item['pushTypeCode'] !== 'group') {
continue;
}
if ($pushType === 'announcement' && $item['pushTypeCode'] !== 'announcement') {
continue;
}
}
// 状态筛选
if (!empty($status)) {
if ($status === 'success' && $item['status'] !== 'success') {
continue;
}
if ($status === 'progress') {
// 进行中:包括 partial 和 pending
if ($item['status'] !== 'partial' && $item['status'] !== 'pending') {
continue;
}
}
if ($status === 'failed' && $item['status'] !== 'failed') {
continue;
}
}
$filteredList[] = $item;
}
// 按创建时间倒序排序
usort($filteredList, function($a, $b) {
return strtotime($b['createTime']) - strtotime($a['createTime']);
});
// 分页处理
$total = count($filteredList);
$offset = ($page - 1) * $limit;
$list = array_slice($filteredList, $offset, $limit);
2025-11-13 16:10:47 +08:00
return json([
'code' => 200,
'msg' => '获取成功',
'data' => [
'list' => $list,
'total' => $total,
'page' => $page,
'limit' => $limit
]
]);
}
2025-11-20 16:07:57 +08:00
/**
* 获取状态文本
* @param string $status 状态码
* @return string 状态文本
*/
private function getStatusText($status)
{
$statusMap = [
'success' => '已完成',
'partial' => '进行中',
'pending' => '进行中',
'failed' => '失败'
];
return $statusMap[$status] ?? '未知';
}
2025-09-12 10:25:19 +08:00
2025-08-12 09:28:57 +08:00
}