170 lines
6.2 KiB
PHP
170 lines
6.2 KiB
PHP
<?php
|
||
|
||
namespace app\chukebao\controller;
|
||
|
||
use app\cunkebao\service\TrafficPoolService;
|
||
use library\ResponseHelper;
|
||
use think\Db;
|
||
|
||
/**
|
||
* 模块 B · 客户资料池 / 流量池(需求一 §1.3.6 · 需求七 §7.6)
|
||
* 真源 cunkebao traffic_pool,chukebao 代理;按 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,
|
||
], '已发起加好友并绑定流量池');
|
||
}
|
||
}
|