Files
cunkebao_v3/Server/application/chukebao/controller/TrafficPoolKefuController.php
Manus AI 5517457929 sync: 以本地为准同步全量变更至 GitHub
含四端需求文档、前端/后端/超管/触客宝迭代及部署脚本更新;未拉取远程。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-30 04:24:56 +08:00

170 lines
6.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\chukebao\controller;
use app\cunkebao\service\TrafficPoolService;
use library\ResponseHelper;
use think\Db;
/**
* 模块 B · 客户资料池 / 流量池(需求一 §1.3.6 · 需求七 §7.6
* 真源 cunkebao traffic_poolchukebao 代理;按 companyId 隔离。
*/
class TrafficPoolKefuController extends BaseController
{
/** @var TrafficPoolService */
private function poolService()
{
return new TrafficPoolService();
}
/**
* 本项目可选「流量池」(只读,用于加好友/AI获客标签
* GET /v1/kefu/traffic-pool/options
*/
public function getOptions()
{
$companyId = $this->getUserInfo('companyId');
$keyword = $this->request->param('keyword', '');
$query = Db::name('traffic_source_package_v1')->alias('tsp')
->join('traffic_source_package_item_v1 tspi', 'tspi.packageId=tsp.id', 'left')
->whereIn('tsp.companyId', [$companyId, 0])
->field('tsp.id,tsp.name,count(tspi.id) as num')
->group('tsp.id');
if ($keyword !== '') {
$query->where('tsp.name', 'like', '%' . $keyword . '%');
}
$list = $query->order('tsp.id DESC')->select();
return ResponseHelper::success(['list' => $list]);
}
/**
* 客户资料池列表(设置 → 客户资料)
* GET /v1/kefu/customer-pool/list
*/
public function customerPoolList()
{
$companyId = $this->getUserInfo('companyId');
$page = (int)$this->request->param('page', 1);
$limit = (int)$this->request->param('limit', 20);
$keyword = $this->request->param('keyword', '');
try {
$filters = [];
if ($keyword !== '') {
$filters['keyword'] = $keyword;
}
$res = $this->poolService()->getPoolList($companyId, $page, $limit, $filters);
return ResponseHelper::success([
'list' => $res['list'] ?? [],
'total' => $res['total'] ?? 0,
]);
} catch (\Exception $e) {
return ResponseHelper::error('获取客户资料池失败:' . $e->getMessage());
}
}
/**
* 客户资料池详情
* GET /v1/kefu/customer-pool/detail?poolId=
*/
public function customerPoolDetail()
{
$companyId = $this->getUserInfo('companyId');
$poolId = (int)$this->request->param('poolId', 0);
if (!$poolId) {
return ResponseHelper::error('poolId 缺失', 400);
}
try {
$detail = $this->poolService()->getPoolDetail($poolId, $companyId);
if (!$detail) {
return ResponseHelper::error('未找到该客资或无权限', 404);
}
return ResponseHelper::success($detail);
} catch (\Exception $e) {
return ResponseHelper::error('获取详情失败:' . $e->getMessage());
}
}
/**
* 更新客户资料池(标签/备注/流量池)
* PATCH|POST /v1/kefu/customer-pool/update
*/
public function customerPoolUpdate()
{
$companyId = $this->getUserInfo('companyId');
$poolId = (int)$this->request->param('poolId', 0);
if (!$poolId) {
return ResponseHelper::error('poolId 缺失', 400);
}
$data = [];
foreach (['tags', 'poolKeywords', 'remark', 'realName', 'phone', 'intentionLevel'] as $f) {
$v = $this->request->param($f, null);
if ($v !== null) {
$data[$f] = $v;
}
}
try {
$this->poolService()->updatePool($poolId, $companyId, $data);
return ResponseHelper::success(true, '已更新并同步流量池');
} catch (\Exception $e) {
return ResponseHelper::error('更新失败:' . $e->getMessage());
}
}
/**
* 加好友并绑定流量池REST 备用;前端实时加好友走 WS CmdSendFriendRequest 已带 PoolIds
* POST /v1/kefu/wechatFriend/add-with-pool
* body: { wechatAccountId, account, poolId|poolId[], labels?, remark? }
*/
public function addWithPool()
{
$companyId = $this->getUserInfo('companyId');
$wechatAccountId = (int)$this->request->param('wechatAccountId', 0);
$account = trim((string)$this->request->param('account', ''));
$poolId = $this->request->param('poolId', []);
if (!$wechatAccountId || $account === '') {
return ResponseHelper::error('参数缺失wechatAccountId/account', 400);
}
$poolIds = is_array($poolId) ? $poolId : array_filter([$poolId]);
$poolIds = array_values(array_unique(array_map('intval', $poolIds)));
// 权限校验流量池须属本项目companyId 或系统 0
if (!empty($poolIds)) {
$valid = Db::name('traffic_source_package_v1')
->whereIn('id', $poolIds)
->whereIn('companyId', [$companyId, 0])
->column('id');
$invalid = array_diff($poolIds, $valid);
if (!empty($invalid)) {
return ResponseHelper::error('存在跨项目/无效流量池,禁止选择', 403);
}
// 记录待绑定标识(识别为 account好友通过后由 S2 回调补全 identifier
try {
foreach ($poolIds as $pid) {
$exists = Db::name('traffic_source_package_item_v1')
->where(['packageId' => $pid, 'identifier' => $account])
->count();
if (!$exists) {
Db::name('traffic_source_package_item_v1')->insert([
'packageId' => $pid,
'identifier' => $account,
'createTime' => time(),
]);
}
}
} catch (\Exception $e) {
// 绑定表结构差异不阻断主流程(实际加好友走 WS
}
}
return ResponseHelper::success([
'wechatAccountId' => $wechatAccountId,
'account' => $account,
'poolIds' => $poolIds,
], '已发起加好友并绑定流量池');
}
}