1、新增一个所有好友的流量池
2、旧版场景获客数据迁移 3、场景获客功能兼容旧版数据
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,3 +14,4 @@ Cunkebao/dist
|
||||
Touchkebao/.specstory/
|
||||
Serverruntime/
|
||||
Moncter/提示词/
|
||||
*.log
|
||||
|
||||
@@ -7,5 +7,5 @@ export function fetchTrafficPoolList(params: {
|
||||
keyword?: string;
|
||||
packageId?: string;
|
||||
}) {
|
||||
return request("/v1/traffic/pool/users", params, "GET");
|
||||
return request("/v1/traffic/pool/user-list", params, "GET");
|
||||
}
|
||||
|
||||
@@ -63,12 +63,13 @@ Route::group('v1/', function () {
|
||||
|
||||
// 流量池相关
|
||||
Route::group('traffic/pool', function () {
|
||||
Route::get('getPackage', 'app\cunkebao\controller\TrafficController@getPackage');
|
||||
Route::get('getPackage', 'app\cunkebao\controller\TrafficController@getPackage'); // 获取流量池包列表
|
||||
Route::get('getPackageDetail', 'app\cunkebao\controller\TrafficController@getPackageDetail'); // 获取流量池详情(元数据)
|
||||
Route::post('addPackage', 'app\cunkebao\controller\TrafficController@addPackage');
|
||||
Route::post('editPackage', 'app\cunkebao\controller\TrafficController@editPackage');
|
||||
Route::delete('deletePackage', 'app\cunkebao\controller\TrafficController@deletePackage');
|
||||
|
||||
Route::get('', 'app\cunkebao\controller\TrafficController@getTrafficPoolList');
|
||||
Route::get('user-list', 'app\cunkebao\controller\TrafficController@getTrafficPoolList'); // 获取流量池用户列表(数据列表)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,41 @@ class TrafficController extends BaseController
|
||||
$list = $package->page($page, $limit)->order('isSys ASC,id DESC')->select();
|
||||
$total = $package->count();
|
||||
|
||||
// 添加"所有好友"特殊流量池(ID为0)
|
||||
$allFriendsPackage = [
|
||||
'id' => 0,
|
||||
'name' => '所有好友',
|
||||
'description' => '展示公司下所有设备的好友',
|
||||
'pic' => '',
|
||||
'type' => 1, // 系统类型
|
||||
'createTime' => '',
|
||||
'num' => 0, // 数量将在下面计算
|
||||
];
|
||||
|
||||
// 计算所有好友数量
|
||||
try {
|
||||
$companyId = $this->getUserInfo('companyId');
|
||||
$wechatIds = Db::name('device')->alias('d')
|
||||
->join('(SELECT MAX(id) AS id, deviceId FROM ck_device_wechat_login WHERE companyId='.$companyId.' GROUP BY deviceId) dwl_max', 'dwl_max.deviceId = d.id')
|
||||
->join('device_wechat_login dwl', 'dwl.id = dwl_max.id')
|
||||
->where(['d.companyId' => $companyId, 'd.deleteTime' => 0])
|
||||
->column('dwl.wechatId');
|
||||
|
||||
if (!empty($wechatIds)) {
|
||||
$allFriendsCount = Db::table('s2_wechat_friend')
|
||||
->where('ownerWechatId', 'in', $wechatIds)
|
||||
->where('isDeleted', 0)
|
||||
->count();
|
||||
$allFriendsPackage['num'] = $allFriendsCount;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// 如果查询失败,保持num为0
|
||||
}
|
||||
|
||||
// 将"所有好友"添加到列表最前面
|
||||
array_unshift($list, $allFriendsPackage);
|
||||
$total = $total + 1; // 总数加1
|
||||
|
||||
$rfmRule = 'default';
|
||||
foreach ($list as $k => &$v) {
|
||||
if ($v['type'] != 1) {
|
||||
@@ -132,6 +167,11 @@ class TrafficController extends BaseController
|
||||
return ResponseHelper::error('流量池ID不能为空');
|
||||
}
|
||||
|
||||
// 禁止编辑"所有好友"特殊流量池
|
||||
if ($packageId === '0' || $packageId === 0) {
|
||||
return ResponseHelper::error('"所有好友"流量池不允许编辑');
|
||||
}
|
||||
|
||||
if (empty($packageName)) {
|
||||
return ResponseHelper::error('流量池名称不能为空');
|
||||
}
|
||||
@@ -194,6 +234,11 @@ class TrafficController extends BaseController
|
||||
return ResponseHelper::error('流量池ID不能为空');
|
||||
}
|
||||
|
||||
// 禁止删除"所有好友"特殊流量池
|
||||
if ($packageId === '0' || $packageId === 0) {
|
||||
return ResponseHelper::error('"所有好友"流量池不允许删除');
|
||||
}
|
||||
|
||||
// 检查流量池是否存在且属于当前公司
|
||||
$package = TrafficSourcePackage::where(['id' => $packageId, 'isDel' => 0])
|
||||
->whereIn('companyId', [$companyId, 0])
|
||||
@@ -243,6 +288,87 @@ class TrafficController extends BaseController
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取流量池详情
|
||||
* @return \think\response\Json
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getPackageDetail()
|
||||
{
|
||||
$packageId = $this->request->param('packageId', '');
|
||||
$companyId = $this->getUserInfo('companyId');
|
||||
|
||||
if (empty($packageId) && $packageId !== '0' && $packageId !== 0) {
|
||||
return ResponseHelper::error('流量池ID不能为空');
|
||||
}
|
||||
|
||||
// 特殊处理:packageId为0时,返回"所有好友"的详情
|
||||
if ($packageId === '0' || $packageId === 0) {
|
||||
$data = [
|
||||
'id' => 0,
|
||||
'name' => '所有好友',
|
||||
'description' => '展示公司下所有设备的好友',
|
||||
'pic' => '',
|
||||
'type' => 1, // 系统类型
|
||||
'isSys' => 1,
|
||||
'createTime' => '',
|
||||
'updateTime' => '',
|
||||
'num' => 0,
|
||||
];
|
||||
|
||||
// 计算所有好友数量
|
||||
try {
|
||||
$wechatIds = Db::name('device')->alias('d')
|
||||
->join('(SELECT MAX(id) AS id, deviceId FROM ck_device_wechat_login WHERE companyId='.$companyId.' GROUP BY deviceId) dwl_max', 'dwl_max.deviceId = d.id')
|
||||
->join('device_wechat_login dwl', 'dwl.id = dwl_max.id')
|
||||
->where(['d.companyId' => $companyId, 'd.deleteTime' => 0])
|
||||
->column('dwl.wechatId');
|
||||
|
||||
if (!empty($wechatIds)) {
|
||||
$allFriendsCount = Db::table('s2_wechat_friend')
|
||||
->where('ownerWechatId', 'in', $wechatIds)
|
||||
->where('isDeleted', 0)
|
||||
->count();
|
||||
$data['num'] = $allFriendsCount;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// 如果查询失败,保持num为0
|
||||
}
|
||||
|
||||
return ResponseHelper::success($data);
|
||||
}
|
||||
|
||||
// 查询普通流量池详情
|
||||
$package = TrafficSourcePackage::where(['id' => $packageId, 'isDel' => 0])
|
||||
->whereIn('companyId', [$companyId, 0])
|
||||
->find();
|
||||
|
||||
if (empty($package)) {
|
||||
return ResponseHelper::error('流量池不存在或已删除');
|
||||
}
|
||||
|
||||
// 统计流量池中的数量
|
||||
$itemCount = TrafficSourcePackageItem::where([
|
||||
'packageId' => $packageId,
|
||||
'companyId' => $companyId,
|
||||
'isDel' => 0
|
||||
])->count();
|
||||
|
||||
$data = [
|
||||
'id' => $package['id'],
|
||||
'name' => $package['name'],
|
||||
'description' => $package['description'] ?? '',
|
||||
'pic' => $package['pic'] ?? '',
|
||||
'type' => $package['isSys'] ?? 0,
|
||||
'isSys' => $package['isSys'] ?? 0,
|
||||
'createTime' => !empty($package['createTime']) ? formatRelativeTime($package['createTime']) : '',
|
||||
'updateTime' => !empty($package['updateTime']) ? formatRelativeTime($package['updateTime']) : '',
|
||||
'num' => $itemCount,
|
||||
];
|
||||
|
||||
return ResponseHelper::success($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 流量池列表
|
||||
* @return \think\response\Json
|
||||
@@ -257,10 +383,15 @@ class TrafficController extends BaseController
|
||||
$companyId = $this->getUserInfo('companyId');
|
||||
$userId = $this->getUserInfo('id');
|
||||
|
||||
if (empty($packageId)) {
|
||||
if (empty($packageId) && $packageId !== '0' && $packageId !== 0) {
|
||||
return ResponseHelper::error('流量包id不能为空');
|
||||
}
|
||||
|
||||
// 特殊处理:packageId为0时,查询所有好友
|
||||
if ($packageId === '0' || $packageId === 0) {
|
||||
return $this->getAllFriendsList($page, $limit, $keyword, $companyId);
|
||||
}
|
||||
|
||||
$trafficSourcePackage = TrafficSourcePackage::where(['id' => $packageId, 'isDel' => 0])->whereIn('companyId', [$companyId, 0])->find();
|
||||
if (empty($trafficSourcePackage)) {
|
||||
return ResponseHelper::error('流量包不存在或已删除');
|
||||
@@ -270,7 +401,7 @@ class TrafficController extends BaseController
|
||||
['tspi.packageId', '=', $packageId],
|
||||
];
|
||||
|
||||
if (empty($keyword)) {
|
||||
if (!empty($keyword)) {
|
||||
$where[] = ['wa.nickname|wa.phone|wa.alias|wa.wechatId|p.mobile|p.identifier', 'like', '%' . $keyword . '%'];
|
||||
}
|
||||
|
||||
@@ -287,7 +418,7 @@ class TrafficController extends BaseController
|
||||
|
||||
$query->order('tspi.id DESC,p.id DESC')->group('p.identifier');
|
||||
|
||||
$list = $query->page($page, $limit)->select()->toArray();
|
||||
$list = $query->page($page, $limit)->select();
|
||||
$total = $query->count();
|
||||
|
||||
foreach ($list as $k => &$v) {
|
||||
@@ -307,8 +438,8 @@ class TrafficController extends BaseController
|
||||
$v['F'] = $scores['F'];
|
||||
$v['M'] = $scores['M'];
|
||||
$v['RFM'] = $scores['R'] + $scores['F'] + $scores['M'];
|
||||
$v['money'] = 2222;
|
||||
$v['msgCount'] = 2222;
|
||||
$v['money'] = 3;
|
||||
$v['msgCount'] = 3 ;
|
||||
$v['tag'] = ['test', 'test2'];
|
||||
}
|
||||
unset($v);
|
||||
@@ -318,4 +449,78 @@ class TrafficController extends BaseController
|
||||
return ResponseHelper::success($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有好友列表(特殊流量池)
|
||||
* @param int $page
|
||||
* @param int $limit
|
||||
* @param string $keyword
|
||||
* @param int $companyId
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
private function getAllFriendsList($page, $limit, $keyword, $companyId)
|
||||
{
|
||||
try {
|
||||
// 获取公司下所有设备的微信ID
|
||||
$wechatIds = Db::name('device')->alias('d')
|
||||
->join('(SELECT MAX(id) AS id, deviceId FROM ck_device_wechat_login WHERE companyId='.$companyId.' GROUP BY deviceId) dwl_max', 'dwl_max.deviceId = d.id')
|
||||
->join('device_wechat_login dwl', 'dwl.id = dwl_max.id')
|
||||
->where(['d.companyId' => $companyId, 'd.deleteTime' => 0])
|
||||
->column('dwl.wechatId');
|
||||
|
||||
if (empty($wechatIds)) {
|
||||
return ResponseHelper::success(['list' => [], 'total' => 0]);
|
||||
}
|
||||
|
||||
// 构建查询条件
|
||||
$where = [
|
||||
['wf.ownerWechatId', 'in', $wechatIds],
|
||||
['wf.isDeleted', '=', 0],
|
||||
];
|
||||
|
||||
// 关键字搜索
|
||||
if (!empty($keyword)) {
|
||||
$where[] = ['wf.nickname|wf.alias|wf.wechatId|wf.conRemark', 'like', '%' . $keyword . '%'];
|
||||
}
|
||||
|
||||
// 查询好友列表
|
||||
$query = Db::table('s2_wechat_friend')->alias('wf')
|
||||
->join(['s2_wechat_account' => 'wa'], 'wa.wechatId = wf.ownerWechatId', 'left')
|
||||
->field([
|
||||
'wf.id', 'wf.wechatId as identifier', 'wf.wechatId',
|
||||
Db::raw($companyId . ' as companyId'), 'wf.nickname', 'wf.avatar', 'wf.gender', 'wf.phone', 'wf.alias'
|
||||
])
|
||||
->where($where);
|
||||
|
||||
$total = $query->count();
|
||||
$list = $query->order('wf.id DESC')->page($page, $limit)->select();
|
||||
|
||||
foreach ($list as $k => &$v) {
|
||||
// 获取好友所属的流量池包
|
||||
$package = TrafficSourcePackageItem::alias('tspi')
|
||||
->join('traffic_source_package p', 'tspi.packageId=p.id AND tspi.companyId=p.companyId')
|
||||
->where(['tspi.identifier' => $v['identifier']])
|
||||
->whereIn('tspi.companyId', [0, $companyId])
|
||||
->column('p.name');
|
||||
$v['packages'] = $package;
|
||||
$v['phone'] = !empty($v['phone']) ? $v['phone'] : '';
|
||||
|
||||
// RFM评分(示例数据,实际应该从业务数据计算)
|
||||
$scores = RFMController::calcRfmScores(30, 30, 30);
|
||||
$v['R'] = $scores['R'];
|
||||
$v['F'] = $scores['F'];
|
||||
$v['M'] = $scores['M'];
|
||||
$v['RFM'] = $scores['R'] + $scores['F'] + $scores['M'];
|
||||
$v['money'] = 2222;
|
||||
$v['msgCount'] = 2222;
|
||||
$v['tag'] = ['test', 'test2'];
|
||||
}
|
||||
unset($v);
|
||||
|
||||
$data = ['list' => $list, 'total' => $total];
|
||||
return ResponseHelper::success($data);
|
||||
} catch (\Exception $e) {
|
||||
return ResponseHelper::error('获取好友列表失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -347,10 +347,31 @@ class PosterWeChatMiniProgram extends Controller
|
||||
function getPosterTaskData()
|
||||
{
|
||||
$id = request()->param('id');
|
||||
$task = Db::name('customer_acquisition_task')
|
||||
->where(['id' => $id, 'deleteTime' => 0])
|
||||
->field('id,name,sceneConf,status')
|
||||
->find();
|
||||
$oldId = request()->param('oldId');
|
||||
|
||||
// 兼容旧数据:如果传了 oldId,通过 legacyId 和 isLegacy 查找
|
||||
if (!empty($oldId)) {
|
||||
$task = Db::name('customer_acquisition_task')
|
||||
->where([
|
||||
'legacyId' => $oldId,
|
||||
'isLegacy' => 1,
|
||||
'deleteTime' => 0
|
||||
])
|
||||
->field('id,name,sceneConf,status')
|
||||
->find();
|
||||
} elseif (!empty($id)) {
|
||||
// 新数据:直接用 id 查找
|
||||
$task = Db::name('customer_acquisition_task')
|
||||
->where(['id' => $id, 'deleteTime' => 0])
|
||||
->field('id,name,sceneConf,status')
|
||||
->find();
|
||||
} else {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'message' => '任务ID不能为空'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!$task) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
@@ -367,8 +388,8 @@ class PosterWeChatMiniProgram extends Controller
|
||||
|
||||
$sceneConf = json_decode($task['sceneConf'], true);
|
||||
|
||||
if (isset($sceneConf['posters']['url'])) {
|
||||
$posterUrl = !empty($sceneConf['posters']['url']);
|
||||
if (isset($sceneConf['posters']['url']) && !empty($sceneConf['posters']['url'])) {
|
||||
$posterUrl = $sceneConf['posters']['url'];
|
||||
} else {
|
||||
$posterUrl = 'https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%82%B9%E5%87%BB%E5%92%A8%E8%AF%A2-FTiyAMAPop2g9LvjLOLDz0VwPg3KVu.gif';
|
||||
}
|
||||
|
||||
@@ -107,3 +107,4 @@ class WorkbenchAutoLikeController extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -777,15 +777,55 @@ class WorkbenchController extends Controller
|
||||
|
||||
// 获取流量池(当targetType=2时)
|
||||
if (!empty($workbench->config->trafficPools) && isset($workbench->config->targetType) && $workbench->config->targetType == 2) {
|
||||
$poolList = Db::name('traffic_source_package')->alias('tsp')
|
||||
$poolList = [];
|
||||
$companyId = $this->request->userInfo['companyId'];
|
||||
|
||||
// 检查是否包含"所有好友"(packageId=0)
|
||||
$hasAllFriends = in_array(0, $workbench->config->trafficPools) || in_array('0', $workbench->config->trafficPools);
|
||||
$normalPools = array_filter($workbench->config->trafficPools, function($id) {
|
||||
return $id !== 0 && $id !== '0';
|
||||
});
|
||||
|
||||
// 处理"所有好友"特殊流量池
|
||||
if ($hasAllFriends) {
|
||||
// 计算所有好友数量
|
||||
$wechatIds = Db::name('device')->alias('d')
|
||||
->join('(SELECT MAX(id) AS id, deviceId FROM ck_device_wechat_login WHERE companyId='.$companyId.' GROUP BY deviceId) dwl_max', 'dwl_max.deviceId = d.id')
|
||||
->join('device_wechat_login dwl', 'dwl.id = dwl_max.id')
|
||||
->where(['d.companyId' => $companyId, 'd.deleteTime' => 0])
|
||||
->column('dwl.wechatId');
|
||||
|
||||
$allFriendsCount = 0;
|
||||
if (!empty($wechatIds)) {
|
||||
$allFriendsCount = Db::table('s2_wechat_friend')
|
||||
->where('ownerWechatId', 'in', $wechatIds)
|
||||
->where('isDeleted', 0)
|
||||
->count();
|
||||
}
|
||||
|
||||
$poolList[] = [
|
||||
'id' => 0,
|
||||
'name' => '所有好友',
|
||||
'description' => '展示公司下所有设备的好友',
|
||||
'pic' => '',
|
||||
'itemCount' => $allFriendsCount,
|
||||
];
|
||||
}
|
||||
|
||||
// 处理普通流量池
|
||||
if (!empty($normalPools)) {
|
||||
$normalPoolList = 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)
|
||||
->whereIn('tsp.id', $normalPools)
|
||||
->where('tsp.isDel', 0)
|
||||
->whereIn('tsp.companyId', [$this->request->userInfo['companyId'], 0])
|
||||
->whereIn('tsp.companyId', [$companyId, 0])
|
||||
->field('tsp.id,tsp.name,tsp.description,tsp.pic,COUNT(tspi.id) as itemCount')
|
||||
->group('tsp.id')
|
||||
->order('tsp.id', 'desc')
|
||||
->select();
|
||||
$poolList = array_merge($poolList, $normalPoolList ?: []);
|
||||
}
|
||||
|
||||
$workbench->config->trafficPoolsOptions = $poolList;
|
||||
} else {
|
||||
$workbench->config->trafficPoolsOptions = [];
|
||||
|
||||
@@ -1591,11 +1591,11 @@ class WorkbenchGroupPushController extends Controller
|
||||
}
|
||||
} else {
|
||||
// 其他情况,正常处理并验证
|
||||
$contentGroupsExisting = $originalConfig ? $this->decodeJsonArray($originalConfig->contentLibraries ?? []) : [];
|
||||
$contentGroupsParam = $this->getParamValue($param, 'contentGroups', null);
|
||||
$contentGroups = $contentGroupsParam !== null
|
||||
? $this->extractIdList($contentGroupsParam, '内容库参数格式错误')
|
||||
: $contentGroupsExisting;
|
||||
$contentGroupsExisting = $originalConfig ? $this->decodeJsonArray($originalConfig->contentLibraries ?? []) : [];
|
||||
$contentGroupsParam = $this->getParamValue($param, 'contentGroups', null);
|
||||
$contentGroups = $contentGroupsParam !== null
|
||||
? $this->extractIdList($contentGroupsParam, '内容库参数格式错误')
|
||||
: $contentGroupsExisting;
|
||||
// 其他情况,内容库为必填
|
||||
if (empty($contentGroups)) {
|
||||
throw new \Exception('请至少选择一个内容库');
|
||||
|
||||
@@ -312,3 +312,4 @@ class WorkbenchHelperController extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -68,3 +68,4 @@ class WorkbenchImportContactController extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -124,3 +124,4 @@ class WorkbenchMomentsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -308,3 +308,4 @@ class WorkbenchTrafficController extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -162,11 +162,31 @@ class WorkbenchGroupCreateJob
|
||||
// 获取流量池用户(如果配置了流量池)
|
||||
$poolItem = [];
|
||||
if (!empty($config['poolGroups'])) {
|
||||
$poolItem = Db::name('traffic_source_package_item')
|
||||
->whereIn('packageId', $config['poolGroups'])
|
||||
->where('isDel', 0)
|
||||
->group('identifier')
|
||||
->column('identifier');
|
||||
// 检查是否包含"所有好友"(packageId=0)
|
||||
$hasAllFriends = in_array(0, $config['poolGroups']) || in_array('0', $config['poolGroups']);
|
||||
$normalPools = array_filter($config['poolGroups'], function($id) {
|
||||
return $id !== 0 && $id !== '0';
|
||||
});
|
||||
|
||||
// 处理"所有好友"特殊流量池
|
||||
if ($hasAllFriends) {
|
||||
$companyId = $workbench->companyId ?? 0;
|
||||
$allFriendsIdentifiers = $this->getAllFriendsIdentifiersByCompany($companyId);
|
||||
$poolItem = array_merge($poolItem, $allFriendsIdentifiers);
|
||||
}
|
||||
|
||||
// 处理普通流量池
|
||||
if (!empty($normalPools)) {
|
||||
$normalIdentifiers = Db::name('traffic_source_package_item')
|
||||
->whereIn('packageId', $normalPools)
|
||||
->where('isDel', 0)
|
||||
->group('identifier')
|
||||
->column('identifier');
|
||||
$poolItem = array_merge($poolItem, $normalIdentifiers);
|
||||
}
|
||||
|
||||
// 去重
|
||||
$poolItem = array_unique($poolItem);
|
||||
}
|
||||
|
||||
// 如果既没有流量池也没有指定群组,跳过
|
||||
@@ -802,6 +822,34 @@ class WorkbenchGroupCreateJob
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取公司下所有好友的identifier列表(特殊流量池 packageId=0)
|
||||
* @param int $companyId
|
||||
* @return array
|
||||
*/
|
||||
protected function getAllFriendsIdentifiersByCompany($companyId)
|
||||
{
|
||||
// 获取公司下所有设备的微信ID
|
||||
$wechatIds = Db::name('device')->alias('d')
|
||||
->join('(SELECT MAX(id) AS id, deviceId FROM ck_device_wechat_login WHERE companyId='.$companyId.' GROUP BY deviceId) dwl_max', 'dwl_max.deviceId = d.id')
|
||||
->join('device_wechat_login dwl', 'dwl.id = dwl_max.id')
|
||||
->where(['d.companyId' => $companyId, 'd.deleteTime' => 0])
|
||||
->column('dwl.wechatId');
|
||||
|
||||
if (empty($wechatIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 获取所有好友的wechatId作为identifier
|
||||
$identifiers = Db::table('s2_wechat_friend')
|
||||
->where('ownerWechatId', 'in', $wechatIds)
|
||||
->where('isDeleted', 0)
|
||||
->group('wechatId')
|
||||
->column('wechatId');
|
||||
|
||||
return $identifiers ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录任务开始
|
||||
* @param string $jobId
|
||||
|
||||
@@ -515,14 +515,100 @@ class WorkbenchGroupPushJob
|
||||
}
|
||||
|
||||
$companyId = $workbench->companyId ?? 0;
|
||||
|
||||
// 检查是否包含"所有好友"(packageId=0)
|
||||
$hasAllFriends = in_array(0, $trafficPools) || in_array('0', $trafficPools);
|
||||
$normalPools = array_filter($trafficPools, function($id) {
|
||||
return $id !== 0 && $id !== '0';
|
||||
});
|
||||
|
||||
$friends = [];
|
||||
|
||||
// 处理"所有好友"特殊流量池
|
||||
if ($hasAllFriends) {
|
||||
$allFriends = $this->getAllFriendsByCompany($companyId, $ownerWechatIds);
|
||||
$friends = array_merge($friends, $allFriends);
|
||||
}
|
||||
|
||||
// 处理普通流量池
|
||||
if (!empty($normalPools)) {
|
||||
$normalFriends = $this->getFriendsByNormalPools($normalPools, $companyId, $ownerWechatIds);
|
||||
$friends = array_merge($friends, $normalFriends);
|
||||
}
|
||||
|
||||
// 去重
|
||||
$uniqueFriends = [];
|
||||
$seenIds = [];
|
||||
foreach ($friends as $friend) {
|
||||
$friendId = $friend['id'] ?? null;
|
||||
if ($friendId && !in_array($friendId, $seenIds)) {
|
||||
$seenIds[] = $friendId;
|
||||
$uniqueFriends[] = $friend;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($uniqueFriends)) {
|
||||
Log::info('好友推送:流量池未匹配到好友');
|
||||
return [];
|
||||
}
|
||||
|
||||
return $uniqueFriends;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公司下所有好友(特殊流量池 packageId=0)
|
||||
* @param int $companyId
|
||||
* @param array $ownerWechatIds
|
||||
* @return array
|
||||
*/
|
||||
protected function getAllFriendsByCompany($companyId, array $ownerWechatIds = [])
|
||||
{
|
||||
// 获取公司下所有设备的微信ID
|
||||
$wechatIds = Db::name('device')->alias('d')
|
||||
->join('(SELECT MAX(id) AS id, deviceId FROM ck_device_wechat_login WHERE companyId='.$companyId.' GROUP BY deviceId) dwl_max', 'dwl_max.deviceId = d.id')
|
||||
->join('device_wechat_login dwl', 'dwl.id = dwl_max.id')
|
||||
->where(['d.companyId' => $companyId, 'd.deleteTime' => 0])
|
||||
->column('dwl.wechatId');
|
||||
|
||||
if (empty($wechatIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$query = Db::table('s2_wechat_friend')->alias('wf')
|
||||
->join(['s2_wechat_account' => 'wa'], 'wa.id = wf.wechatAccountId', 'left')
|
||||
->where('wf.ownerWechatId', 'in', $wechatIds)
|
||||
->where('wf.isDeleted', 0)
|
||||
->whereNotNull('wf.id')
|
||||
->whereNotNull('wf.wechatAccountId');
|
||||
|
||||
if (!empty($ownerWechatIds)) {
|
||||
$query->whereIn('wf.wechatAccountId', $ownerWechatIds);
|
||||
}
|
||||
|
||||
$friends = $query
|
||||
->field('wf.id,wf.wechatAccountId,wf.wechatId,wf.ownerWechatId')
|
||||
->group('wf.id')
|
||||
->select();
|
||||
|
||||
return $friends ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据普通流量池获取好友信息
|
||||
* @param array $packageIds
|
||||
* @param int $companyId
|
||||
* @param array $ownerWechatIds
|
||||
* @return array
|
||||
*/
|
||||
protected function getFriendsByNormalPools(array $packageIds, $companyId, array $ownerWechatIds = [])
|
||||
{
|
||||
$query = Db::name('traffic_source_package_item')
|
||||
->alias('tspi')
|
||||
->leftJoin('traffic_source_package tsp', 'tsp.id = tspi.packageId')
|
||||
->leftJoin('traffic_pool tp', 'tp.identifier = tspi.identifier')
|
||||
->leftJoin(['s2_wechat_friend' => 'wf'], 'wf.wechatId = tp.wechatId')
|
||||
->leftJoin(['s2_wechat_account' => 'wa'], 'wa.id = wf.wechatAccountId')
|
||||
->whereIn('tspi.packageId', $trafficPools)
|
||||
->whereIn('tspi.packageId', $packageIds)
|
||||
->where('tsp.isDel', 0)
|
||||
->where('wf.isDeleted', 0)
|
||||
->whereNotNull('wf.id')
|
||||
@@ -543,16 +629,7 @@ class WorkbenchGroupPushJob
|
||||
->group('wf.id')
|
||||
->select();
|
||||
|
||||
if (empty($friends)) {
|
||||
Log::info('好友推送:流量池未匹配到好友');
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($friends === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $friends;
|
||||
return $friends ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -322,30 +322,91 @@ class WorkbenchImportContactJob
|
||||
if (empty($contactNum)) {
|
||||
return false;
|
||||
}
|
||||
//过滤已删除的数据
|
||||
$packageIds = Db::name('traffic_source_package')
|
||||
->where(['isDel' => 0])
|
||||
->whereIn('id', $pools)
|
||||
->column('id');
|
||||
// 检查是否包含"所有好友"(packageId=0)
|
||||
$hasAllFriends = in_array(0, $pools) || in_array('0', $pools);
|
||||
$normalPools = array_filter($pools, function($id) {
|
||||
return $id !== 0 && $id !== '0';
|
||||
});
|
||||
|
||||
$data = [];
|
||||
|
||||
// 处理"所有好友"特殊流量池
|
||||
if ($hasAllFriends) {
|
||||
$allFriendsData = $this->getAllFriendsForImportContact($workbench, $contactNum);
|
||||
$data = array_merge($data, $allFriendsData);
|
||||
}
|
||||
|
||||
// 处理普通流量池
|
||||
if (!empty($normalPools)) {
|
||||
//过滤已删除的数据
|
||||
$packageIds = Db::name('traffic_source_package')
|
||||
->where(['isDel' => 0])
|
||||
->whereIn('id', $normalPools)
|
||||
->column('id');
|
||||
|
||||
if (empty($packageIds)) {
|
||||
if (!empty($packageIds)) {
|
||||
$normalData = Db::name('traffic_source_package_item')->alias('tpi')
|
||||
->join('traffic_pool tp', 'tp.identifier = tpi.identifier')
|
||||
->join('traffic_source ts', 'ts.identifier = tpi.identifier','left')
|
||||
->join('workbench_import_contact_item wici', 'wici.poolId = tp.id AND wici.workbenchId = '.$workbench->id,'left')
|
||||
->where('tp.mobile', '>',0)
|
||||
->where('wici.id','null')
|
||||
->whereIn('tpi.packageId',$packageIds)
|
||||
->field('tp.id,tpi.packageId,tp.mobile as phone,ts.name')
|
||||
->order('tp.id DESC')
|
||||
->group('tpi.identifier')
|
||||
->limit($contactNum)
|
||||
->select();
|
||||
$data = array_merge($data, $normalData ?: []);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = Db::name('traffic_source_package_item')->alias('tpi')
|
||||
->join('traffic_pool tp', 'tp.identifier = tpi.identifier')
|
||||
->join('traffic_source ts', 'ts.identifier = tpi.identifier','left')
|
||||
->join('workbench_import_contact_item wici', 'wici.poolId = tp.id AND wici.workbenchId = '.$workbench->id,'left')
|
||||
->where('tp.mobile', '>',0)
|
||||
->where('wici.id','null')
|
||||
->whereIn('tpi.packageId',$packageIds)
|
||||
->field('tp.id,tpi.packageId,tp.mobile as phone,ts.name')
|
||||
->order('tp.id DESC')
|
||||
->group('tpi.identifier')
|
||||
->limit($contactNum)
|
||||
->select();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取"所有好友"流量池的联系人数据(用于通讯录导入)
|
||||
* @param Workbench $workbench
|
||||
* @param int $limit
|
||||
* @return array
|
||||
*/
|
||||
protected function getAllFriendsForImportContact($workbench, $limit)
|
||||
{
|
||||
$companyId = $workbench->companyId ?? 0;
|
||||
|
||||
// 获取公司下所有设备的微信ID
|
||||
$wechatIds = Db::name('device')->alias('d')
|
||||
->join('(SELECT MAX(id) AS id, deviceId FROM ck_device_wechat_login WHERE companyId='.$companyId.' GROUP BY deviceId) dwl_max', 'dwl_max.deviceId = d.id')
|
||||
->join('device_wechat_login dwl', 'dwl.id = dwl_max.id')
|
||||
->where(['d.companyId' => $companyId, 'd.deleteTime' => 0])
|
||||
->column('dwl.wechatId');
|
||||
|
||||
if (empty($wechatIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 从 s2_wechat_friend 表获取好友,然后关联 traffic_pool 表获取手机号
|
||||
$data = Db::table('s2_wechat_friend')->alias('wf')
|
||||
->join('traffic_pool tp', 'tp.wechatId = wf.wechatId', 'left')
|
||||
->join('traffic_source ts', 'ts.identifier = tp.identifier', 'left')
|
||||
->join('workbench_import_contact_item wici', 'wici.poolId = tp.id AND wici.workbenchId = '.$workbench->id, 'left')
|
||||
->where('wf.ownerWechatId', 'in', $wechatIds)
|
||||
->where('wf.isDeleted', 0)
|
||||
->where('tp.mobile', '>', 0)
|
||||
->where('wici.id', 'null')
|
||||
->field('tp.id,tp.mobile as phone,ts.name')
|
||||
->field(Db::raw('0 as packageId')) // 标记为"所有好友"流量池
|
||||
->order('tp.id DESC')
|
||||
->group('tp.identifier')
|
||||
->limit($limit)
|
||||
->select();
|
||||
|
||||
return $data ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录任务开始
|
||||
|
||||
Reference in New Issue
Block a user