Merge branch 'develop' into yongpxu-dev
This commit is contained in:
22
Server/application/ai/config/route.php
Normal file
22
Server/application/ai/config/route.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use think\facade\Route;
|
||||
|
||||
// 定义RESTful风格的API路由
|
||||
Route::group('v1/ai', function () {
|
||||
|
||||
//openai、chatGPT
|
||||
Route::group('openai', function () {
|
||||
Route::post('text', 'app\ai\controller\OpenAi@text');
|
||||
});
|
||||
|
||||
|
||||
//豆包ai
|
||||
Route::group('doubao', function () {
|
||||
Route::post('text', 'app\ai\controller\DouBaoAI@text');
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
})->middleware(['jwt']);
|
||||
53
Server/application/ai/controller/DouBaoAI.php
Normal file
53
Server/application/ai/controller/DouBaoAI.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace app\ai\controller;
|
||||
|
||||
use think\facade\Env;
|
||||
|
||||
class DouBaoAI
|
||||
{
|
||||
protected $apiUrl;
|
||||
protected $apiKey;
|
||||
protected $headers;
|
||||
|
||||
public function __init()
|
||||
{
|
||||
$this->apiUrl = Env::get('doubaoAi.api_url');
|
||||
$this->apiKey = Env::get('doubaoAi.api_key');
|
||||
|
||||
// 设置请求头
|
||||
$this->headers = [
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Bearer ' . $this->apiKey
|
||||
];
|
||||
|
||||
if (empty($this->apiKey) || empty($this->apiUrl)) {
|
||||
return json_encode(['code' => 500, 'msg' => '参数缺失']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function text()
|
||||
{
|
||||
$this->__init();
|
||||
|
||||
// 发送请求
|
||||
$params = [
|
||||
'model' => 'doubao-1-5-pro-32k-250115',
|
||||
'messages' => [
|
||||
['role' => 'system', 'content' => '你是人工智能助手.'],
|
||||
['role' => 'user', 'content' => '厦门天气'],
|
||||
],
|
||||
/*'extra_headers' => [
|
||||
'x-is-encrypted' => true
|
||||
],
|
||||
'temperature' => 1,
|
||||
'top_p' => 0.7,
|
||||
'max_tokens' => 4096,
|
||||
'frequency_penalty' => 0,*/
|
||||
];
|
||||
$result = requestCurl($this->apiUrl, $params, 'POST', $this->headers, 'json');
|
||||
$result = json_decode($result, true);
|
||||
return successJson($result);
|
||||
}
|
||||
}
|
||||
141
Server/application/ai/controller/OpenAi.php
Normal file
141
Server/application/ai/controller/OpenAi.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace app\ai\controller;
|
||||
|
||||
use think\facade\Env;
|
||||
class OpenAi
|
||||
{
|
||||
protected $apiUrl;
|
||||
protected $apiKey;
|
||||
protected $headers;
|
||||
|
||||
public function __init()
|
||||
{
|
||||
$this->apiUrl = Env::get('openAi.apiUrl');
|
||||
$this->apiKey = Env::get('openAi.apiKey');
|
||||
|
||||
// 设置请求头
|
||||
$this->headers = [
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Bearer '.$this->apiKey
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function text()
|
||||
{
|
||||
$this->__init();
|
||||
$params = [
|
||||
'model' => 'gpt-3.5-turbo-0125',
|
||||
'input' => 'DHA 从孕期到出生到老年都需要,助力大脑发育🧠/减缓脑压力有助记忆/给大脑动力#贝蒂喜藻油DHA 双标认证每粒 150毫克,高含量、高性价比从小吃到老,长期吃更健康 重写这条朋友圈 要求: 1、原本的字数和意思不要修改超过10% 2、出现品牌名或个人名字就去除'
|
||||
];
|
||||
$result = $this->httpRequest( $this->apiUrl, 'POST', $params,$this->headers);
|
||||
exit_data($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 示例:调用OpenAI API生成睡前故事
|
||||
* 对应curl命令:
|
||||
* curl "https://api.ai.com/v1/responses" \
|
||||
* -H "Content-Type: application/json" \
|
||||
* -H "Authorization: Bearer $OPENAI_API_KEY" \
|
||||
* -d '{
|
||||
* "model": "gpt-5",
|
||||
* "input": "Write a one-sentence bedtime story about a unicorn."
|
||||
* }'
|
||||
*/
|
||||
public function bedtimeStory()
|
||||
{
|
||||
$this->__init();
|
||||
|
||||
// API请求参数
|
||||
$params = [
|
||||
'model' => 'gpt-5',
|
||||
'input' => 'Write a one-sentence bedtime story about a unicorn.'
|
||||
];
|
||||
|
||||
// 发送请求到OpenAI API
|
||||
$url = 'https://api.openai.com/v1/responses';
|
||||
$result = $this->httpRequest($url, 'POST', $params, $this->headers);
|
||||
|
||||
// 返回结果
|
||||
exit_data($result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* CURL请求 - 专门用于JSON API请求
|
||||
*
|
||||
* @param $url 请求url地址
|
||||
* @param $method 请求方法 get post
|
||||
* @param null $postfields post数据数组
|
||||
* @param array $headers 请求header信息
|
||||
* @param int $timeout 超时时间
|
||||
* @param bool|false $debug 调试开启 默认false
|
||||
* @return mixed
|
||||
*/
|
||||
protected function httpRequest($url, $method = "GET", $postfields = null, $headers = array(), $timeout = 30, $debug = false)
|
||||
{
|
||||
$method = strtoupper($method);
|
||||
$ci = curl_init();
|
||||
|
||||
/* Curl settings */
|
||||
curl_setopt($ci, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
|
||||
curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 60); /* 在发起连接前等待的时间,如果设置为0,则无限等待 */
|
||||
curl_setopt($ci, CURLOPT_TIMEOUT, $timeout); /* 设置cURL允许执行的最长秒数 */
|
||||
curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
switch ($method) {
|
||||
case "POST":
|
||||
curl_setopt($ci, CURLOPT_POST, true);
|
||||
if (!empty($postfields)) {
|
||||
// 对于JSON API,直接将数组转换为JSON字符串
|
||||
if (is_array($postfields)) {
|
||||
$tmpdatastr = json_encode($postfields);
|
||||
} else {
|
||||
$tmpdatastr = $postfields;
|
||||
}
|
||||
curl_setopt($ci, CURLOPT_POSTFIELDS, $tmpdatastr);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
curl_setopt($ci, CURLOPT_CUSTOMREQUEST, $method); /* //设置请求方式 */
|
||||
break;
|
||||
}
|
||||
|
||||
$ssl = preg_match('/^https:\/\//i', $url) ? TRUE : FALSE;
|
||||
curl_setopt($ci, CURLOPT_URL, $url);
|
||||
if ($ssl) {
|
||||
curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
|
||||
curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, FALSE); // 不从证书中检查SSL加密算法是否存在
|
||||
}
|
||||
|
||||
if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
|
||||
curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 1);
|
||||
}
|
||||
curl_setopt($ci, CURLOPT_MAXREDIRS, 2);/*指定最多的HTTP重定向的数量,这个选项是和CURLOPT_FOLLOWLOCATION一起使用的*/
|
||||
curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ci, CURLINFO_HEADER_OUT, true);
|
||||
|
||||
$response = curl_exec($ci);
|
||||
$requestinfo = curl_getinfo($ci);
|
||||
$http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
|
||||
|
||||
if ($debug) {
|
||||
echo "=====post data======\r\n";
|
||||
var_dump($postfields);
|
||||
echo "=====info===== \r\n";
|
||||
print_r($requestinfo);
|
||||
echo "=====response=====\r\n";
|
||||
print_r($response);
|
||||
}
|
||||
|
||||
curl_close($ci);
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace app\api\controller;
|
||||
|
||||
use app\api\model\DeviceModel;
|
||||
use app\api\model\DeviceGroupModel;
|
||||
use think\Db;
|
||||
use think\facade\Request;
|
||||
use think\facade\Env;
|
||||
use Endroid\QrCode\QrCode;
|
||||
@@ -274,6 +275,53 @@ class DeviceController extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除设备
|
||||
*
|
||||
* @param $deviceId
|
||||
* @return false|string
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function delDevice($deviceId = '')
|
||||
{
|
||||
$authorization = $this->authorization;
|
||||
if (empty($authorization)) {
|
||||
return json_encode(['code'=>500,'msg'=>'缺少授权信息']);
|
||||
}
|
||||
|
||||
if (empty($deviceId)) {
|
||||
return json_encode(['code'=>500,'msg'=>'删除的设备不能为空']);
|
||||
}
|
||||
|
||||
$device = Db::table('s2_device')->where('id', $deviceId)->find();
|
||||
if (empty($device)) {
|
||||
return json_encode(['code'=>500,'msg'=>'设备不存在']);
|
||||
}
|
||||
|
||||
try {
|
||||
// 设置请求头
|
||||
$headerData = ['client:system'];
|
||||
$header = setHeader($headerData, $authorization, 'json');
|
||||
// 发送请求
|
||||
$result = requestCurl($this->baseUrl . 'api/device/del/'.$deviceId, [], 'DELETE', $header,'json');
|
||||
if (empty($result)) {
|
||||
Db::table('s2_device')->where('id', $deviceId)->update([
|
||||
'isDeleted' => 1,
|
||||
'deleteTime' => time()
|
||||
]);
|
||||
return json_encode(['code'=>200,'msg'=>'删除成功']);
|
||||
}else{
|
||||
return json_encode(['code'=>200,'msg'=>'删除失败']);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return json_encode(['code'=>500,'msg'=>'获取设备分组列表失败:' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************ 设备分组相关接口 ************************/
|
||||
|
||||
/**
|
||||
|
||||
@@ -837,4 +837,54 @@ class WebSocketController extends BaseController
|
||||
return json_encode(['code' => 500, 'msg' => '邀请好友入群异常:' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加群好友
|
||||
* @param $data
|
||||
* @return false|string
|
||||
*/
|
||||
public function CmdChatroomOperate($data = [])
|
||||
{
|
||||
try {
|
||||
// 参数验证
|
||||
if (empty($data)) {
|
||||
return json_encode(['code' => 400, 'msg' => '参数缺失']);
|
||||
}
|
||||
|
||||
// 验证必要参数
|
||||
if (empty($data['wechatId'])) {
|
||||
return json_encode(['code' => 400, 'msg' => 'wechatId不能为空']);
|
||||
}
|
||||
|
||||
if (empty($data['sendWord'])) {
|
||||
return json_encode(['code' => 400, 'msg' => '添加的招呼语不能为空']);
|
||||
}
|
||||
|
||||
if (empty($data['wechatAccountId'])) {
|
||||
return json_encode(['code' => 400, 'msg' => '微信账号ID不能为空']);
|
||||
}
|
||||
if (empty($data['wechatChatroomId'])) {
|
||||
return json_encode(['code' => 400, 'msg' => '群ID不能为空']);
|
||||
}
|
||||
|
||||
|
||||
// 构建请求参数
|
||||
$params = [
|
||||
"chatroomOperateType" => 1,
|
||||
"cmdType" => "CmdChatroomOperate",
|
||||
"extra" => [
|
||||
'wechatId' => $data['wechatId'],
|
||||
'sendWord' => $data['sendWord']
|
||||
],
|
||||
"seq" => time(),
|
||||
"wechatAccountId" => $data['wechatAccountId'],
|
||||
"wechatChatroomId" => $data['wechatChatroomId'],
|
||||
];
|
||||
$message = $this->sendMessage($params);
|
||||
return json_encode(['code' => 200, 'msg' => '添加好友请求发送成功', 'data' => $message]);
|
||||
} catch (\Exception $e) {
|
||||
// 返回错误响应
|
||||
return json_encode(['code' => 500, 'msg' => '添加群好友异常:' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,7 @@ class SyncWechatDataToCkbTask extends Command
|
||||
$this->syncWechatFriendToTrafficPoolBatch($ChuKeBaoAdapter);
|
||||
$this->syncTrafficSourceUser($ChuKeBaoAdapter);
|
||||
$this->syncTrafficSourceGroup($ChuKeBaoAdapter);
|
||||
$this->syncCallRecording($ChuKeBaoAdapter);
|
||||
|
||||
$output->writeln("同步任务 sync_wechat_to_ckb 已结束");
|
||||
return true;
|
||||
@@ -118,6 +119,10 @@ class SyncWechatDataToCkbTask extends Command
|
||||
{
|
||||
return $ChuKeBaoAdapter->syncWechatGroupCustomer();
|
||||
}
|
||||
protected function syncCallRecording(ChuKeBaoAdapter $ChuKeBaoAdapter)
|
||||
{
|
||||
return $ChuKeBaoAdapter->syncCallRecording();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -16,8 +16,8 @@ class TaskServer extends Server
|
||||
protected $socket = 'text://0.0.0.0:2980';
|
||||
|
||||
protected $option = [
|
||||
'count' => self::PROCESS_COUNT,
|
||||
'name' => 'ckb_task_server'
|
||||
'count' => self::PROCESS_COUNT,
|
||||
'name' => 'ckb_task_server'
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -31,11 +31,17 @@ class TaskServer extends Server
|
||||
Log::record("error $code $msg");
|
||||
}
|
||||
|
||||
public function onMessage($connection, $data) {}
|
||||
public function onMessage($connection, $data)
|
||||
{
|
||||
}
|
||||
|
||||
public function onClose($connection) {}
|
||||
public function onClose($connection)
|
||||
{
|
||||
}
|
||||
|
||||
public function onConnect($connection) {}
|
||||
public function onConnect($connection)
|
||||
{
|
||||
}
|
||||
|
||||
public function onWorkerStart($worker)
|
||||
{
|
||||
@@ -52,7 +58,7 @@ class TaskServer extends Server
|
||||
|
||||
// 在一个进程里处理获客任务新是数据
|
||||
if ($current_worker_id == 4) {
|
||||
Timer::add(60, function () use($adapter) {
|
||||
Timer::add(60, function () use ($adapter) {
|
||||
$adapter->handleCustomerTaskNewUser();
|
||||
});
|
||||
}
|
||||
@@ -60,7 +66,7 @@ class TaskServer extends Server
|
||||
|
||||
// 在一个进程里处理获客任务添加后的相关逻辑
|
||||
if ($current_worker_id == 3) {
|
||||
Timer::add(60, function () use($adapter) {
|
||||
Timer::add(60, function () use ($adapter) {
|
||||
$adapter->handleCustomerTaskWithStatusIsCreated();
|
||||
});
|
||||
}
|
||||
@@ -74,6 +80,6 @@ class TaskServer extends Server
|
||||
|
||||
// 更多其他后台任务
|
||||
// ......
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,10 +57,7 @@ class PasswordLoginController extends BaseController
|
||||
throw new \Exception('用户不存在或已禁用', 403);
|
||||
}
|
||||
|
||||
|
||||
$password = md5($password);
|
||||
|
||||
|
||||
if ($user->passwordMd5 !== $password) {
|
||||
throw new \Exception('账号或密码错误', 403);
|
||||
}
|
||||
@@ -119,8 +116,11 @@ class PasswordLoginController extends BaseController
|
||||
// 生成JWT令牌
|
||||
$token = JwtUtil::createToken($member, 86400 * 30);
|
||||
$token_expired = time() + 86400 * 30;
|
||||
|
||||
return compact('member', 'token', 'token_expired','deviceTotal');
|
||||
$kefuData = [
|
||||
'token' => [],
|
||||
'self' => [],
|
||||
];
|
||||
return compact('member', 'token', 'token_expired','deviceTotal','kefuData');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,15 +131,34 @@ class PasswordLoginController extends BaseController
|
||||
public function index()
|
||||
{
|
||||
$params = $this->request->only(['account', 'password', 'typeId']);
|
||||
|
||||
try {
|
||||
$result = $this->dataValidate($params)->doLogin(
|
||||
$userData = $this->dataValidate($params)->doLogin(
|
||||
$params['account'],
|
||||
$params['password'],
|
||||
$params['typeId']
|
||||
);
|
||||
|
||||
return ResponseHelper::success($result, '登录成功');
|
||||
//同时登录客服系统
|
||||
if (!empty($userData['member']['passwordLocal'])){
|
||||
$params = [
|
||||
'grant_type' => 'password',
|
||||
'username' => $userData['member']['account'],
|
||||
'password' => localDecrypt($userData['member']['passwordLocal'])
|
||||
];
|
||||
// 调用登录接口获取token
|
||||
$headerData = ['client:kefu-client'];
|
||||
$header = setHeader($headerData, '', 'plain');
|
||||
$result = requestCurl('https://s2.siyuguanli.com:9991/token', $params, 'POST', $header);
|
||||
$token = handleApiResponse($result);
|
||||
$userData['kefuData']['token'] = $token;
|
||||
if (isset($token['access_token']) && !empty($token['access_token'])) {
|
||||
$headerData = ['client:kefu-client'];
|
||||
$header = setHeader($headerData, $token['access_token']);
|
||||
$result = requestCurl( 'https://s2.siyuguanli.com:9991/api/account/self', [], 'GET', $header,'json');
|
||||
$self = handleApiResponse($result);
|
||||
$userData['kefuData']['self'] = $self;
|
||||
}
|
||||
}
|
||||
return ResponseHelper::success($userData, '登录成功');
|
||||
} catch (Exception $e) {
|
||||
return ResponseHelper::error($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
@@ -34,5 +34,5 @@ class User extends Model
|
||||
* 隐藏属性
|
||||
* @var array
|
||||
*/
|
||||
protected $hidden = ['passwordMd5', 'passwordLocal', 'deleteTime'];
|
||||
protected $hidden = ['passwordMd5', 'deleteTime'];
|
||||
}
|
||||
@@ -20,8 +20,8 @@ class BaseController extends Controller
|
||||
parent::__construct();
|
||||
|
||||
// 从环境变量获取配置
|
||||
$this->apiUrl = Env::get('ai.api_url');
|
||||
$this->accessToken = Env::get('ai.token');
|
||||
$this->apiUrl = Env::get('cozeAi.api_url');
|
||||
$this->accessToken = Env::get('cozeAi.token');
|
||||
|
||||
// 设置请求头
|
||||
$this->headers = [
|
||||
|
||||
@@ -101,7 +101,7 @@ class ConversationController extends BaseController
|
||||
public function create($is_internal = false)
|
||||
{
|
||||
try {
|
||||
$bot_id = Env::get('ai.bot_id');
|
||||
$bot_id = Env::get('cozeAi.bot_id');
|
||||
$userInfo = request()->userInfo;
|
||||
$uid = $userInfo['id'];
|
||||
$companyId = $userInfo['companyId'];
|
||||
@@ -117,7 +117,7 @@ class ConversationController extends BaseController
|
||||
];
|
||||
$messages[] = [
|
||||
'role' => 'assistant',
|
||||
'content' => Env::get('ai.content'),
|
||||
'content' => Env::get('cozeAi.content'),
|
||||
'type' => 'answer',
|
||||
'content_type' => 'text',
|
||||
];
|
||||
@@ -145,7 +145,7 @@ class ConversationController extends BaseController
|
||||
'chat_id' => $conversation['id'],
|
||||
'conversation_id' => $conversation['id'],
|
||||
'bot_id' => $bot_id,
|
||||
'content' => Env::get('ai.content'),
|
||||
'content' => Env::get('cozeAi.content'),
|
||||
'content_type' => 'text',
|
||||
'role' => 'assistant',
|
||||
'type' => 'answer',
|
||||
@@ -177,7 +177,7 @@ class ConversationController extends BaseController
|
||||
public function createChat()
|
||||
{
|
||||
try {
|
||||
$bot_id = Env::get('ai.bot_id');
|
||||
$bot_id = Env::get('cozeAi.bot_id');
|
||||
$conversation_id = input('conversation_id','');
|
||||
$question = input('question','');
|
||||
|
||||
|
||||
@@ -67,6 +67,8 @@ Route::group('v1/', function () {
|
||||
Route::get('getUserJourney', 'app\cunkebao\controller\traffic\GetPotentialListWithInCompanyV1Controller@getUserJourney');
|
||||
Route::get('getUserTags', 'app\cunkebao\controller\traffic\GetPotentialListWithInCompanyV1Controller@getUserTags');
|
||||
Route::get('getUserInfo', 'app\cunkebao\controller\traffic\GetPotentialListWithInCompanyV1Controller@getUser');
|
||||
Route::get('getPackage', 'app\cunkebao\controller\traffic\GetPotentialListWithInCompanyV1Controller@getPackage');
|
||||
Route::post('addPackage', 'app\cunkebao\controller\traffic\GetPotentialListWithInCompanyV1Controller@addPackage');
|
||||
|
||||
|
||||
|
||||
@@ -94,6 +96,7 @@ Route::group('v1/', function () {
|
||||
Route::get('device-labels', 'app\cunkebao\controller\WorkbenchController@getDeviceLabels'); // 获取设备微信好友标签统计
|
||||
Route::get('group-list', 'app\cunkebao\controller\WorkbenchController@getGroupList'); // 获取群列表
|
||||
Route::get('account-list', 'app\cunkebao\controller\WorkbenchController@getAccountList'); // 获取账号列表
|
||||
Route::get('transfer-friends', 'app\cunkebao\controller\WorkbenchController@getTrafficList'); // 获取账号列表
|
||||
|
||||
Route::get('getJdSocialMedia', 'app\cunkebao\controller\WorkbenchController@getJdSocialMedia'); // 获取京东联盟导购媒体
|
||||
Route::get('getJdPromotionSite', 'app\cunkebao\controller\WorkbenchController@getJdPromotionSite'); // 获取京东联盟广告位
|
||||
@@ -129,12 +132,14 @@ Route::group('v1/', function () {
|
||||
|
||||
|
||||
//数据统计相关
|
||||
Route::group('dashboard',function (){
|
||||
Route::get('', 'app\cunkebao\controller\StatsController@baseInfoStats');
|
||||
Route::get('plan-stats', 'app\cunkebao\controller\StatsController@planStats');
|
||||
Route::get('sevenDay-stats', 'app\cunkebao\controller\StatsController@customerAcquisitionStats7Days');
|
||||
Route::get('today-stats', 'app\cunkebao\controller\StatsController@todayStats');
|
||||
});
|
||||
Route::group('dashboard',function (){
|
||||
Route::get('', 'app\cunkebao\controller\StatsController@baseInfoStats');
|
||||
Route::get('plan-stats', 'app\cunkebao\controller\StatsController@planStats');
|
||||
Route::get('sevenDay-stats', 'app\cunkebao\controller\StatsController@customerAcquisitionStats7Days');
|
||||
Route::get('today-stats', 'app\cunkebao\controller\StatsController@todayStats');
|
||||
Route::get('friendRequestTaskStats', 'app\cunkebao\controller\StatsController@getFriendRequestTaskStats');
|
||||
Route::get('userInfoStats', 'app\cunkebao\controller\StatsController@userInfoStats');
|
||||
});
|
||||
|
||||
|
||||
})->middleware(['jwt']);
|
||||
@@ -151,6 +156,7 @@ Route::group('v1/frontend', function () {
|
||||
Route::group('business/poster', function () {
|
||||
Route::post('getone', 'app\cunkebao\controller\plan\PosterWeChatMiniProgram@getPosterTaskData');
|
||||
Route::post('decryptphone', 'app\cunkebao\controller\plan\PosterWeChatMiniProgram@getPhoneNumber');
|
||||
Route::post('decryptphones', 'app\cunkebao\controller\plan\PosterWeChatMiniProgram@decryptphones');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -58,9 +58,9 @@ class ContentLibraryController extends Controller
|
||||
$data = [
|
||||
'name' => $param['name'],
|
||||
// 数据来源配置
|
||||
'sourceFriends' => $sourceType == 1 ? json_encode($param['friendsGroups']) : json_encode([]), // 选择的微信好友
|
||||
'sourceGroups' => $sourceType == 2 ? json_encode($param['wechatGroups']) : json_encode([]), // 选择的微信群
|
||||
'groupMembers' => $sourceType == 2 ? json_encode($param['groupMembers']) : json_encode([]), // 群组成员
|
||||
'sourceFriends' => $sourceType == 1 && isset($param['friendsGroups']) ? json_encode($param['friendsGroups']) : json_encode([]), // 选择的微信好友
|
||||
'sourceGroups' => $sourceType == 2 && isset($param['wechatGroups']) ? json_encode($param['wechatGroups']) : json_encode([]), // 选择的微信群
|
||||
'groupMembers' => $sourceType == 2 && isset($param['groupMembers']) ? json_encode($param['groupMembers']) : json_encode([]), // 群组成员
|
||||
// 关键词配置
|
||||
'keywordInclude' => $keywordInclude, // 包含的关键词
|
||||
'keywordExclude' => $keywordExclude, // 排除的关键词
|
||||
@@ -324,9 +324,9 @@ class ContentLibraryController extends Controller
|
||||
// 更新内容库基本信息
|
||||
$library->name = $param['name'];
|
||||
$library->sourceType = isset($param['sourceType']) ? $param['sourceType'] : 1;
|
||||
$library->sourceFriends = $param['sourceType'] == 1 ? json_encode($param['friendsGroups']) : json_encode([]);
|
||||
$library->sourceGroups = $param['sourceType'] == 2 ? json_encode($param['wechatGroups']) : json_encode([]);
|
||||
$library->groupMembers = $param['sourceType'] == 2 ? json_encode($param['groupMembers']) : json_encode([]);
|
||||
$library->sourceFriends = $param['sourceType'] == 1 && isset($param['friendsGroups']) ? json_encode($param['friendsGroups']) : json_encode([]);
|
||||
$library->sourceGroups = $param['sourceType'] == 2 && isset($param['wechatGroups']) ? json_encode($param['wechatGroups']) : json_encode([]);
|
||||
$library->groupMembers = $param['sourceType'] == 2 && isset($param['groupMembers']) ? json_encode($param['groupMembers']) : json_encode([]);
|
||||
$library->keywordInclude = $keywordInclude;
|
||||
$library->keywordExclude = $keywordExclude;
|
||||
$library->aiEnabled = isset($param['aiEnabled']) ? $param['aiEnabled'] : 0;
|
||||
@@ -840,7 +840,7 @@ class ContentLibraryController extends Controller
|
||||
$where = [
|
||||
['isDel', '=', 0], // 未删除
|
||||
['status', '=', 1], // 已开启
|
||||
['id', '=', 61], // 已开启
|
||||
// ['id', '=', 61], // 已开启
|
||||
];
|
||||
|
||||
// 查询符合条件的内容库
|
||||
|
||||
@@ -51,7 +51,6 @@ class StatsController extends Controller
|
||||
{
|
||||
|
||||
$num = $this->request->param('num', 4);
|
||||
|
||||
$planScene = Db::name('plan_scene')
|
||||
->field('id,name,image')
|
||||
->where(['status' => 1])
|
||||
@@ -196,4 +195,193 @@ class StatsController extends Controller
|
||||
|
||||
return successJson($data, '获取成功');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 场景获客数据统计
|
||||
* @return \think\response\Json
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function getFriendRequestTaskStats()
|
||||
{
|
||||
$companyId = $this->request->userInfo['companyId'];
|
||||
$taskId = $this->request->param('taskId', '');
|
||||
if(empty($taskId)){
|
||||
return errorJson('任务id不能为空');
|
||||
}
|
||||
|
||||
$task = Db::name('customer_acquisition_task')->where(['id' => $taskId, 'companyId' => $companyId,'deleteTime' => 0])->find();
|
||||
if(empty($task)){
|
||||
return errorJson('任务不存在或已删除');
|
||||
}
|
||||
|
||||
|
||||
// 1. 获取startTime和endTime,格式是日期
|
||||
$startTime = $this->request->param('startTime', '');
|
||||
$endTime = $this->request->param('endTime', '');
|
||||
|
||||
// 如果获取不到则默认为7天的跨度
|
||||
if (empty($startTime)) {
|
||||
$startTime = date('Y-m-d', time() - 86400 * 6);
|
||||
}
|
||||
if (empty($endTime)) {
|
||||
$endTime = date('Y-m-d', time());
|
||||
}
|
||||
|
||||
// 转换成时间戳格式
|
||||
$startTimestamp = strtotime($startTime . ' 00:00:00');
|
||||
$endTimestamp = strtotime($endTime . ' 23:59:59');
|
||||
|
||||
// 同时生成日期数组和时间戳二维数组
|
||||
$dateArray = [];
|
||||
$timestampArray = [];
|
||||
$currentTimestamp = $startTimestamp;
|
||||
|
||||
while ($currentTimestamp <= $endTimestamp) {
|
||||
// 生成日期格式数组
|
||||
$dateArray[] = date('m-d', $currentTimestamp);
|
||||
|
||||
// 生成时间戳二维数组
|
||||
$dayStart = $currentTimestamp;
|
||||
$dayEnd = strtotime('+1 day', $currentTimestamp) - 1; // 23:59:59
|
||||
$timestampArray[] = [$dayStart, $dayEnd];
|
||||
|
||||
$currentTimestamp = strtotime('+1 day', $currentTimestamp);
|
||||
}
|
||||
|
||||
|
||||
// 使用分组聚合统计,减少 SQL 次数
|
||||
$allRows = Db::name('task_customer')
|
||||
->field("FROM_UNIXTIME(createTime, '%m-%d') AS d, COUNT(*) AS c")
|
||||
->where(['task_id' => $taskId])
|
||||
->where('createTime', 'between', [$startTimestamp, $endTimestamp])
|
||||
->group('d')
|
||||
->select();
|
||||
|
||||
$successRows = Db::name('task_customer')
|
||||
->field("FROM_UNIXTIME(addTime, '%m-%d') AS d, COUNT(*) AS c")
|
||||
->where(['task_id' => $taskId])
|
||||
->where('addTime', 'between', [$startTimestamp, $endTimestamp])
|
||||
->whereIn('status', [1, 2, 4])
|
||||
->group('d')
|
||||
->select();
|
||||
|
||||
$passRows = Db::name('task_customer')
|
||||
->field("FROM_UNIXTIME(passTime, '%m-%d') AS d, COUNT(*) AS c")
|
||||
->where(['task_id' => $taskId])
|
||||
->where('passTime', 'between', [$startTimestamp, $endTimestamp])
|
||||
->group('d')
|
||||
->select();
|
||||
|
||||
$errorRows = Db::name('task_customer')
|
||||
->field("FROM_UNIXTIME(updateTime, '%m-%d') AS d, COUNT(*) AS c")
|
||||
->where(['task_id' => $taskId, 'status' => 3])
|
||||
->where('updateTime', 'between', [$startTimestamp, $endTimestamp])
|
||||
->group('d')
|
||||
->select();
|
||||
|
||||
// 将分组结果映射到连续日期数组
|
||||
$mapToSeries = function(array $rows) use ($dateArray) {
|
||||
$dict = [];
|
||||
foreach ($rows as $row) {
|
||||
// 兼容对象/数组两种返回
|
||||
$d = is_array($row) ? ($row['d'] ?? '') : ($row->d ?? '');
|
||||
$c = (int)(is_array($row) ? ($row['c'] ?? 0) : ($row->c ?? 0));
|
||||
if ($d !== '') {
|
||||
$dict[$d] = $c;
|
||||
}
|
||||
}
|
||||
$series = [];
|
||||
foreach ($dateArray as $d) {
|
||||
$series[] = $dict[$d] ?? 0;
|
||||
}
|
||||
return $series;
|
||||
};
|
||||
|
||||
$allNumArray = $mapToSeries($allRows);
|
||||
$successNumArray = $mapToSeries($successRows);
|
||||
$passNumArray = $mapToSeries($passRows);
|
||||
$errorNumArray = $mapToSeries($errorRows);
|
||||
|
||||
// 计算通过率和成功率
|
||||
$passRateArray = [];
|
||||
$successRateArray = [];
|
||||
|
||||
for ($i = 0; $i < count($dateArray); $i++) {
|
||||
// 通过率 = 通过数 / 总数
|
||||
$passRate = ($allNumArray[$i] > 0) ? round(($passNumArray[$i] / $allNumArray[$i]) * 100, 2) : 0;
|
||||
$passRateArray[] = $passRate;
|
||||
|
||||
// 成功率 = 成功数 / 总数
|
||||
$successRate = ($allNumArray[$i] > 0) ? round(($successNumArray[$i] / $allNumArray[$i]) * 100, 2) : 0;
|
||||
$successRateArray[] = $successRate;
|
||||
}
|
||||
|
||||
// 计算总体统计
|
||||
$totalAll = array_sum($allNumArray);
|
||||
$totalSuccess = array_sum($successNumArray);
|
||||
$totalPass = array_sum($passNumArray);
|
||||
$totalError = array_sum($errorNumArray);
|
||||
|
||||
$totalPassRate = ($totalAll > 0) ? round(($totalPass / $totalAll) * 100, 2) : 0;
|
||||
$totalSuccessRate = ($totalAll > 0) ? round(($totalSuccess / $totalAll) * 100, 2) : 0;
|
||||
|
||||
// 返回结果
|
||||
$result = [
|
||||
'startTime' => $startTime,
|
||||
'endTime' => $endTime,
|
||||
'dateArray' => $dateArray,
|
||||
'allNumArray' => $allNumArray,
|
||||
'successNumArray' => $successNumArray,
|
||||
'passNumArray' => $passNumArray,
|
||||
'errorNumArray' => $errorNumArray,
|
||||
'passRateArray' => $passRateArray,
|
||||
'successRateArray' => $successRateArray,
|
||||
'totalStats' => [
|
||||
'totalAll' => $totalAll,
|
||||
'totalSuccess' => $totalSuccess,
|
||||
'totalPass' => $totalPass,
|
||||
'totalError' => $totalError,
|
||||
'totalPassRate' => $totalPassRate,
|
||||
'totalSuccessRate' => $totalSuccessRate
|
||||
]
|
||||
];
|
||||
|
||||
return successJson($result, '获取成功');
|
||||
}
|
||||
|
||||
|
||||
public function userInfoStats()
|
||||
{
|
||||
$companyId = $this->request->userInfo['companyId'];
|
||||
$userId = $this->request->userInfo['id'];
|
||||
$isAdmin = $this->request->userInfo['isAdmin'];
|
||||
|
||||
|
||||
$device = Db::name('device')->where(['companyId' => $companyId,'deleteTime' => 0]);
|
||||
$wechat = Db::name('wechat_customer')->where(['companyId' => $companyId]);
|
||||
$contentLibrary = Db::name('content_library')->where(['companyId' => $companyId,'isDel' => 0]);
|
||||
$user = Db::name('wechat_friendship')->where(['companyId' => $companyId,'deleteTime' => 0]);
|
||||
|
||||
if(empty($isAdmin)){
|
||||
$contentLibrary = $contentLibrary->where(['userId' => $userId]);
|
||||
}
|
||||
|
||||
$deviceNum = $device->count();
|
||||
$wechatNum = $wechat->count();
|
||||
$contentLibraryNum = $contentLibrary->count();
|
||||
$userNum = $user->count();
|
||||
|
||||
$data = [
|
||||
'deviceNum' => $deviceNum,
|
||||
'wechatNum' => $wechatNum,
|
||||
'contentLibraryNum' => $contentLibraryNum,
|
||||
'userNum' => $userNum,
|
||||
];
|
||||
return successJson($data, '获取成功');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace app\cunkebao\controller;
|
||||
|
||||
use app\common\model\Device as DeviceModel;
|
||||
use app\common\model\DeviceWechatLogin as DeviceWechatLoginModel;
|
||||
use app\common\model\WechatCustomer as WechatCustomerModel;
|
||||
use app\cunkebao\model\Workbench;
|
||||
use app\cunkebao\model\WorkbenchAutoLike;
|
||||
use app\cunkebao\model\WorkbenchMomentsSync;
|
||||
@@ -57,7 +58,7 @@ class WorkbenchController extends Controller
|
||||
$workbench = new Workbench;
|
||||
$workbench->name = $param['name'];
|
||||
$workbench->type = $param['type'];
|
||||
$workbench->status = 1;
|
||||
$workbench->status = !empty($param['status']) ? 1 : 0;
|
||||
$workbench->autoStart = !empty($param['autoStart']) ? 1 : 0;
|
||||
$workbench->userId = $userInfo['id'];
|
||||
$workbench->companyId = $userInfo['companyId'];
|
||||
@@ -122,11 +123,16 @@ class WorkbenchController extends Controller
|
||||
case self::TYPE_GROUP_CREATE: // 自动建群
|
||||
$config = new WorkbenchGroupCreate;
|
||||
$config->workbenchId = $workbench->id;
|
||||
$config->groupNamePrefix = $param['groupNamePrefix'];
|
||||
$config->maxGroups = $param['maxGroups'];
|
||||
$config->membersPerGroup = $param['membersPerGroup'];
|
||||
$config->devices = json_encode($param['deveiceGroups']);
|
||||
$config->targetGroups = json_encode($param['targetGroups']);
|
||||
$config->devices = json_encode($param['deveiceGroups'], 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'];
|
||||
$config->poolGroups = json_encode($param['poolGroups'] ?? []);
|
||||
$config->wechatGroups = json_encode($param['wechatGroups'] ?? []);
|
||||
$config->createTime = time();
|
||||
$config->updateTime = time();
|
||||
$config->save();
|
||||
@@ -196,6 +202,9 @@ class WorkbenchController extends Controller
|
||||
'groupPush' => function ($query) {
|
||||
$query->field('workbenchId,pushType,startTime,endTime,maxPerDay,pushOrder,isLoop,status,groups,contentLibraries');
|
||||
},
|
||||
'groupCreate' => function($query) {
|
||||
$query->field('workbenchId,devices,startTime,endTime,groupSizeMin,groupSizeMax,maxGroupsPerDay,groupNameTemplate,groupDescription,poolGroups,wechatGroups');
|
||||
},
|
||||
'user' => function ($query) {
|
||||
$query->field('id,username');
|
||||
}
|
||||
@@ -270,7 +279,7 @@ class WorkbenchController extends Controller
|
||||
$item->config->status = $item->config->status;
|
||||
$item->config->groups = json_decode($item->config->groups, true);
|
||||
$item->config->contentLibraries = json_decode($item->config->contentLibraries, true);
|
||||
$item->config->lastPushTime = '22222';
|
||||
$item->config->lastPushTime = '';
|
||||
}
|
||||
unset($item->groupPush, $item->group_push);
|
||||
break;
|
||||
@@ -278,7 +287,8 @@ class WorkbenchController extends Controller
|
||||
if (!empty($item->groupCreate)) {
|
||||
$item->config = $item->groupCreate;
|
||||
$item->config->devices = json_decode($item->config->devices, true);
|
||||
$item->config->targetGroups = json_decode($item->config->targetGroups, true);
|
||||
$item->config->poolGroups = json_decode($item->config->poolGroups, true);
|
||||
$item->config->wechatGroups = json_decode($item->config->wechatGroups, true);
|
||||
}
|
||||
unset($item->groupCreate, $item->group_create);
|
||||
break;
|
||||
@@ -384,11 +394,10 @@ class WorkbenchController extends Controller
|
||||
'groupPush' => function ($query) {
|
||||
$query->field('workbenchId,pushType,startTime,endTime,maxPerDay,pushOrder,isLoop,status,groups,contentLibraries');
|
||||
},
|
||||
// 'groupCreate' => function($query) {
|
||||
// $query->field('workbenchId,groupNamePrefix,maxGroups,membersPerGroup,devices,targetGroups');
|
||||
// }
|
||||
'groupCreate' => function($query) {
|
||||
$query->field('workbenchId,devices,startTime,endTime,groupSizeMin,groupSizeMax,maxGroupsPerDay,groupNameTemplate,groupDescription,poolGroups,wechatGroups');
|
||||
}
|
||||
];
|
||||
|
||||
$workbench = Workbench::where([
|
||||
['id', '=', $id],
|
||||
['userId', '=', $this->request->userInfo['id']],
|
||||
@@ -453,65 +462,6 @@ class WorkbenchController extends Controller
|
||||
$workbench->config = $workbench->groupPush;
|
||||
$workbench->config->wechatGroups = json_decode($workbench->config->groups, true);
|
||||
$workbench->config->contentLibraries = json_decode($workbench->config->contentLibraries, true);
|
||||
|
||||
/* // 获取群组内容库
|
||||
$contentLibraryList = ContentLibrary::where('id', 'in', $workbench->config->contentLibraries)
|
||||
->field('id,name,sourceFriends,sourceGroups,keywordInclude,keywordExclude,aiEnabled,aiPrompt,timeEnabled,timeStart,timeEnd,status,sourceType,userId,createTime,updateTime')
|
||||
->with(['user' => function ($query) {
|
||||
$query->field('id,username');
|
||||
}])
|
||||
->order('id', 'desc')
|
||||
->select();
|
||||
|
||||
// 处理JSON字段
|
||||
foreach ($contentLibraryList as &$item) {
|
||||
$item['sourceFriends'] = json_decode($item['sourceFriends'] ?: '[]', true);
|
||||
$item['sourceGroups'] = json_decode($item['sourceGroups'] ?: '[]', true);
|
||||
$item['keywordInclude'] = json_decode($item['keywordInclude'] ?: '[]', true);
|
||||
$item['keywordExclude'] = json_decode($item['keywordExclude'] ?: '[]', true);
|
||||
// 添加创建人名称
|
||||
$item['creatorName'] = $item['user']['username'] ?? '';
|
||||
$item['itemCount'] = Db::name('content_item')->where('libraryId', $item['id'])->count();
|
||||
|
||||
// 获取好友详细信息
|
||||
if (!empty($item['sourceFriends'] && $item['sourceType'] == 1)) {
|
||||
$friendIds = $item['sourceFriends'];
|
||||
$friendsInfo = [];
|
||||
|
||||
if (!empty($friendIds)) {
|
||||
// 查询好友信息,使用wechat_friendship表
|
||||
$friendsInfo = Db::name('wechat_friendship')->alias('wf')
|
||||
->field('wf.id,wf.wechatId, wa.nickname, wa.avatar')
|
||||
->join('wechat_account wa', 'wf.wechatId = wa.wechatId')
|
||||
->whereIn('wf.id', $friendIds)
|
||||
->select();
|
||||
}
|
||||
|
||||
// 将好友信息添加到返回数据中
|
||||
$item['selectedFriends'] = $friendsInfo;
|
||||
}
|
||||
|
||||
|
||||
if (!empty($item['sourceGroups']) && $item['sourceType'] == 2) {
|
||||
$groupIds = $item['sourceGroups'];
|
||||
$groupsInfo = [];
|
||||
|
||||
if (!empty($groupIds)) {
|
||||
// 查询群组信息
|
||||
$groupsInfo = Db::name('wechat_group')->alias('g')
|
||||
->field('g.id, g.chatroomId, g.name, g.avatar, g.ownerWechatId')
|
||||
->whereIn('g.id', $groupIds)
|
||||
->select();
|
||||
}
|
||||
|
||||
// 将群组信息添加到返回数据中
|
||||
$item['selectedGroups'] = $groupsInfo;
|
||||
}
|
||||
|
||||
unset($item['user']); // 移除关联数据
|
||||
}
|
||||
$workbench->config->contentLibraryList = $contentLibraryList;*/
|
||||
|
||||
unset($workbench->groupPush, $workbench->group_push);
|
||||
}
|
||||
break;
|
||||
@@ -520,7 +470,9 @@ class WorkbenchController extends Controller
|
||||
if (!empty($workbench->groupCreate)) {
|
||||
$workbench->config = $workbench->groupCreate;
|
||||
$workbench->config->deveiceGroups = json_decode($workbench->config->devices, true);
|
||||
$workbench->config->targetGroups = json_decode($workbench->config->targetGroups, true);
|
||||
$workbench->config->poolGroups = json_decode($workbench->config->poolGroups, true);
|
||||
$workbench->config->wechatGroups = json_decode($workbench->config->wechatGroups, true);
|
||||
unset($workbench->groupCreate, $workbench->group_create);
|
||||
}
|
||||
break;
|
||||
//流量分发
|
||||
@@ -533,7 +485,6 @@ class WorkbenchController extends Controller
|
||||
$config_item = Db::name('workbench_traffic_config_item')->where(['workbenchId' => $workbench->id])->order('id DESC')->find();
|
||||
$workbench->config->lastUpdated = !empty($config_item) ? date('Y-m-d H:i', $config_item['createTime']) : '--';
|
||||
|
||||
|
||||
//统计
|
||||
$labels = $workbench->config->pools;
|
||||
$totalUsers = Db::table('s2_wechat_friend')->alias('wf')
|
||||
@@ -600,13 +551,20 @@ class WorkbenchController extends Controller
|
||||
->field([
|
||||
'd.id', 'd.imei', 'd.memo', 'd.alive',
|
||||
'l.wechatId',
|
||||
'a.nickname', 'a.alias', 'a.avatar', 'a.alias'
|
||||
'a.nickname', 'a.alias', 'a.avatar', 'a.alias', '0 totalFriend'
|
||||
])
|
||||
->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')
|
||||
->whereIn('d.id', $workbench->config->deveiceGroups)
|
||||
->order('d.id desc')
|
||||
->select();
|
||||
|
||||
foreach ($deviceList as &$device) {
|
||||
$curstomer = WechatCustomerModel::field('friendShip')->where(['wechatId' => $device['wechatId']])->find();
|
||||
$device['totalFriend'] = $curstomer->friendShip->totalFriend ?? 0;
|
||||
}
|
||||
unset($device);
|
||||
|
||||
$workbench->config->deveiceGroupsOptions = $deviceList;
|
||||
} else {
|
||||
$workbench->config->deveiceGroupsOptions = [];
|
||||
@@ -648,6 +606,21 @@ class WorkbenchController extends Controller
|
||||
$workbench->config->accountGroupsOptions = [];
|
||||
}
|
||||
|
||||
if (!empty($workbench->config->poolGroups)){
|
||||
$poolGroupsOptions = Db::name('traffic_source_package')->alias('tsp')
|
||||
->join('traffic_source_package_item tspi','tspi.packageId=tsp.id','left')
|
||||
->whereIn('tsp.companyId', [$this->request->userInfo['companyId'],0])
|
||||
->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;
|
||||
}else{
|
||||
$workbench->config->poolGroupsOptions = [];
|
||||
}
|
||||
|
||||
|
||||
|
||||
return json(['code' => 200, 'msg' => '获取成功', 'data' => $workbench]);
|
||||
}
|
||||
|
||||
@@ -684,6 +657,7 @@ class WorkbenchController extends Controller
|
||||
try {
|
||||
// 更新工作台基本信息
|
||||
$workbench->name = $param['name'];
|
||||
$workbench->status = !empty($param['status']) ? 1 : 0;
|
||||
$workbench->autoStart = !empty($param['autoStart']) ? 1 : 0;
|
||||
$workbench->updateTime = time();
|
||||
$workbench->save();
|
||||
@@ -760,11 +734,16 @@ class WorkbenchController extends Controller
|
||||
case self::TYPE_GROUP_CREATE:
|
||||
$config = WorkbenchGroupCreate::where('workbenchId', $param['id'])->find();
|
||||
if ($config) {
|
||||
$config->groupNamePrefix = $param['groupNamePrefix'];
|
||||
$config->maxGroups = $param['maxGroups'];
|
||||
$config->membersPerGroup = $param['membersPerGroup'];
|
||||
$config->devices = json_encode($param['deveiceGroups']);
|
||||
$config->targetGroups = json_encode($param['targetGroups']);
|
||||
$config->devices = json_encode($param['deveiceGroups'], 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'];
|
||||
$config->poolGroups = json_encode($param['poolGroups'] ?? []);
|
||||
$config->wechatGroups = json_encode($param['wechatGroups'] ?? []);
|
||||
$config->updateTime = time();
|
||||
$config->save();
|
||||
}
|
||||
@@ -904,7 +883,8 @@ class WorkbenchController extends Controller
|
||||
$newConfig->contentTypes = $config->contentTypes;
|
||||
$newConfig->devices = $config->devices;
|
||||
$newConfig->friends = $config->friends;
|
||||
//$newConfig->targetGroups = $config->targetGroups;
|
||||
$newConfig->createTime = time();
|
||||
$newConfig->updateTime = time();
|
||||
$newConfig->save();
|
||||
}
|
||||
break;
|
||||
@@ -921,6 +901,8 @@ class WorkbenchController extends Controller
|
||||
$newConfig->accountType = $config->accountType;
|
||||
$newConfig->devices = $config->devices;
|
||||
$newConfig->contentLibraries = $config->contentLibraries;
|
||||
$newConfig->createTime = time();
|
||||
$newConfig->updateTime = time();
|
||||
$newConfig->save();
|
||||
}
|
||||
break;
|
||||
@@ -938,6 +920,8 @@ class WorkbenchController extends Controller
|
||||
$newConfig->status = $config->status;
|
||||
$newConfig->groups = $config->groups;
|
||||
$newConfig->contentLibraries = $config->contentLibraries;
|
||||
$newConfig->createTime = time();
|
||||
$newConfig->updateTime = time();
|
||||
$newConfig->save();
|
||||
}
|
||||
break;
|
||||
@@ -946,12 +930,18 @@ class WorkbenchController extends Controller
|
||||
if ($config) {
|
||||
$newConfig = new WorkbenchGroupCreate;
|
||||
$newConfig->workbenchId = $newWorkbench->id;
|
||||
$newConfig->groupNamePrefix = $config->groupNamePrefix;
|
||||
$newConfig->maxGroups = $config->maxGroups;
|
||||
$newConfig->membersPerGroup = $config->membersPerGroup;
|
||||
$newConfig->devices = $config->devices;
|
||||
$newConfig->targetGroups = $config->targetGroups;
|
||||
$newConfig->account = $config->account;
|
||||
$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;
|
||||
$newConfig->poolGroups = $config->poolGroups;
|
||||
$newConfig->wechatGroups = $config->wechatGroups;
|
||||
$newConfig->createTime = time();
|
||||
$newConfig->updateTime = time();
|
||||
$newConfig->save();
|
||||
}
|
||||
break;
|
||||
@@ -982,8 +972,6 @@ class WorkbenchController extends Controller
|
||||
// 查询点赞记录
|
||||
$list = Db::name('workbench_auto_like_item')->alias('wali')
|
||||
->join(['s2_wechat_moments' => 'wm'], 'wali.snsId = wm.snsId')
|
||||
->join(['s2_wechat_account' => 'wa'], 'wali.wechatAccountId = wa.id')
|
||||
->join(['s2_wechat_friend' => 'wf'], 'wali.wechatFriendId = wf.id')
|
||||
->field([
|
||||
'wali.id',
|
||||
'wali.workbenchId',
|
||||
@@ -996,10 +984,6 @@ class WorkbenchController extends Controller
|
||||
'wm.resUrls',
|
||||
'wm.createTime as momentTime',
|
||||
'wm.userName',
|
||||
'wa.nickName as operatorName',
|
||||
'wa.avatar as operatorAvatar',
|
||||
'wf.nickName as friendName',
|
||||
'wf.avatar as friendAvatar',
|
||||
])
|
||||
->where($where)
|
||||
->order('wali.createTime', 'desc')
|
||||
@@ -1007,8 +991,36 @@ class WorkbenchController extends Controller
|
||||
->page($page, $limit)
|
||||
->select();
|
||||
|
||||
|
||||
// 处理数据
|
||||
foreach ($list as &$item) {
|
||||
//处理用户信息
|
||||
$friend = Db::table('s2_wechat_friend')
|
||||
->where(['id' => $item['wechatFriendId']])
|
||||
->field('nickName,avatar')
|
||||
->find();
|
||||
if(!empty($friend)){
|
||||
$item['friendName'] = $friend['nickName'];
|
||||
$item['friendAvatar'] = $friend['avatar'];
|
||||
}else{
|
||||
$item['friendName'] = '';
|
||||
$item['friendAvatar'] = '';
|
||||
}
|
||||
|
||||
|
||||
//处理客服
|
||||
$friend = Db::table('s2_wechat_account')
|
||||
->where(['id' => $item['wechatAccountId']])
|
||||
->field('nickName,avatar')
|
||||
->find();
|
||||
if(!empty($friend)){
|
||||
$item['operatorName'] = $friend['nickName'];
|
||||
$item['operatorAvatar'] = $friend['avatar'];
|
||||
}else{
|
||||
$item['operatorName'] = '';
|
||||
$item['operatorAvatar'] = '';
|
||||
}
|
||||
|
||||
// 处理时间格式
|
||||
$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']) : '';
|
||||
@@ -1565,4 +1577,56 @@ class WorkbenchController extends Controller
|
||||
}
|
||||
|
||||
|
||||
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' => '参数错误']);
|
||||
}
|
||||
|
||||
$workbench = Db::name('workbench')->where(['id' => $workbenchId,'isDel' => 0,'companyId' => $companyId,'type' => 5])->find();
|
||||
|
||||
if (empty($workbench)){
|
||||
return json(['code' => 400, 'msg' => '该任务不存在或已删除']);
|
||||
}
|
||||
$query = Db::name('workbench_traffic_config_item')->alias('wtc')
|
||||
->join(['s2_wechat_friend' => 'wf'],'wtc.wechatFriendId = wf.id')
|
||||
->join('users u','wtc.wechatAccountId = u.s2_accountId','left')
|
||||
->field([
|
||||
'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');
|
||||
|
||||
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]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@ use app\common\model\User as UserModel;
|
||||
use app\cunkebao\controller\BaseController;
|
||||
use library\ResponseHelper;
|
||||
use think\Db;
|
||||
use app\api\controller\DeviceController as apiDevice;
|
||||
|
||||
/**
|
||||
* 设备管理控制器
|
||||
@@ -83,11 +84,17 @@ class DeleteDeviceV1Controller extends BaseController
|
||||
*/
|
||||
protected function deleteCkbAbout(int $id): self
|
||||
{
|
||||
$this->deleteDevice($id);
|
||||
$this->deleteDeviceConf($id);
|
||||
$this->deleteDeviceUser($id);
|
||||
|
||||
return $this;
|
||||
$apiDevice = new ApiDevice();
|
||||
$res = $apiDevice->delDevice($id);
|
||||
$res = json_decode($res, true);
|
||||
if ($res['code'] == 200){
|
||||
$this->deleteDevice($id);
|
||||
$this->deleteDeviceConf($id);
|
||||
$this->deleteDeviceUser($id);
|
||||
return $this;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -75,7 +75,7 @@ class GetDeviceListV1Controller extends BaseController
|
||||
->field([
|
||||
'd.id', 'd.imei', 'd.memo', 'd.alive',
|
||||
'l.wechatId',
|
||||
'a.nickname', 'a.alias', '0 totalFriend'
|
||||
'a.nickname', 'a.alias', 'a.avatar', '0 totalFriend'
|
||||
])
|
||||
->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')
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace app\cunkebao\controller\plan;
|
||||
|
||||
use app\common\model\Device as DeviceModel;
|
||||
use app\common\model\DeviceWechatLogin as DeviceWechatLoginModel;
|
||||
use app\common\model\WechatCustomer as WechatCustomerModel;
|
||||
use library\ResponseHelper;
|
||||
use think\Controller;
|
||||
use think\Db;
|
||||
@@ -118,19 +119,19 @@ class GetAddFriendPlanDetailV1Controller extends Controller
|
||||
|
||||
// 解析JSON字段
|
||||
$sceneConf = json_decode($plan['sceneConf'], true) ?: [];
|
||||
$sceneConf['wechatGroups'] = $sceneConf['groupSelected'];
|
||||
$reqConf = json_decode($plan['reqConf'], true) ?: [];
|
||||
$reqConf['deveiceGroups'] = $reqConf['device'];
|
||||
$msgConf = json_decode($plan['msgConf'], true) ?: [];
|
||||
$tagConf = json_decode($plan['tagConf'], true) ?: [];
|
||||
|
||||
|
||||
|
||||
if(!empty($sceneConf['wechatGroups'])){
|
||||
$groupList = Db::name('wechat_group')->alias('wg')
|
||||
->join('wechat_account wa', 'wa.wechatId = wg.ownerWechatId')
|
||||
->where('wg.id', 'in', $sceneConf['wechatGroups'])
|
||||
->order('wg.id', 'desc')
|
||||
->field('wg.id,wg.name as groupName,wg.ownerWechatId,wa.nickName,wa.avatar,wa.alias,wg.avatar as groupAvatar')
|
||||
->field('wg.id,wg.name,wg.chatroomId,wg.ownerWechatId,wa.nickName as ownerNickName,wa.avatar as ownerAvatar,wa.alias as ownerAlias,wg.avatar')
|
||||
->select();
|
||||
$sceneConf['wechatGroupsOptions'] = $groupList;
|
||||
}else{
|
||||
@@ -138,20 +139,23 @@ class GetAddFriendPlanDetailV1Controller extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (!empty($reqConf['deveiceGroups'])){
|
||||
$deveiceGroupsOptions = DeviceModel::alias('d')
|
||||
->field([
|
||||
'd.id', 'd.imei', 'd.memo', 'd.alive',
|
||||
'l.wechatId',
|
||||
'a.nickname', 'a.alias', '0 totalFriend'
|
||||
'a.nickname', 'a.alias', '0 totalFriend', '0 totalFriend'
|
||||
])
|
||||
->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')
|
||||
->order('d.id desc')
|
||||
->whereIn('d.id',$reqConf['deveiceGroups'])
|
||||
->select();
|
||||
foreach ($deveiceGroupsOptions as &$device) {
|
||||
$curstomer = WechatCustomerModel::field('friendShip')->where(['wechatId' => $device['wechatId']])->find();
|
||||
$device['totalFriend'] = $curstomer->friendShip->totalFriend ?? 0;
|
||||
}
|
||||
unset($device);
|
||||
$reqConf['deveiceGroupsOptions'] = $deveiceGroupsOptions;
|
||||
}else{
|
||||
$reqConf['deveiceGroupsOptions'] = [];
|
||||
|
||||
@@ -16,7 +16,7 @@ class PostCreateAddFriendPlanV1Controller extends BaseController
|
||||
|
||||
/**
|
||||
* 生成唯一API密钥
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateApiKey()
|
||||
@@ -24,7 +24,7 @@ class PostCreateAddFriendPlanV1Controller extends BaseController
|
||||
// 生成5组随机字符串,每组5个字符
|
||||
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
$apiKey = '';
|
||||
|
||||
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$segment = '';
|
||||
for ($j = 0; $j < 5; $j++) {
|
||||
@@ -32,17 +32,17 @@ class PostCreateAddFriendPlanV1Controller extends BaseController
|
||||
}
|
||||
$apiKey .= ($i > 0 ? '-' : '') . $segment;
|
||||
}
|
||||
|
||||
|
||||
// 检查是否已存在
|
||||
$exists = Db::name('customer_acquisition_task')
|
||||
->where('apiKey', $apiKey)
|
||||
->find();
|
||||
|
||||
|
||||
if ($exists) {
|
||||
// 如果已存在,递归重新生成
|
||||
return $this->generateApiKey();
|
||||
}
|
||||
|
||||
|
||||
return $apiKey;
|
||||
}
|
||||
|
||||
@@ -55,35 +55,34 @@ class PostCreateAddFriendPlanV1Controller extends BaseController
|
||||
{
|
||||
try {
|
||||
$params = $this->request->param();
|
||||
|
||||
|
||||
// 验证必填字段
|
||||
if (empty($params['name'])) {
|
||||
return ResponseHelper::error('计划名称不能为空', 400);
|
||||
}
|
||||
|
||||
|
||||
if (empty($params['sceneId'])) {
|
||||
return ResponseHelper::error('场景ID不能为空', 400);
|
||||
}
|
||||
|
||||
|
||||
if (empty($params['deveiceGroups'])) {
|
||||
return ResponseHelper::error('请选择设备', 400);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 归类参数
|
||||
$msgConf = isset($params['messagePlans']) ? $params['messagePlans'] : [];
|
||||
$tagConf = [
|
||||
'scenarioTags' => $params['scenarioTags'] ?? [],
|
||||
'customTags' => $params['customTags'] ?? [],
|
||||
'customTags' => $params['customTags'] ?? [],
|
||||
];
|
||||
$reqConf = [
|
||||
'device' => $params['deveiceGroups'] ?? [],
|
||||
'remarkType' => $params['remarkType'] ?? '',
|
||||
'greeting' => $params['greeting'] ?? '',
|
||||
'device' => $params['deveiceGroups'] ?? [],
|
||||
'remarkType' => $params['remarkType'] ?? '',
|
||||
'greeting' => $params['greeting'] ?? '',
|
||||
'addFriendInterval' => $params['addFriendInterval'] ?? '',
|
||||
'startTime' => $params['startTime'] ?? '',
|
||||
'endTime' => $params['endTime'] ?? '',
|
||||
'startTime' => $params['startTime'] ?? '',
|
||||
'endTime' => $params['endTime'] ?? '',
|
||||
];
|
||||
// 其余参数归为sceneConf
|
||||
$sceneConf = $params;
|
||||
@@ -112,18 +111,18 @@ class PostCreateAddFriendPlanV1Controller extends BaseController
|
||||
|
||||
// 构建数据
|
||||
$data = [
|
||||
'name' => $params['name'],
|
||||
'sceneId' => $params['sceneId'],
|
||||
'name' => $params['name'],
|
||||
'sceneId' => $params['sceneId'],
|
||||
'sceneConf' => json_encode($sceneConf, JSON_UNESCAPED_UNICODE),
|
||||
'reqConf' => json_encode($reqConf, JSON_UNESCAPED_UNICODE),
|
||||
'msgConf' => json_encode($msgConf, JSON_UNESCAPED_UNICODE),
|
||||
'tagConf' => json_encode($tagConf, JSON_UNESCAPED_UNICODE),
|
||||
'userId' => $this->getUserInfo('id'),
|
||||
'reqConf' => json_encode($reqConf, JSON_UNESCAPED_UNICODE),
|
||||
'msgConf' => json_encode($msgConf, JSON_UNESCAPED_UNICODE),
|
||||
'tagConf' => json_encode($tagConf, JSON_UNESCAPED_UNICODE),
|
||||
'userId' => $this->getUserInfo('id'),
|
||||
'companyId' => $this->getUserInfo('companyId'),
|
||||
'status' => 1,
|
||||
'apiKey' => $this->generateApiKey(), // 生成API密钥
|
||||
'createTime'=> time(),
|
||||
'updateTime'=> time(),
|
||||
'status' => !empty($params['status']) ? 1 : 0,
|
||||
'apiKey' => $this->generateApiKey(), // 生成API密钥
|
||||
'createTime' => time(),
|
||||
'updateTime' => time(),
|
||||
];
|
||||
|
||||
|
||||
@@ -131,15 +130,15 @@ class PostCreateAddFriendPlanV1Controller extends BaseController
|
||||
Db::startTrans();
|
||||
// 插入数据
|
||||
$planId = Db::name('customer_acquisition_task')->insertGetId($data);
|
||||
|
||||
|
||||
if (!$planId) {
|
||||
throw new \Exception('添加计划失败');
|
||||
}
|
||||
|
||||
|
||||
//订单
|
||||
if($params['sceneId'] == 2){
|
||||
if(!empty($params['orderTableFile'])){
|
||||
if ($params['sceneId'] == 2) {
|
||||
if (!empty($params['orderTableFile'])) {
|
||||
// 先下载到本地临时文件,再分析,最后删除
|
||||
$originPath = $params['orderTableFile'];
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'order_');
|
||||
@@ -172,12 +171,12 @@ class PostCreateAddFriendPlanV1Controller extends BaseController
|
||||
|
||||
foreach ($data as $cols) {
|
||||
$rows[] = [
|
||||
'name' => isset($cols[0]) ? trim($cols[0]) : '',
|
||||
'phone' => isset($cols[1]) ? trim($cols[1]) : '',
|
||||
'wechat' => isset($cols[2]) ? trim($cols[2]) : '',
|
||||
'source' => isset($cols[3]) ? trim($cols[3]) : '',
|
||||
'name' => isset($cols[0]) ? trim($cols[0]) : '',
|
||||
'phone' => isset($cols[1]) ? trim($cols[1]) : '',
|
||||
'wechatId' => isset($cols[2]) ? trim($cols[2]) : '',
|
||||
'source' => isset($cols[3]) ? trim($cols[3]) : '',
|
||||
'orderAmount' => isset($cols[4]) ? trim($cols[4]) : '',
|
||||
'orderDate' => isset($cols[5]) ? trim($cols[5]) : '',
|
||||
'orderDate' => isset($cols[5]) ? trim($cols[5]) : '',
|
||||
];
|
||||
}
|
||||
} elseif ($ext === 'csv') {
|
||||
@@ -190,12 +189,12 @@ class PostCreateAddFriendPlanV1Controller extends BaseController
|
||||
$cols = str_getcsv($line);
|
||||
if (count($cols) >= 6) {
|
||||
$rows[] = [
|
||||
'name' => isset($cols[0]) ? trim($cols[0]) : '',
|
||||
'phone' => isset($cols[1]) ? trim($cols[1]) : '',
|
||||
'wechat' => isset($cols[2]) ? trim($cols[2]) : '',
|
||||
'source' => isset($cols[3]) ? trim($cols[3]) : '',
|
||||
'name' => isset($cols[0]) ? trim($cols[0]) : '',
|
||||
'phone' => isset($cols[1]) ? trim($cols[1]) : '',
|
||||
'wechatId' => isset($cols[2]) ? trim($cols[2]) : '',
|
||||
'source' => isset($cols[3]) ? trim($cols[3]) : '',
|
||||
'orderAmount' => isset($cols[4]) ? trim($cols[4]) : '',
|
||||
'orderDate' => isset($cols[5]) ? trim($cols[5]) : '',
|
||||
'orderDate' => isset($cols[5]) ? trim($cols[5]) : '',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -206,84 +205,115 @@ class PostCreateAddFriendPlanV1Controller extends BaseController
|
||||
}
|
||||
// 删除临时文件
|
||||
unlink($tmpFile);
|
||||
|
||||
// 1000条为一组进行批量处理
|
||||
$batchSize = 1000;
|
||||
$totalRows = count($rows);
|
||||
|
||||
for ($i = 0; $i < $totalRows; $i += $batchSize) {
|
||||
$batchRows = array_slice($rows, $i, $batchSize);
|
||||
|
||||
if (!empty($batchRows)) {
|
||||
// 1. 提取当前批次的phone
|
||||
$phones = [];
|
||||
foreach ($batchRows as $row) {
|
||||
$phone = !empty($row['phone']) ? $row['phone'] : $row['wechat'];
|
||||
if (!empty($phone)) {
|
||||
$phones[] = $phone;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 批量查询已存在的phone
|
||||
$existingPhones = [];
|
||||
if (!empty($phones)) {
|
||||
$existing = Db::name('task_customer')
|
||||
->where('task_id', $planId)
|
||||
->where('phone', 'in', $phones)
|
||||
->field('phone')
|
||||
->select();
|
||||
$existingPhones = array_column($existing, 'phone');
|
||||
}
|
||||
|
||||
// 3. 过滤出新数据,批量插入
|
||||
$newData = [];
|
||||
foreach ($batchRows as $row) {
|
||||
$phone = !empty($row['phone']) ? $row['phone'] : $row['wechat'];
|
||||
if (!empty($phone) && !in_array($phone, $existingPhones)) {
|
||||
$newData[] = [
|
||||
'task_id' => $planId,
|
||||
'name' => $row['name'] ?? '',
|
||||
'source' => $row['source'] ?? '',
|
||||
'phone' => $phone,
|
||||
'tags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'siteTags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'createTime' => time(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 批量插入新数据
|
||||
if (!empty($newData)) {
|
||||
Db::name('task_customer')->insertAll($newData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//群获客
|
||||
if($params['sceneId'] == 7){
|
||||
//电话获客
|
||||
if ($params['sceneId'] == 5) {
|
||||
$rows = Db::name('call_recording')
|
||||
->where('companyId', $this->getUserInfo('companyId'))
|
||||
->group('phone')
|
||||
->field('id,phone')
|
||||
->select();
|
||||
}
|
||||
|
||||
|
||||
//群获客
|
||||
if ($params['sceneId'] == 7) {
|
||||
if (!empty($params['wechatGroups']) && is_array($params['wechatGroups'])) {
|
||||
$rows = Db::name('wechat_group_member')->alias('gm')
|
||||
->join('wechat_account wa', 'gm.identifier = wa.wechatId')
|
||||
->where('gm.companyId', $this->getUserInfo('companyId'))
|
||||
->whereIn('gm.groupId', $params['wechatGroups'])
|
||||
->group('gm.identifier')
|
||||
->column('wa.id,wa.wechatId,wa.alias,wa.phone');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (in_array($params['sceneId'], [2, 5, 7]) && !empty($rows) && is_array($rows)) {
|
||||
// 1000条为一组进行批量处理
|
||||
$batchSize = 1000;
|
||||
$totalRows = count($rows);
|
||||
|
||||
for ($i = 0; $i < $totalRows; $i += $batchSize) {
|
||||
$batchRows = array_slice($rows, $i, $batchSize);
|
||||
|
||||
if (!empty($batchRows)) {
|
||||
// 1. 提取当前批次的phone
|
||||
$phones = [];
|
||||
foreach ($batchRows as $row) {
|
||||
if (!empty($row['phone'])) {
|
||||
$phone = $row['phone'];
|
||||
} elseif (!empty($row['alias'])) {
|
||||
$phone = $row['alias'];
|
||||
} else {
|
||||
$phone = $row['wechatId'];
|
||||
}
|
||||
if (!empty($phone)) {
|
||||
$phones[] = $phone;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 批量查询已存在的phone
|
||||
$existingPhones = [];
|
||||
if (!empty($phones)) {
|
||||
$existing = Db::name('task_customer')
|
||||
->where('task_id', $planId)
|
||||
->where('phone', 'in', $phones)
|
||||
->field('phone')
|
||||
->select();
|
||||
$existingPhones = array_column($existing, 'phone');
|
||||
}
|
||||
|
||||
// 3. 过滤出新数据,批量插入
|
||||
$newData = [];
|
||||
foreach ($batchRows as $row) {
|
||||
if (!empty($row['phone'])) {
|
||||
$phone = $row['phone'];
|
||||
} elseif (!empty($row['alias'])) {
|
||||
$phone = $row['alias'];
|
||||
} else {
|
||||
$phone = $row['wechatId'];
|
||||
}
|
||||
if (!empty($phone) && !in_array($phone, $existingPhones)) {
|
||||
$newData[] = [
|
||||
'task_id' => $planId,
|
||||
'name' => '',
|
||||
'source' => '场景获客_' . $params['name'] ?? '',
|
||||
'phone' => $phone,
|
||||
'tags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'siteTags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'createTime' => time(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 批量插入新数据
|
||||
if (!empty($newData)) {
|
||||
Db::name('task_customer')->insertAll($newData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Db::commit();
|
||||
|
||||
|
||||
return ResponseHelper::success(['planId' => $planId], '添加计划任务成功');
|
||||
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// 回滚事务
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return ResponseHelper::error('系统错误: ' . $e->getMessage(), 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* 验证JSON格式是否正确
|
||||
*
|
||||
* @param string $string
|
||||
@@ -294,7 +324,7 @@ class PostCreateAddFriendPlanV1Controller extends BaseController
|
||||
if (empty($string)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
json_decode($string);
|
||||
return (json_last_error() == JSON_ERROR_NONE);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace app\cunkebao\controller\plan;
|
||||
|
||||
use app\cunkebao\controller\BaseController;
|
||||
use library\ResponseHelper;
|
||||
use think\Controller;
|
||||
use think\Db;
|
||||
@@ -9,7 +10,7 @@ use think\Db;
|
||||
/**
|
||||
* 更新获客计划控制器
|
||||
*/
|
||||
class PostUpdateAddFriendPlanV1Controller extends Controller
|
||||
class PostUpdateAddFriendPlanV1Controller extends BaseController
|
||||
{
|
||||
/**
|
||||
* 更新计划任务
|
||||
@@ -62,12 +63,6 @@ class PostUpdateAddFriendPlanV1Controller extends Controller
|
||||
'endTime' => $params['endTime'] ?? '',
|
||||
];
|
||||
|
||||
if (isset($params['wechatGroups'])){
|
||||
$params['wechatGroups'] = $params['groupSelected'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 其余参数归为sceneConf
|
||||
$sceneConf = $params;
|
||||
unset(
|
||||
@@ -101,6 +96,7 @@ class PostUpdateAddFriendPlanV1Controller extends Controller
|
||||
'reqConf' => json_encode($reqConf, JSON_UNESCAPED_UNICODE),
|
||||
'msgConf' => json_encode($msgConf, JSON_UNESCAPED_UNICODE),
|
||||
'tagConf' => json_encode($tagConf, JSON_UNESCAPED_UNICODE),
|
||||
'status' => !empty($params['status']) ? 1 : 0,
|
||||
'updateTime' => time(),
|
||||
];
|
||||
|
||||
@@ -152,7 +148,7 @@ class PostUpdateAddFriendPlanV1Controller extends Controller
|
||||
$rows[] = [
|
||||
'name' => isset($cols[0]) ? trim($cols[0]) : '',
|
||||
'phone' => isset($cols[1]) ? trim($cols[1]) : '',
|
||||
'wechat' => isset($cols[2]) ? trim($cols[2]) : '',
|
||||
'wechatId' => isset($cols[2]) ? trim($cols[2]) : '',
|
||||
'source' => isset($cols[3]) ? trim($cols[3]) : '',
|
||||
'orderAmount' => isset($cols[4]) ? trim($cols[4]) : '',
|
||||
'orderDate' => isset($cols[5]) ? trim($cols[5]) : '',
|
||||
@@ -170,7 +166,7 @@ class PostUpdateAddFriendPlanV1Controller extends Controller
|
||||
$rows[] = [
|
||||
'name' => isset($cols[0]) ? trim($cols[0]) : '',
|
||||
'phone' => isset($cols[1]) ? trim($cols[1]) : '',
|
||||
'wechat' => isset($cols[2]) ? trim($cols[2]) : '',
|
||||
'wechatId' => isset($cols[2]) ? trim($cols[2]) : '',
|
||||
'source' => isset($cols[3]) ? trim($cols[3]) : '',
|
||||
'orderAmount' => isset($cols[4]) ? trim($cols[4]) : '',
|
||||
'orderDate' => isset($cols[5]) ? trim($cols[5]) : '',
|
||||
@@ -184,139 +180,98 @@ class PostUpdateAddFriendPlanV1Controller extends Controller
|
||||
}
|
||||
// 删除临时文件
|
||||
unlink($tmpFile);
|
||||
|
||||
// 1000条为一组进行批量处理
|
||||
$batchSize = 1000;
|
||||
$totalRows = count($rows);
|
||||
|
||||
for ($i = 0; $i < $totalRows; $i += $batchSize) {
|
||||
$batchRows = array_slice($rows, $i, $batchSize);
|
||||
|
||||
if (!empty($batchRows)) {
|
||||
// 1. 提取当前批次的phone
|
||||
$phones = [];
|
||||
foreach ($batchRows as $row) {
|
||||
$phone = !empty($row['phone']) ? $row['phone'] : $row['wechat'];
|
||||
if (!empty($phone)) {
|
||||
$phones[] = $phone;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 批量查询已存在的phone
|
||||
$existingPhones = [];
|
||||
if (!empty($phones)) {
|
||||
$existing = Db::name('task_customer')
|
||||
->where('task_id', $params['planId'])
|
||||
->where('phone', 'in', $phones)
|
||||
->field('phone')
|
||||
->select();
|
||||
$existingPhones = array_column($existing, 'phone');
|
||||
}
|
||||
|
||||
// 3. 过滤出新数据,批量插入
|
||||
$newData = [];
|
||||
foreach ($batchRows as $row) {
|
||||
$phone = !empty($row['phone']) ? $row['phone'] : $row['wechat'];
|
||||
if (!empty($phone) && !in_array($phone, $existingPhones)) {
|
||||
$newData[] = [
|
||||
'task_id' => $params['planId'],
|
||||
'name' => $row['name'] ?? '',
|
||||
'source' => $row['source'] ?? '',
|
||||
'phone' => $phone,
|
||||
'tags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'siteTags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'createTime' => time(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 批量插入新数据
|
||||
if (!empty($newData)) {
|
||||
Db::name('task_customer')->insertAll($newData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//电话获客
|
||||
if ($params['sceneId'] == 5) {
|
||||
$rows = Db::name('call_recording')
|
||||
->where('companyId', $this->getUserInfo('companyId'))
|
||||
->group('phone')
|
||||
->field('id,phone')
|
||||
->select();
|
||||
}
|
||||
|
||||
//群获客
|
||||
if ($params['sceneId'] == 7) {
|
||||
if (!empty($params['groupSelected']) && is_array($params['groupSelected'])) {
|
||||
if (!empty($params['wechatGroups']) && is_array($params['wechatGroups'])) {
|
||||
$rows = Db::name('wechat_group_member')->alias('gm')
|
||||
->join('wechat_account wa', 'gm.identifier = wa.wechatId')
|
||||
->where('gm.companyId', $this->getUserInfo('companyId'))
|
||||
->whereIn('gm.groupId', $params['groupSelected'])
|
||||
->whereIn('gm.groupId', $params['wechatGroups'])
|
||||
->group('gm.identifier')
|
||||
->column('wa.id,wa.wechatId,wa.alias,wa.phone');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 1000条为一组进行批量处理
|
||||
$batchSize = 1000;
|
||||
$totalRows = count($rows);
|
||||
if (in_array($params['sceneId'], [2, 5, 7]) && !empty($rows) && is_array($rows)) {
|
||||
// 1000条为一组进行批量处理
|
||||
$batchSize = 1000;
|
||||
$totalRows = count($rows);
|
||||
|
||||
for ($i = 0; $i < $totalRows; $i += $batchSize) {
|
||||
$batchRows = array_slice($rows, $i, $batchSize);
|
||||
|
||||
if (!empty($batchRows)) {
|
||||
// 1. 提取当前批次的phone
|
||||
$phones = [];
|
||||
foreach ($batchRows as $row) {
|
||||
if (!empty($row['phone'])) {
|
||||
$phone = !empty($row['phone']);
|
||||
} elseif (!empty($row['alias'])) {
|
||||
$phone = $row['alias'];
|
||||
} else {
|
||||
$phone = $row['wechatId'];
|
||||
}
|
||||
if (!empty($phone)) {
|
||||
$phones[] = $phone;
|
||||
}
|
||||
for ($i = 0; $i < $totalRows; $i += $batchSize) {
|
||||
$batchRows = array_slice($rows, $i, $batchSize);
|
||||
if (!empty($batchRows)) {
|
||||
// 1. 提取当前批次的phone
|
||||
// 1. 提取当前批次的phone
|
||||
$phones = [];
|
||||
foreach ($batchRows as $row) {
|
||||
if (!empty($row['phone'])) {
|
||||
$phone = $row['phone'];
|
||||
} elseif (!empty($row['alias'])) {
|
||||
$phone = $row['alias'];
|
||||
} else {
|
||||
$phone = $row['wechatId'];
|
||||
}
|
||||
|
||||
// 2. 批量查询已存在的phone
|
||||
$existingPhones = [];
|
||||
if (!empty($phones)) {
|
||||
$existing = Db::name('task_customer')
|
||||
->where('task_id', $params['planId'])
|
||||
->where('phone', 'in', $phones)
|
||||
->field('phone')
|
||||
->select();
|
||||
$existingPhones = array_column($existing, 'phone');
|
||||
if (!empty($phone)) {
|
||||
$phones[] = $phone;
|
||||
}
|
||||
}
|
||||
// 2. 批量查询已存在的phone
|
||||
$existingPhones = [];
|
||||
if (!empty($phones)) {
|
||||
$existing = Db::name('task_customer')
|
||||
->where('task_id', $params['planId'])
|
||||
->where('phone', 'in', $phones)
|
||||
->field('phone')
|
||||
->select();
|
||||
$existingPhones = array_column($existing, 'phone');
|
||||
}
|
||||
|
||||
// 3. 过滤出新数据,批量插入
|
||||
$newData = [];
|
||||
foreach ($batchRows as $row) {
|
||||
if (!empty($row['phone'])) {
|
||||
$phone = !empty($row['phone']);
|
||||
} elseif (!empty($row['alias'])) {
|
||||
$phone = $row['alias'];
|
||||
} else {
|
||||
$phone = $row['wechatId'];
|
||||
}
|
||||
if (!empty($phone) && !in_array($phone, $existingPhones)) {
|
||||
$newData[] = [
|
||||
'task_id' => $params['planId'],
|
||||
'name' => '',
|
||||
'source' => '场景获客_' . $params['name'] ?? '',
|
||||
'phone' => $phone,
|
||||
'tags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'siteTags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'createTime' => time(),
|
||||
];
|
||||
}
|
||||
// 3. 过滤出新数据,批量插入
|
||||
$newData = [];
|
||||
foreach ($batchRows as $row) {
|
||||
if (!empty($row['phone'])) {
|
||||
$phone = $row['phone'];
|
||||
} elseif (!empty($row['alias'])) {
|
||||
$phone = $row['alias'];
|
||||
} else {
|
||||
$phone = $row['wechatId'];
|
||||
}
|
||||
if (!empty($phone) && !in_array($phone, $existingPhones)) {
|
||||
$newData[] = [
|
||||
'task_id' => $params['planId'],
|
||||
'name' => !empty($row['name']) ? $row['name'] : '',
|
||||
'source' => '场景获客_' . $params['name'] ?? '',
|
||||
'phone' => $phone,
|
||||
'tags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'siteTags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'createTime' => time(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 批量插入新数据
|
||||
if (!empty($newData)) {
|
||||
Db::name('task_customer')->insertAll($newData);
|
||||
}
|
||||
// 4. 批量插入新数据
|
||||
if (!empty($newData)) {
|
||||
Db::name('task_customer')->insertAll($newData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ResponseHelper::success(['planId' => $params['planId']], '更新计划任务成功');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
@@ -127,6 +127,73 @@ class PosterWeChatMiniProgram extends Controller
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function decryptphones() {
|
||||
|
||||
$taskId = request()->param('id');
|
||||
$phone = request()->param('phone');
|
||||
if (!$phone) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'message' => '手机号不能为空'
|
||||
]);
|
||||
}
|
||||
|
||||
$task = Db::name('customer_acquisition_task')->where('id', $taskId)->find();
|
||||
if (!$task) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'message' => '任务不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!empty($phone)) {
|
||||
|
||||
// TODO 拿到手机号之后的后续操作:
|
||||
// 1. 先写入 ck_traffic_pool 表 identifier mobile 都是 用 phone字段的值
|
||||
$trafficPool = Db::name('traffic_pool')->where('identifier', $phone)->find();
|
||||
if (!$trafficPool) {
|
||||
Db::name('traffic_pool')->insert([
|
||||
'identifier' => $phone,
|
||||
'mobile' => $phone,
|
||||
'createTime' => time()
|
||||
]);
|
||||
}
|
||||
|
||||
$taskCustomer = Db::name('task_customer')->where('task_id', $taskId)->where('phone', $phone)->find();
|
||||
if (!$taskCustomer) {
|
||||
Db::name('task_customer')->insert([
|
||||
'task_id' => $taskId,
|
||||
// 'identifier' => $phone,
|
||||
'phone' => $phone,
|
||||
'source' => $task['name'],
|
||||
'createTime' => time(),
|
||||
'tags' => json_encode([]),
|
||||
'siteTags' => json_encode([]),
|
||||
]);
|
||||
}
|
||||
// return $phone;
|
||||
return json([
|
||||
'code' => 200,
|
||||
'message' => '获取手机号成功',
|
||||
'data' => $phone
|
||||
]);
|
||||
} else {
|
||||
// return null;
|
||||
return json([
|
||||
'code' => 400,
|
||||
'message' => '手机号失败:'
|
||||
]);
|
||||
}
|
||||
|
||||
// return $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// todo 获取海报获客任务的任务/海报数据 -- 表还没设计好,不急 ck_customer_acquisition_task
|
||||
public function getPosterTaskData() {
|
||||
$id = request()->param('id');
|
||||
|
||||
@@ -22,35 +22,49 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController
|
||||
*/
|
||||
protected function makeWhere(array $params = []): array
|
||||
{
|
||||
if (!empty($keyword = $this->request->param('keyword'))) {
|
||||
$keyword = $this->request->param('keyword','');
|
||||
$device = $this->request->param('deviceId');
|
||||
$status = $this->request->param('addStatus','');
|
||||
$taskId = $this->request->param('taskId','');
|
||||
$packageId = $this->request->param('packageId','');
|
||||
$where = [];
|
||||
if (!empty($keyword)) {
|
||||
$where[] = ['p.identifier|wa.nickname|wa.phone|wa.wechatId|wa.alias', 'like', '%' . $keyword . '%'];
|
||||
}
|
||||
|
||||
// 状态筛选
|
||||
if ($status = $this->request->param('addStatus')) {
|
||||
$where['s.status'] = $status;
|
||||
} else {
|
||||
$where['s.status'] = array('<>', TrafficSourceModel::STATUS_PASSED);
|
||||
if (!empty($status)) {
|
||||
if ($status == 1){
|
||||
$where[] = ['s.status','=',4];
|
||||
}elseif ($status == 2){
|
||||
$where[] = ['s.status','=',0];
|
||||
}elseif ($status == -1){
|
||||
$where[] = ['s.status','=',2];
|
||||
}elseif ($status == 3){
|
||||
$where[] = ['s.status','=',2];
|
||||
}
|
||||
}
|
||||
|
||||
// 来源的筛选
|
||||
if ($fromd = $this->request->param('packageId')) {
|
||||
if ($fromd != -1) {
|
||||
$where['tsp.id'] = $fromd;
|
||||
if ($packageId) {
|
||||
if ($packageId != -1) {
|
||||
$where[] = ['tsp.id','=',$packageId];
|
||||
} else {
|
||||
$where[] = ['tsp.id', null];
|
||||
$where[] = ['tsp.id','=', null];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($device = $this->request->param('device')) {
|
||||
$where['d.deviceId'] = $device;
|
||||
if (!empty($device)) {
|
||||
$where[] = ['d.deviceId','=',$device];
|
||||
}
|
||||
|
||||
if (!empty($taskId)){
|
||||
$where[] = ['t.sceneId','=',$taskId];
|
||||
}
|
||||
$where[] = ['s.companyId','=',$this->getUserInfo('companyId')];
|
||||
|
||||
$where['s.companyId'] = $this->getUserInfo('companyId');
|
||||
|
||||
return array_merge($where, $params);
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,67 +73,58 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController
|
||||
* @param array $where
|
||||
* @return \think\Paginator
|
||||
*/
|
||||
protected function getPoolListByCompanyId(array $where)
|
||||
protected function getPoolListByCompanyId(array $where,$isPage = true)
|
||||
{
|
||||
$query = TrafficPoolModel::alias('p')
|
||||
->field(
|
||||
[
|
||||
'p.id', 'p.identifier', 'p.mobile', 'p.wechatId', 'p.identifier',
|
||||
's.fromd', 's.status', 's.createTime', 's.companyId', 's.sourceId', 's.type',
|
||||
'wa.nickname', 'wa.avatar', 'wa.gender', 'wa.phone',
|
||||
'wa.nickname', 'wa.avatar', 'wa.gender', 'wa.phone','wa.alias'
|
||||
]
|
||||
)
|
||||
->join('traffic_source s', 'p.identifier=s.identifier', 'left')
|
||||
->join('traffic_source s', 'p.identifier=s.identifier')
|
||||
->join('wechat_account wa', 'p.identifier=wa.wechatId', 'left')
|
||||
->join('traffic_source_package_item tspi', 'p.identifier = tspi.identifier AND s.companyId = tspi.companyId', 'left')
|
||||
->join('traffic_source_package tsp', 'tspi.packageId=tsp.id', 'left')
|
||||
->join('device_wechat_login d', 's.sourceId=d.wechatId', 'left')
|
||||
->order('p.id DESC,s.id DESC')
|
||||
->group('p.identifier');
|
||||
|
||||
foreach ($where as $key => $value) {
|
||||
if (is_numeric($key) && is_array($value) && isset($value[0]) && $value[0] === 'exp') {
|
||||
$query->whereExp('', $value[1]);
|
||||
continue;
|
||||
}
|
||||
if (is_array($value)) {
|
||||
$query->where($key, ...$value);
|
||||
continue;
|
||||
}
|
||||
$query->where($key, $value);
|
||||
}
|
||||
|
||||
$result = $query->paginate($this->request->param('limit/d', 10), false, ['page' => $this->request->param('page/d', 1)]);
|
||||
$list = $result->items();
|
||||
$total = $result->total();
|
||||
|
||||
foreach ($list as &$item) {
|
||||
//流量池筛选
|
||||
$package = Db::name('traffic_source_package_item')->alias('tspi')
|
||||
->join('traffic_source_package p', 'tspi.packageId=p.id AND tspi.companyId=p.companyId')
|
||||
->where(['tspi.companyId' => $item->companyId, 'tspi.identifier' => $item->identifier])
|
||||
->column('p.name');
|
||||
|
||||
$package2 = Db::name('traffic_source_package_item')->alias('tspi')
|
||||
->join('traffic_source_package p', 'tspi.packageId=p.id')
|
||||
->where(['tspi.companyId' => $item->companyId, 'tspi.identifier' => $item->identifier, 'p.isSys' => 1])
|
||||
->column('p.name');
|
||||
$packages = array_merge($package, $package2);
|
||||
$item['packages'] = $packages;
|
||||
->where($where);
|
||||
|
||||
|
||||
if ($item->type == 1) {
|
||||
$tag = Db::name('wechat_friendship')->where(['wechatId' => $item->wechatId])->column('tags');
|
||||
$tags = [];
|
||||
foreach ($tag as $k => $v) {
|
||||
$v = json_decode($v, true);
|
||||
if (!empty($v)) {
|
||||
$tags = array_merge($tags, $v);
|
||||
$result = $query->order('p.id DESC,s.id DESC')->group('p.identifier');
|
||||
|
||||
if ($isPage) {
|
||||
$result = $query->paginate($this->request->param('limit/d', 10), false, ['page' => $this->request->param('page/d', 1)]);
|
||||
$list = $result->items();
|
||||
$total = $result->total();
|
||||
}else{
|
||||
$list = $result->select();
|
||||
$total = '';
|
||||
}
|
||||
|
||||
|
||||
if ($isPage) {
|
||||
foreach ($list as &$item) {
|
||||
//流量池筛选
|
||||
$package = Db::name('traffic_source_package_item')->alias('tspi')
|
||||
->join('traffic_source_package p', 'tspi.packageId=p.id AND tspi.companyId=p.companyId')
|
||||
->where(['tspi.identifier' => $item->identifier])
|
||||
->whereIn('tspi.companyId', [0, $item->companyId])
|
||||
->column('p.name');
|
||||
$item['packages'] = $package;
|
||||
if ($item->type == 1) {
|
||||
$tag = Db::name('wechat_friendship')->where(['wechatId' => $item->wechatId])->column('tags');
|
||||
$tags = [];
|
||||
foreach ($tag as $k => $v) {
|
||||
$v = json_decode($v, true);
|
||||
if (!empty($v)) {
|
||||
$tags = array_merge($tags, $v);
|
||||
}
|
||||
}
|
||||
$item['tags'] = $tags;
|
||||
}
|
||||
$item['tags'] = $tags;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
unset($item);
|
||||
$data = ['list' => $list, 'total' => $total];
|
||||
@@ -356,6 +361,143 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController
|
||||
return ResponseHelper::success(['wechat' => $tags, 'siteLabels' => $siteLabels]);
|
||||
}
|
||||
|
||||
|
||||
public function getPackage()
|
||||
{
|
||||
|
||||
$page = $this->request->param('page',1);
|
||||
$limit = $this->request->param('limit',10);
|
||||
$keyword = $this->request->param('keyword','');
|
||||
|
||||
$companyId = $this->getUserInfo('companyId');
|
||||
$package = Db::name('traffic_source_package')->alias('tsp')
|
||||
->join('traffic_source_package_item tspi','tspi.packageId=tsp.id','left')
|
||||
->whereIn('tsp.companyId', [$companyId,0])
|
||||
->field('tsp.id,tsp.name,tsp.description,tsp.createTime,count(tspi.id) as num')
|
||||
->group('tsp.id');
|
||||
|
||||
if (!empty($keyword)){
|
||||
$package->where('tsp.name|tsp.description','like','%'.$keyword.'%');
|
||||
}
|
||||
|
||||
$list = $package->page($page,$limit)->select();
|
||||
$total = $package->count();
|
||||
|
||||
foreach ($list as $k => &$v) {
|
||||
$v['createTime'] = !empty($v['createTime']) ? date('Y-m-d H:i:s', $v['createTime']) : '';
|
||||
}
|
||||
unset($v);
|
||||
|
||||
$data = [
|
||||
'total' => $total,
|
||||
'list' => $list,
|
||||
];
|
||||
|
||||
return ResponseHelper::success($data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function addPackage()
|
||||
{
|
||||
try {
|
||||
$addPackageId = $this->request->param('addPackageId','');
|
||||
$packageName = $this->request->param('packageName','');
|
||||
$userIds = $this->request->param('userIds',[]);
|
||||
$companyId = $this->getUserInfo('companyId');
|
||||
$userId = $this->getUserInfo('id');
|
||||
if (empty($addPackageId) && empty($packageName)){
|
||||
return ResponseHelper::error('存储的流量池不能为空');
|
||||
}
|
||||
|
||||
if (!empty($addPackageId)){
|
||||
$package = Db::name('traffic_source_package')
|
||||
->where(['id' => $addPackageId,'isDel' => 0])
|
||||
->whereIn('companyId', [$companyId,0])
|
||||
->field('id,name')
|
||||
->find();
|
||||
if (empty($package)){
|
||||
return ResponseHelper::error('该流量池不存在');
|
||||
}
|
||||
$packageId = $package['id'];
|
||||
}else{
|
||||
$package = Db::name('traffic_source_package')
|
||||
->where(['isDel' => 0,'name' => $packageName])
|
||||
->whereIn('companyId', [$companyId,0])
|
||||
->field('id,name')
|
||||
->find();
|
||||
if (!empty($package)){
|
||||
return ResponseHelper::error('该流量池名称已存在');
|
||||
}
|
||||
$packageId = Db::name('traffic_source_package')->insertGetId([
|
||||
'userId' => $userId,
|
||||
'companyId' => $companyId,
|
||||
'name' => $packageName,
|
||||
'matchingRules' => json_encode($this->makeWhere()),
|
||||
'createTime' => time(),
|
||||
'isDel' => 0,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
if (!empty($userIds)){
|
||||
if (!is_array($userIds)){
|
||||
return ResponseHelper::error('选择的用户类型错误');
|
||||
}
|
||||
$result = Db::name('traffic_pool')->alias('tp')
|
||||
->join('traffic_source tc','tp.identifier=tc.identifier')
|
||||
->whereIn('tp.id',$userIds)
|
||||
->where(['companyId' => $companyId])
|
||||
->group('tp.identifier')
|
||||
->column('tc.identifier');
|
||||
}else{
|
||||
$result = $this->getPoolListByCompanyId($this->makeWhere(),false);
|
||||
$result = json_decode($result, true);
|
||||
$result = array_column($result['list'],'identifier');
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 1000条为一组进行批量处理
|
||||
$batchSize = 1000;
|
||||
$totalRows = count($result);
|
||||
|
||||
for ($i = 0; $i < $totalRows; $i += $batchSize) {
|
||||
$batchRows = array_slice($result, $i, $batchSize);
|
||||
if (!empty($batchRows)) {
|
||||
// 2. 批量查询已存在的手机
|
||||
$existingPhones = [];
|
||||
$existing = Db::name('traffic_source_package_item')
|
||||
->where(['companyId' => $companyId,'packageId' => $packageId])
|
||||
->whereIn('identifier', $batchRows)
|
||||
->field('identifier')
|
||||
->select();
|
||||
$existingPhones = array_column($existing, 'identifier');
|
||||
// 3. 过滤出新数据,批量插入
|
||||
$newData = [];
|
||||
foreach ($batchRows as $row) {
|
||||
if (!in_array($row, $existingPhones)) {
|
||||
$newData[] = [
|
||||
'packageId' => $packageId,
|
||||
'companyId' => $companyId,
|
||||
'identifier' => $row,
|
||||
'createTime' => time(),
|
||||
];
|
||||
}
|
||||
}
|
||||
// 4. 批量插入新数据
|
||||
if (!empty($newData)) {
|
||||
Db::name('traffic_source_package_item')->insertAll($newData);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ResponseHelper::success('添加成功');
|
||||
} catch (\Exception $e) {
|
||||
return ResponseHelper::error($e->getMessage(), $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* public function editUserTags()
|
||||
{
|
||||
$userId = $this->request->param('userId', '');
|
||||
|
||||
@@ -33,31 +33,32 @@ class Workbench extends Validate
|
||||
'syncType' => 'requireIf:type,2|in:1,2,3,4',
|
||||
'startTime' => 'requireIf:type,2|dateFormat:H:i',
|
||||
'endTime' => 'requireIf:type,2|dateFormat:H:i',
|
||||
'accountType' => 'requireIf:type,2|in:1,2',
|
||||
'contentLibraries' => 'requireIf:type,2|array',
|
||||
'accountGroups' => 'requireIf:type,2|in:1,2',
|
||||
'contentGroups' => 'requireIf:type,2|array',
|
||||
// 群消息推送特有参数
|
||||
'pushType' => 'requireIf:type,3|in:1,2', // 推送方式 1定时 2立即
|
||||
'pushType' => 'requireIf:type,3|in:0,1', // 推送方式 0定时 1立即
|
||||
'startTime' => 'requireIf:type,3|dateFormat:H:i',
|
||||
'endTime' => 'requireIf:type,3|dateFormat:H:i',
|
||||
'maxPerDay' => 'requireIf:type,3|number|min:1',
|
||||
'pushOrder' => 'requireIf:type,3|in:1,2', // 1最早 2最新
|
||||
'isLoop' => 'requireIf:type,3|in:0,1',
|
||||
'status' => 'requireIf:type,3|in:0,1',
|
||||
'groups' => 'requireIf:type,3|array|min:1',
|
||||
'contentLibraries' => 'requireIf:type,3|array|min:1',
|
||||
'wechatGroups' => 'requireIf:type,3|array|min:1',
|
||||
'contentGroups' => 'requireIf:type,3|array|min:1',
|
||||
// 自动建群特有参数
|
||||
'groupNamePrefix' => 'requireIf:type,4|max:50',
|
||||
'maxGroups' => 'requireIf:type,4|number|min:1',
|
||||
'membersPerGroup' => 'requireIf:type,4|number|min:1',
|
||||
'groupNameTemplate' => 'requireIf:type,4|max:50',
|
||||
'maxGroupsPerDay' => 'requireIf:type,4|number|min:1',
|
||||
'groupSizeMin' => 'requireIf:type,4|number|min:1|max:50',
|
||||
'groupSizeMax' => 'requireIf:type,4|number|min:1|max:50',
|
||||
// 流量分发特有参数
|
||||
'distributeType' => 'requireIf:type,5|in:1,2',
|
||||
'maxPerDay' => 'requireIf:type,5|number|min:1',
|
||||
'timeType' => 'requireIf:type,5|in:1,2',
|
||||
'startTime' => 'requireIf:type,5|dateFormat:H:i',
|
||||
'endTime' => 'requireIf:type,5|dateFormat:H:i',
|
||||
'account' => 'requireIf:type,5|array|min:1',
|
||||
'accountGroups' => 'requireIf:type,5|array|min:1',
|
||||
// 通用参数
|
||||
'devices' => 'requireIf:type,1,2,5|array',
|
||||
'deveiceGroups' => 'requireIf:type,1,2,5|array',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -97,13 +98,12 @@ class Workbench extends Validate
|
||||
'startTime.dateFormat' => '发布开始时间格式错误',
|
||||
'endTime.requireIf' => '请设置发布结束时间',
|
||||
'endTime.dateFormat' => '发布结束时间格式错误',
|
||||
'accountType.requireIf' => '请选择账号类型',
|
||||
'accountType.in' => '账号类型错误',
|
||||
'contentLibraries.requireIf' => '请选择内容库',
|
||||
'contentLibraries.array' => '内容库格式错误',
|
||||
'accountGroups.requireIf' => '请选择账号类型',
|
||||
'accountGroups.in' => '账号类型错误',
|
||||
'contentGroups.requireIf' => '请选择内容库',
|
||||
'contentGroups.array' => '内容库格式错误',
|
||||
// 群消息推送相关提示
|
||||
'pushType.requireIf' => '请选择推送方式',
|
||||
'pushType.in' => '推送方式错误',
|
||||
'startTime.requireIf' => '请设置推送开始时间',
|
||||
'startTime.dateFormat' => '推送开始时间格式错误',
|
||||
'endTime.requireIf' => '请设置推送结束时间',
|
||||
@@ -115,20 +115,23 @@ class Workbench extends Validate
|
||||
'pushOrder.in' => '推送顺序错误',
|
||||
'isLoop.requireIf' => '请选择是否循环推送',
|
||||
'isLoop.in' => '循环推送参数错误',
|
||||
'status.requireIf' => '请选择推送状态',
|
||||
'status.in' => '推送状态错误',
|
||||
'groups.requireIf' => '请选择推送群组',
|
||||
'groups.array' => '推送群组格式错误',
|
||||
'groups.min' => '至少选择一个推送群组',
|
||||
'wechatGroups.requireIf' => '请选择推送群组',
|
||||
'wechatGroups.array' => '推送群组格式错误',
|
||||
'wechatGroups.min' => '至少选择一个推送群组',
|
||||
// 自动建群相关提示
|
||||
'groupNamePrefix.requireIf' => '请设置群名称前缀',
|
||||
'groupNamePrefix.max' => '群名称前缀最多50个字符',
|
||||
'maxGroups.requireIf' => '请设置最大建群数量',
|
||||
'maxGroups.number' => '最大建群数量必须为数字',
|
||||
'maxGroups.min' => '最大建群数量必须大于0',
|
||||
'membersPerGroup.requireIf' => '请设置每个群的人数',
|
||||
'membersPerGroup.number' => '每个群的人数必须为数字',
|
||||
'membersPerGroup.min' => '每个群的人数必须大于0',
|
||||
'groupNameTemplate.requireIf' => '请设置群名称前缀',
|
||||
'groupNameTemplate.max' => '群名称前缀最多50个字符',
|
||||
'maxGroupsPerDay.requireIf' => '请设置最大建群数量',
|
||||
'maxGroupsPerDay.number' => '最大建群数量必须为数字',
|
||||
'maxGroupsPerDay.min' => '最大建群数量必须大于0',
|
||||
'groupSizeMin.requireIf' => '请设置每个群的人数',
|
||||
'groupSizeMin.number' => '每个群的人数必须为数字',
|
||||
'groupSizeMin.min' => '每个群的人数必须大于0',
|
||||
'groupSizeMin.max' => '每个群的人数最大50人',
|
||||
'groupSizeMax.requireIf' => '请设置每个群的人数',
|
||||
'groupSizeMax.number' => '每个群的人数必须为数字',
|
||||
'groupSizeMax.min' => '每个群的人数必须大于0',
|
||||
'groupSizeMax.max' => '每个群的人数最大50人',
|
||||
// 流量分发相关提示
|
||||
'distributeType.requireIf' => '请选择流量分发类型',
|
||||
'distributeType.in' => '流量分发类型错误',
|
||||
@@ -138,31 +141,33 @@ class Workbench extends Validate
|
||||
'timeType.requireIf' => '请选择时间类型',
|
||||
|
||||
// 通用提示
|
||||
'devices.require' => '请选择设备',
|
||||
'devices.array' => '设备格式错误',
|
||||
'deveiceGroups.require' => '请选择设备',
|
||||
'deveiceGroups.array' => '设备格式错误',
|
||||
'targetGroups.require' => '请选择目标用户组',
|
||||
'targetGroups.array' => '目标用户组格式错误',
|
||||
'account.requireIf' => '流量分发时必须选择分发账号',
|
||||
'account.array' => '分发账号格式错误',
|
||||
'account.min' => '至少选择一个分发账号',
|
||||
'accountGroups.requireIf' => '流量分发时必须选择分发账号',
|
||||
'accountGroups.array' => '分发账号格式错误',
|
||||
'accountGroups.min' => '至少选择一个分发账号',
|
||||
];
|
||||
|
||||
/**
|
||||
* 验证场景
|
||||
*/
|
||||
protected $scene = [
|
||||
'create' => ['name', 'type', 'autoStart', 'devices', 'targetGroups',
|
||||
'create' => ['name', 'type', 'autoStart', 'deveiceGroups', 'targetGroups',
|
||||
'interval', 'maxLikes', 'startTime', 'endTime', 'contentTypes',
|
||||
'syncInterval', 'syncCount', 'syncType',
|
||||
'pushType', 'startTime', 'endTime', 'maxPerDay', 'pushOrder', 'isLoop', 'status', 'groups', 'contentLibraries',
|
||||
'groupNamePrefix', 'maxGroups', 'membersPerGroup'
|
||||
'pushType', 'startTime', 'endTime', 'maxPerDay', 'pushOrder', 'isLoop', 'status', 'wechatGroups', 'contentGroups',
|
||||
'groupNamePrefix', 'maxGroups', 'membersPerGroup',
|
||||
'groupNameTemplate', 'maxGroupsPerDay', 'groupSizeMin', 'groupSizeMax',
|
||||
],
|
||||
'update_status' => ['id', 'status'],
|
||||
'edit' => ['name', 'type', 'autoStart', 'devices', 'targetGroups',
|
||||
'edit' => ['name', 'type', 'autoStart', 'deveiceGroups', 'targetGroups',
|
||||
'interval', 'maxLikes', 'startTime', 'endTime', 'contentTypes',
|
||||
'syncInterval', 'syncCount', 'syncType',
|
||||
'pushType', 'startTime', 'endTime', 'maxPerDay', 'pushOrder', 'isLoop', 'status', 'groups', 'contentLibraries',
|
||||
'groupNamePrefix', 'maxGroups', 'membersPerGroup'
|
||||
'pushType', 'startTime', 'endTime', 'maxPerDay', 'pushOrder', 'isLoop', 'status', 'wechatGroups', 'contentGroups',
|
||||
'groupNamePrefix', 'maxGroups', 'membersPerGroup',
|
||||
'groupNameTemplate', 'maxGroupsPerDay', 'groupSizeMin', 'groupSizeMax',
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
@@ -71,20 +71,15 @@ class CallRecordingListJob
|
||||
'secondMin' => 0,
|
||||
'secondMax' => 99999,
|
||||
'departmentIds' => '',
|
||||
'from' => '2016-01-01 00:00:00',
|
||||
'to' => '2025-08-31 00:00:00',
|
||||
'from' => date('Y-m-d') . ' 00:00:00',
|
||||
'to' => date('Y-m-d') . ' 00:00:00',
|
||||
'departmentId' => ''
|
||||
];
|
||||
|
||||
// 设置请求信息
|
||||
$request = request();
|
||||
$request->withGet($params);
|
||||
|
||||
|
||||
// 调用通话记录列表获取方法
|
||||
$result = $callRecordingController->getlist($params, true);
|
||||
$response = json_decode($result, true);
|
||||
|
||||
|
||||
// 判断是否成功
|
||||
if ($response['code'] == 200) {
|
||||
$data = $response['data'];
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
# 微信群好友列表
|
||||
*/30 * * * * cd /www/wwwroot/mckb_quwanzhi_com/Server && php think groupFriends:list >> /www/wwwroot/mckb_quwanzhi_com/Server/runtime/log/group_friends_list.log 2>&1
|
||||
|
||||
# 获取通话记录
|
||||
*/30 * * * * cd /www/wwwroot/mckb_quwanzhi_com/Server && php think call-recording:list >> /www/wwwroot/mckb_quwanzhi_com/Server/runtime/log/call_recording.log 2>&1
|
||||
|
||||
|
||||
# 分配规则列表
|
||||
0 3 * * * cd /www/wwwroot/mckb_quwanzhi_com/Server && php think allotrule:list >> /www/wwwroot/mckb_quwanzhi_com/Server/runtime/log/allot_rule_list.log 2>&1
|
||||
|
||||
|
||||
@@ -240,8 +240,9 @@ class Adapter implements WeChatServiceInterface
|
||||
->where('id', $task['id'])
|
||||
->update([
|
||||
'status' => $friendAddTaskCreated ? 1 : 3,
|
||||
'fail_reason' => $friendAddTaskCreated ? '' : '已经是好友了',
|
||||
'fail_reason' => '',
|
||||
'processed_wechat_ids' => $task['processed_wechat_ids'],
|
||||
'addTime' => time(),
|
||||
'updateTime' => time()
|
||||
]);
|
||||
// ~~不用管,回头再添加再判断即可~~
|
||||
@@ -298,7 +299,7 @@ class Adapter implements WeChatServiceInterface
|
||||
|
||||
Db::name('task_customer')
|
||||
->where('id', $task['id'])
|
||||
->update(['status' => 4, 'updateTime' => time()]);
|
||||
->update(['status' => 4,'passTime' => time(), 'updateTime' => time()]);
|
||||
|
||||
$wechatFriendRecord = $this->getWeChatAccoutIdAndFriendIdByWeChatIdAndFriendPhone($passedWeChatId, $task['phone']);
|
||||
$msgConf = is_string($task_info['msgConf']) ? json_decode($task_info['msgConf'], 1) : $task_info['msgConf'];
|
||||
@@ -339,7 +340,7 @@ class Adapter implements WeChatServiceInterface
|
||||
{
|
||||
$task = Db::name('customer_acquisition_task')
|
||||
->where(['status' => 1, 'deleteTime' => 0])
|
||||
->whereIn('sceneId', [7])
|
||||
->whereIn('sceneId', [5, 7])
|
||||
->order('id desc')
|
||||
->select();
|
||||
|
||||
@@ -349,7 +350,17 @@ class Adapter implements WeChatServiceInterface
|
||||
|
||||
foreach ($task as $item) {
|
||||
$sceneConf = json_decode($item['sceneConf'], true);
|
||||
//群获客
|
||||
//电话
|
||||
if ($item['sceneId'] == 5) {
|
||||
$rows = Db::name('call_recording')
|
||||
->where('companyId', $item['companyId'])
|
||||
->group('phone')
|
||||
->field('id,phone')
|
||||
->order('id asc')
|
||||
->limit(0, 100)
|
||||
->select();
|
||||
}
|
||||
|
||||
if ($item['sceneId'] == 7) {
|
||||
if (!empty($sceneConf['groupSelected']) && is_array($sceneConf['groupSelected'])) {
|
||||
$rows = Db::name('wechat_group_member')->alias('gm')
|
||||
@@ -358,76 +369,77 @@ class Adapter implements WeChatServiceInterface
|
||||
->whereIn('gm.groupId', $sceneConf['groupSelected'])
|
||||
->group('gm.identifier')
|
||||
->column('wa.id,wa.wechatId,wa.alias,wa.phone');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 1000条为一组进行批量处理
|
||||
$batchSize = 1000;
|
||||
$totalRows = count($rows);
|
||||
if (in_array($item['sceneId'], [5, 7]) && !empty($rows) && is_array($rows)) {
|
||||
// 1000条为一组进行批量处理
|
||||
$batchSize = 1000;
|
||||
$totalRows = count($rows);
|
||||
|
||||
for ($i = 0; $i < $totalRows; $i += $batchSize) {
|
||||
$batchRows = array_slice($rows, $i, $batchSize);
|
||||
for ($i = 0; $i < $totalRows; $i += $batchSize) {
|
||||
$batchRows = array_slice($rows, $i, $batchSize);
|
||||
|
||||
if (!empty($batchRows)) {
|
||||
// 1. 提取当前批次的phone
|
||||
$phones = [];
|
||||
foreach ($batchRows as $row) {
|
||||
if (!empty($row['phone'])) {
|
||||
$phone = !empty($row['phone']);
|
||||
} elseif (!empty($row['alias'])) {
|
||||
$phone = $row['alias'];
|
||||
} else {
|
||||
$phone = $row['wechatId'];
|
||||
}
|
||||
if (!empty($phone)) {
|
||||
$phones[] = $phone;
|
||||
}
|
||||
if (!empty($batchRows)) {
|
||||
// 1. 提取当前批次的phone
|
||||
$phones = [];
|
||||
foreach ($batchRows as $row) {
|
||||
if (!empty($row['phone'])) {
|
||||
$phone = !empty($row['phone']);
|
||||
} elseif (!empty($row['alias'])) {
|
||||
$phone = $row['alias'];
|
||||
} else {
|
||||
$phone = $row['wechatId'];
|
||||
}
|
||||
|
||||
// 2. 批量查询已存在的phone
|
||||
$existingPhones = [];
|
||||
if (!empty($phones)) {
|
||||
$existing = Db::name('task_customer')
|
||||
->where('task_id', $item['id'])
|
||||
->where('phone', 'in', $phones)
|
||||
->field('phone')
|
||||
->select();
|
||||
$existingPhones = array_column($existing, 'phone');
|
||||
if (!empty($phone)) {
|
||||
$phones[] = $phone;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 过滤出新数据,批量插入
|
||||
$newData = [];
|
||||
foreach ($batchRows as $row) {
|
||||
if (!empty($row['phone'])) {
|
||||
$phone = !empty($row['phone']);
|
||||
} elseif (!empty($row['alias'])) {
|
||||
$phone = $row['alias'];
|
||||
} else {
|
||||
$phone = $row['wechatId'];
|
||||
}
|
||||
if (!empty($phone) && !in_array($phone, $existingPhones)) {
|
||||
$newData[] = [
|
||||
'task_id' => $item['id'],
|
||||
'name' => '',
|
||||
'source' => '场景获客_' . $item['name'],
|
||||
'phone' => $phone,
|
||||
'tags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'siteTags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'createTime' => time(),
|
||||
];
|
||||
}
|
||||
}
|
||||
// 2. 批量查询已存在的phone
|
||||
$existingPhones = [];
|
||||
if (!empty($phones)) {
|
||||
$existing = Db::name('task_customer')
|
||||
->where('task_id', $item['id'])
|
||||
->where('phone', 'in', $phones)
|
||||
->field('phone')
|
||||
->select();
|
||||
$existingPhones = array_column($existing, 'phone');
|
||||
}
|
||||
|
||||
// 4. 批量插入新数据
|
||||
if (!empty($newData)) {
|
||||
Db::name('task_customer')->insertAll($newData);
|
||||
// 3. 过滤出新数据,批量插入
|
||||
$newData = [];
|
||||
foreach ($batchRows as $row) {
|
||||
if (!empty($row['phone'])) {
|
||||
$phone = !empty($row['phone']);
|
||||
} elseif (!empty($row['alias'])) {
|
||||
$phone = $row['alias'];
|
||||
} else {
|
||||
$phone = $row['wechatId'];
|
||||
}
|
||||
if (!empty($phone) && !in_array($phone, $existingPhones)) {
|
||||
$newData[] = [
|
||||
'task_id' => $item['id'],
|
||||
'name' => '',
|
||||
'source' => '场景获客_' . $item['name'],
|
||||
'phone' => $phone,
|
||||
'tags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'siteTags' => json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'createTime' => time(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 批量插入新数据
|
||||
if (!empty($newData)) {
|
||||
Db::name('task_customer')->insertAll($newData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
exit_data($sceneConf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1488,4 +1500,39 @@ class Adapter implements WeChatServiceInterface
|
||||
}
|
||||
|
||||
|
||||
public function syncCallRecording()
|
||||
{
|
||||
$sql = "insert into ck_call_recording(`id`,`phone`,`isCallOut`,`companyId`,`callType`,`beginTime`,`endTime`,`createTime`)
|
||||
SELECT
|
||||
c.id id,
|
||||
c.phone phone,
|
||||
c.isCallOut isCallOut,
|
||||
a.departmentId companyId,
|
||||
c.callType callType,
|
||||
c.beginTime beginTime,
|
||||
c.endTime endTime,
|
||||
c.callBeginTime createTime
|
||||
FROM
|
||||
s2_call_recording c
|
||||
LEFT JOIN s2_company_account a ON c.deviceOwnerId = a.id
|
||||
ORDER BY c.id DESC
|
||||
LIMIT ?, ?
|
||||
ON DUPLICATE KEY UPDATE
|
||||
id=VALUES(id),
|
||||
phone=VALUES(phone),
|
||||
isCallOut=VALUES(isCallOut),
|
||||
companyId=VALUES(companyId)";
|
||||
|
||||
$offset = 0;
|
||||
$limit = 2000;
|
||||
$usleepTime = 50000;
|
||||
do {
|
||||
$affected = Db::execute($sql, [$offset, $limit]);
|
||||
$offset += $limit;
|
||||
if ($affected > 0) {
|
||||
usleep($usleepTime);
|
||||
}
|
||||
} while ($affected > 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,4 +36,7 @@ include __DIR__ . '/../application/superadmin/config/route.php';
|
||||
// 加载CozeAI模块路由配置
|
||||
include __DIR__ . '/../application/cozeai/config/route.php';
|
||||
|
||||
// 加载OpenAiAI模块路由配置
|
||||
include __DIR__ . '/../application/ai/config/route.php';
|
||||
|
||||
return [];
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// API配置文件
|
||||
|
||||
// 基础配置
|
||||
export const BASE_URL = 'http://yi.cn'
|
||||
//export const BASE_URL = 'https://ckbapi.quwanzhi.com'
|
||||
//export const BASE_URL = 'http://yishi.com'
|
||||
export const BASE_URL = 'https://ckbapi.quwanzhi.com'
|
||||
|
||||
// 获取请求头
|
||||
const getHeaders = (options = {}) => {
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<view class="side-menu-mask" @tap="closeSideMenu"></view>
|
||||
<view class="side-menu">
|
||||
<view class="side-menu-header">
|
||||
<text class="side-menu-title">AI赋能</text>
|
||||
<text class="close-icon" @tap="closeSideMenu">
|
||||
<text class="side-menu-title">AI助手</text>
|
||||
<!-- <text class="close-icon" @tap="closeSideMenu">
|
||||
<u-icon name="close" color="#333" size="24"></u-icon>
|
||||
</text>
|
||||
</text> -->
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<!-- 头部 -->
|
||||
<view class="header">
|
||||
<view class="back-icon" @tap="closePage">
|
||||
<text class="uni-icons-arrow-left" style="font-size: 26px; color: #333;"></text>
|
||||
<u-icon name="arrow-left" color="#333" size="26"></u-icon>
|
||||
</view>
|
||||
<view class="title">供应链采购</view>
|
||||
<view class="close-icon" @tap="closePage">
|
||||
<text class="uni-icons-close" style="font-size: 24px; color: #333;"></text>
|
||||
<u-icon name="close" color="#333" size="24"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<!-- 头部 -->
|
||||
<view class="header">
|
||||
<view class="back-icon" @tap="closePage">
|
||||
<text class="uni-icons-arrow-left" style="font-size: 26px; color: #333;"></text>
|
||||
<u-icon name="arrow-left" color="#333" size="26"></u-icon>
|
||||
</view>
|
||||
<view class="title">{{detailData.name || packageData.name}}</view>
|
||||
<view class="close-icon" @tap="closePage">
|
||||
<text class="uni-icons-close" style="font-size: 24px; color: #333;"></text>
|
||||
<u-icon name="close" color="#333" size="24"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
<text class="iconfont">
|
||||
<u-icon name="file-text" size="24" color="{color: contentLibEnabled ? '#fff' : '#333'}"></u-icon>
|
||||
</text>
|
||||
<text style="margin-left: 5px;">艺施内容库</text>
|
||||
<text style="margin-left: 5px;">内容库</text>
|
||||
</view>
|
||||
</u-button>
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
contentLibEnabled: true,
|
||||
autoCustomerEnabled: false,
|
||||
scrollTop: 0,
|
||||
menuVisible: false,
|
||||
menuVisible: true,
|
||||
isRecording: false,
|
||||
messages: [],
|
||||
pageSize: 20,
|
||||
|
||||
Reference in New Issue
Block a user