作者 zhl

fb询盘分发

  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2024/09/30
  6 + * Time: 11:51
  7 + */
  8 +namespace App\Console\Commands\Inquiry;
  9 +
  10 +use App\Helper\Translate;
  11 +use App\Models\Inquiry\ReInquiryDetail;
  12 +use App\Models\Inquiry\ReInquiryDetailLog;
  13 +use App\Models\Inquiry\ReInquiryForm;
  14 +use App\Models\Inquiry\ReInquiryTask;
  15 +use App\Models\Inquiry\ReInquiryText;
  16 +use App\Models\Project\Project;
  17 +use App\Models\WebSetting\WebLanguage;
  18 +use Illuminate\Console\Command;
  19 +use Illuminate\Support\Arr;
  20 +use Illuminate\Support\Facades\Cache;
  21 +use Illuminate\Support\Facades\DB;
  22 +use Illuminate\Support\Facades\Http;
  23 +use Illuminate\Support\Facades\Log;
  24 +use Illuminate\Support\Str;
  25 +
  26 +/**
  27 + * Class RelayInquiry
  28 + * @package App\Console\Commands\Inquiry
  29 + */
  30 +class RelayInquiry extends Command
  31 +{
  32 + /**
  33 + * The name and signature of the console command.
  34 + *
  35 + * @var string
  36 + */
  37 + protected $signature = 'relay_inquiry';
  38 +
  39 + /**
  40 + * The console command description.
  41 + *
  42 + * @var string
  43 + */
  44 + protected $description = '转发询盘:拆分转发数据';
  45 +
  46 + /**
  47 + * Create a new command instance.
  48 + *
  49 + * @return void
  50 + */
  51 + public function __construct()
  52 + {
  53 + parent::__construct();
  54 + }
  55 +
  56 + /**
  57 + * 模拟访问来源占比
  58 + * @var array
  59 + */
  60 + protected $lyzb = [
  61 + 'https://www.google.com/' => 630,
  62 + 'http://www.google.com/' => 30,
  63 + 'http://www.bing.com/' => 20,
  64 + 'https://www.bing.com/' => 5,
  65 + 'https://www.youtube.com/' => 5,
  66 + 'https://search.yahoo.com/' => 5,
  67 + 'https://www.facebook.com/' => 5,
  68 + ];
  69 +
  70 + /**
  71 + * 俄语站 模拟访问来源占比
  72 + * @var array
  73 + */
  74 + protected $eylyzb = [
  75 + 'https://www.yandex.com/' => 630,
  76 + 'https://www.google.com/' => 30,
  77 + 'http://www.google.com/' => 30,
  78 + 'http://www.bing.com/' => 20,
  79 + 'https://www.bing.com/' => 5,
  80 + 'https://www.youtube.com/' => 5,
  81 + 'https://search.yahoo.com/' => 5,
  82 + 'https://www.facebook.com/' => 5,
  83 + ];
  84 +
  85 + /**
  86 + * PC端访问头信息
  87 + * @var array
  88 + */
  89 + protected $pc_ua = [
  90 + 0 => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
  91 + 1 => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36',
  92 + 2 => 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1'
  93 + ];
  94 +
  95 + /**
  96 + * 移动端访问头信息
  97 + * @var array
  98 + */
  99 + protected $mobile_ua = [
  100 + 0 => 'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko; googleweblight) Chrome/38.0.1025.166 Mobile Safari/535.19',
  101 + ];
  102 +
  103 + /**
  104 + * google域名后缀
  105 + * @var string[]
  106 + */
  107 + protected $suffix = [
  108 + 'co.jp' => '日本',
  109 + 'com.tr' => '土耳其',
  110 + 'nl' => '荷兰',
  111 + 'ru' => '俄罗斯',
  112 + 'fr' => '法国',
  113 + 'co.kr' => '韩国',
  114 + 'fi' => '芬兰',
  115 + 'be' => '比利时',
  116 + 'lt' => '立陶宛',
  117 + 'es' => '西班牙',
  118 + 'it' => '意大利',
  119 + 'com.au' => '澳大利亚',
  120 + 'no' => '挪威',
  121 + 'al' => '阿尔巴尼亚',
  122 + 'pt' => '葡萄牙',
  123 + 'lv' => '拉脱维亚',
  124 + 'hu' => '匈牙利',
  125 + 'cz' => '捷克',
  126 + 'de' => '德国',
  127 + 'ca' => '加拿大',
  128 + 'co.in' => '印度',
  129 + 'co.uk' => '英国',
  130 + 'com.vn' => '越南',
  131 + 'com.br' => '巴西',
  132 + 'co.il' => '以色列',
  133 + 'pl' => '波兰',
  134 + 'com.eg' => '埃及',
  135 + 'co.th' => '泰国',
  136 + 'sk' => '斯洛伐克',
  137 + 'ro' => '罗马尼亚',
  138 + 'com.mx' => '墨西哥',
  139 + 'com.my' => '马来西亚',
  140 + 'com.pk' => '巴基斯坦',
  141 + 'co.nz' => '新西兰',
  142 + 'co.za' => '南非',
  143 + 'com.ar' => '阿根廷',
  144 + 'com.kw' => '科威特',
  145 + 'com.sg' => '新加坡',
  146 + 'com.co' => '哥伦比亚',
  147 + 'co.id' => '印度尼西亚',
  148 + 'gr' => '希腊',
  149 + 'bg' => '保加利亚',
  150 + 'mn' => '蒙古',
  151 + 'dk' => '丹麦',
  152 + 'com.sa' => '沙特阿拉伯',
  153 + 'com.pe' => '秘鲁',
  154 + 'com.ph' => '菲律宾',
  155 + 'com.ua' => '乌克兰',
  156 + 'ge' => '格鲁吉亚',
  157 + 'ae' => '阿拉伯联合酋长国',
  158 + 'tn' => '突尼斯',
  159 + ];
  160 +
  161 + protected $otherzb = [700, 300]; //模拟访问来源占比 (非美国) google.com|google.其他后缀
  162 +
  163 + /**
  164 + * @return bool
  165 + */
  166 + public function handle()
  167 + {
  168 + while (true) {
  169 + $inquiry = $this->getInquiry();
  170 + if ($inquiry->isEmpty()){
  171 + $this->logChannel()->info('未发现待处理询盘!');
  172 + $this->output('未发现待处理询盘!');
  173 + sleep(60);
  174 + continue;
  175 + }
  176 +
  177 + $this->output('开始处理本轮询盘!');
  178 + foreach ($inquiry as $key=>$val) {
  179 + $this->output('询盘ID:' . $val->id);
  180 + // 询盘对应广告
  181 + $ad_task = $this->getAdTask($val->ad_id);
  182 + // 没有获取到转发任务
  183 + if (empty($ad_task)) {
  184 + $val->status = ReInquiryForm::STATUS_FORGO;
  185 + $val->remark = '未找到需要转发的广告任务!';
  186 + $val->save();
  187 + continue;
  188 + }
  189 + // 未设置对法对象
  190 + if (empty($ad_task['target'])) {
  191 + $val->status = ReInquiryForm::STATUS_FORGO;
  192 + $val->remark = '广告任务转发对象为空!';
  193 + $val->save();
  194 + continue;
  195 + }
  196 +
  197 + try {
  198 + $this->relayDetail($ad_task, $val);
  199 + } catch (\Exception $e) {
  200 + $this->logChannel()->info('执行询盘错误:' . $e->getMessage());
  201 + $this->output('执行询盘错误:' . $e->getMessage());
  202 + }
  203 + }
  204 + $this->output('本轮询盘处理结束!');
  205 + }
  206 + return true;
  207 + }
  208 +
  209 + /**
  210 + * 创建转发详情
  211 + * TODO 通过任务生成转发对象, 更具转发对象获取对应数据, 写入着陆记录
  212 + * @param $task
  213 + * @param $form
  214 + * @return bool
  215 + */
  216 + public function relayDetail($task, $form)
  217 + {
  218 + $this->output('获取转发对象');
  219 + // 获取转发对象 重置num数量, array_rand数量不足会报错
  220 + $task['num'] = $task['num'] > count($task['target']) ? count($task['target']) : $task['num'];
  221 + $relay_target_key = array_rand($task['target'], $task['num']);
  222 + if (empty($relay_target_key)) {
  223 + $this->logChannel()->info('当前任务未发现转发对象!', ['广告任务ID:' . $task['id'], '询盘ID:' . $form->id]);
  224 + $form->status = ReInquiryForm::STATUS_FORGO;
  225 + $form->remark = '当前任务未发现转发对象,广告ID: ' . $form->ad_id . '!';
  226 + $form->save();
  227 + return false;
  228 + }
  229 +
  230 + foreach ($relay_target_key as $key) {
  231 + // 推送站点
  232 + $domain = $task['target'][$key]['url'];
  233 + $is_v6 = $task['target'][$key]['is_v6'];
  234 + $re_website = 'https://' . $domain . '/';
  235 +
  236 + $this->output('转发对象:' . $domain);
  237 + $this->output('获取转发链接');
  238 + // v6:有邮箱推送主站,没有邮箱推送AMP站;v5:仅推送有邮箱到主站
  239 + $lang = '';
  240 + if ($is_v6) {
  241 + // 获取语种, 6.0是可以确定语种的
  242 + $project = Project::getProjectByDomain($domain);
  243 + if (empty($project)) {
  244 + $this->logChannel()->info('广告任务ID:' . $task['id'] . ', 转发对象:' . $re_website . '非v6链接,转发失败;', ['广告任务ID:' . $task['id'], '询盘ID:' . $form->id]);
  245 + continue;
  246 + }
  247 + $lang = WebLanguage::getLangById($project->main_lang_id ?? 1)['short'];
  248 +
  249 + // 获取访问明细和着陆页
  250 + $product_url = $this->getLinksFromSitemap($re_website . 'product_sitemap.xml');
  251 + $product_cate_url = $this->getLinksFromSitemap($re_website . 'product_category_sitemap.xml');
  252 + $keywords_url = $this->getLinksFromSitemap($re_website . 'product_keywords_sitemap.xml');
  253 + $page_url = $this->getLinksFromSitemap($re_website . 'page_sitemap.xml');
  254 + } else {
  255 + if($form->email){
  256 + //通过sitemap拿访问页面
  257 + $product_url = $this->getLinksFromSitemap($re_website . 'sitemap_post.xml');
  258 + $product_cate_url = $this->getLinksFromSitemap($re_website . 'sitemap_category.xml');
  259 + $keywords_url = $this->getLinksFromSitemap($re_website . 'sitemap_post_tag.xml');
  260 + $page_url = $this->getLinksFromSitemap($re_website . 'sitemap_page.xml');
  261 + }else{
  262 + //m站先就往contact-us着陆
  263 + $product_url = $product_cate_url = $keywords_url = [];
  264 + $page_url = [$re_website . 'contact-us/'];
  265 + }
  266 + }
  267 + // 所有可用url
  268 + $urls = $inquiry_urls = [];
  269 + $urls[] = $inquiry_urls[] = $re_website;
  270 + $all_urls = array_merge($urls, $product_url, $product_cate_url, $keywords_url, $page_url);
  271 + $inquiry_urls = array_merge($urls, $product_cate_url, $keywords_url, $page_url);
  272 +
  273 + // 随机访问1-3个页面
  274 + $visit_urls = Arr::random($all_urls, rand(1, count($all_urls) > 3 ? 3 : count($all_urls)));
  275 + $urls = array_merge($urls, $visit_urls);
  276 + // 推送着落页只能是 首页、产品分类、单页面、聚合页
  277 + if(!in_array(end($urls), $inquiry_urls)){
  278 + $urls[] = Arr::random($inquiry_urls);
  279 + }
  280 +
  281 + $this->output('获取转发ip');
  282 + // TODO 获取IP:如果是简码,查询数据库获取对应的国家, 如果是国家使用翻译, 再转化成IP
  283 + if (strlen($form->country) == 2) {
  284 + $country = $this->getCountry($form->country);
  285 + } else {
  286 + $country = Translate::tran($form->country, 'zh');
  287 + }
  288 + // 有国家 通过国家查询, 如果没有获取到就随机获取
  289 + $where = [];
  290 + $country && $where['ip_area'] = $country;
  291 + $ip_data = DB::table('gl_xunpan_ipdata')->where($where)->inRandomOrder()->first();
  292 + if (empty($ip_data)) {
  293 + $ip_data = DB::table('gl_xunpan_ipdata')->inRandomOrder()->first();
  294 + }
  295 + $ip = $ip_data->ip;
  296 + $country_name = $ip_data->ip_area;
  297 +
  298 + $this->output('转发内容');
  299 + // 推送消息 消息内容小于10个字符, 使用内置询盘内容
  300 + $message = $form->message;
  301 + $message_id = 0;
  302 + if (strlen($message) < 10) {
  303 + $use_ids = ReInquiryDetail::where(['re_website' => $domain])->where('status', '<>', ReInquiryDetail::STATUS_FAIL)->pluck('text_id')->toArray();
  304 + $text = ReInquiryText::whereNotIn('id', $use_ids)->where('status', ReInquiryText::STATUS_USABLE)->inRandomOrder()->first();
  305 + $message = $text->content;
  306 + $message_id = $text->id;
  307 + // 获取后,使用次数+1
  308 + $text->use_time += 1;
  309 + $text->save();
  310 + }
  311 +
  312 + $this->output('获取转发设备信息');
  313 + // 客户端 头信息 来源
  314 + $device_port = $form->email ? '1' : '2'; //1 pc 2移动端
  315 + $user_agent = $form->email ? Arr::random($this->pc_ua) : Arr::random($this->mobile_ua);
  316 + $referrer = $this->getReferer($country_name, $lang);
  317 + $this->output('写入数据');
  318 +
  319 + $pre = 0;
  320 + $start_time = time();
  321 + $seconds = rand(300, 900); // 开始时间 从5-15分钟后开始
  322 + // 写入推送详情
  323 + $re_detail = ReInquiryDetail::createInquiry($task['id'], $form->id, $domain, $country_name, $ip, $form->full_name, $form->email, $form->phone, $message, $message_id, $device_port,
  324 + $user_agent, $referrer, $urls, $is_v6, date('Y-m-d H:i:s', $start_time + $seconds));
  325 + foreach ($urls as $k=>$v){
  326 + $pre++;
  327 + $seconds += rand(3,10);
  328 + ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_VISIT, $pre, $v, date('Y-m-d H:i:s', $start_time + $seconds));
  329 + // 最后一次访问询盘 加上询盘
  330 + if($k+1 >= count($urls)){
  331 + $seconds += rand(10,30);
  332 + $pre++;
  333 + ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_INQUIRY, $pre, $v, date('Y-m-d H:i:s', $start_time + $seconds));
  334 + }
  335 + }
  336 + }
  337 +
  338 + $form->status = ReInquiryForm::STATUS_SUCCESS;
  339 + $form->save();
  340 + return true;
  341 + }
  342 +
  343 + /**
  344 + * 获取待处理询盘表单
  345 + * @param int $num
  346 + * @return mixed
  347 + */
  348 + public function getInquiry($num = 10)
  349 + {
  350 + $result = ReInquiryForm::where(['status' => ReInquiryForm::STATUS_INIT])->orderBy('id', 'asc')->limit($num)->get();
  351 + return $result;
  352 + }
  353 +
  354 + /**
  355 + * 获取广告任务配置数据
  356 + * @param $ad_id
  357 + * @return array
  358 + */
  359 + public function getAdTask($ad_id)
  360 + {
  361 + $cache_key = 'inquiry_ads_task';
  362 + $ads = Cache::get($cache_key, function () use ($cache_key) {
  363 + $ads = ReInquiryTask::where(['status' => ReInquiryTask::STATUS_OPEN])->get(['id', 'ad_id', 'num', 'target']);
  364 + $array = [];
  365 + foreach ($ads as $key=>$val) {
  366 + $array[$val->ad_id] = $val;
  367 + }
  368 + if ($array)
  369 + Cache::put($cache_key, $array, 60);
  370 + return $array;
  371 + });
  372 + return empty($ads[$ad_id]) ? [] : $ads[$ad_id];
  373 + }
  374 +
  375 + /**
  376 + * 通过国家简码获取国家名称
  377 + * @param $code
  378 + * @return string
  379 + */
  380 + public function getCountry($code)
  381 + {
  382 + $cache_key = 'inquiry_world_country';
  383 + $country_code = Cache::get($cache_key, function () use ($cache_key) {
  384 + $country_code = DB::table('gl_world_country_city')->where(['pid' => 0])->pluck('chinese_name', 'iso2')->toArray();
  385 + Cache::put($cache_key, $country_code, 86400);
  386 + return $country_code;
  387 + });
  388 + return empty($country_code[$code]) ? '' : $country_code[$code];
  389 + }
  390 +
  391 + /**
  392 + * 获取头信息
  393 + * @param $ip_area
  394 + * @param $lang
  395 + * @return int|string
  396 + */
  397 + public function getReferer($ip_area, $lang)
  398 + {
  399 + if($lang == 'ru'){
  400 + return $this->get_rand($this->eylyzb);
  401 + }
  402 + if($ip_area == '美国'){
  403 + $referer = $this->get_rand($this->lyzb);
  404 + }else{
  405 + $referer = 'https://www.google.com/';
  406 + $suffix = array_search($ip_area, $this->suffix);
  407 + if($suffix){
  408 + $res_qtzb = $this->get_rand($this->otherzb);
  409 + if($res_qtzb == 1){
  410 + $referer = 'https://www.google.'.$suffix.'/';
  411 + }
  412 + }
  413 + }
  414 + return $referer;
  415 + }
  416 +
  417 + /**
  418 + * 概率算法
  419 + * @param $proArr
  420 + * @return int|string
  421 + */
  422 + protected function get_rand($proArr)
  423 + {
  424 + $result = '';
  425 + $proSum = array_sum($proArr);
  426 + foreach ($proArr as $key => $proCur) {
  427 + $randNum = mt_rand(1, $proSum);
  428 + if ($randNum <= $proCur) {
  429 + $result = $key;
  430 + break;
  431 + } else {
  432 + $proSum -= $proCur;
  433 + }
  434 + }
  435 + unset ($proArr);
  436 + return $result;
  437 + }
  438 +
  439 + /**
  440 + * 获取sitemap内容
  441 + * @param $sitemapUrl
  442 + * @return array|mixed
  443 + */
  444 + function getLinksFromSitemap($sitemapUrl) {
  445 + try {
  446 + //忽略cert证书 先下载到临时文件
  447 + $result = Http::withoutVerifying()->get($sitemapUrl)->body();
  448 + $tempFilePath = tempnam(sys_get_temp_dir(), 'remote_file_');
  449 + file_put_contents($tempFilePath, $result);
  450 + $xml = simplexml_load_file($tempFilePath);
  451 + $links = [];
  452 + foreach ($xml->url as $url) {
  453 + $loc = (string) $url->loc;
  454 + if(!Str::contains($loc, ['404', 'thanks'])){
  455 + $links[] = $loc;
  456 + }
  457 + }
  458 + //随机取20个
  459 + $total = count($links);
  460 + return Arr::random($links, $total > 20 ? 20 : $total);
  461 + }catch (\Exception $e){
  462 + echo date('Y-m-d H:i:s') . 'sitemap获取失败:' . $e->getMessage() . PHP_EOL;
  463 + return $links??[];
  464 + }
  465 + }
  466 +
  467 + /**
  468 + * @return \Psr\Log\LoggerInterface
  469 + */
  470 + public function logChannel()
  471 + {
  472 + return Log::channel('inquiry_relay');
  473 + }
  474 +
  475 + public function output($message)
  476 + {
  477 + echo date('Y-m-d H:i:s') . ' | ' . $message . PHP_EOL;
  478 + }
  479 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2024/09/30
  6 + * Time: 14:01
  7 + */
  8 +namespace App\Console\Commands\Inquiry;
  9 +
  10 +use App\Models\Inquiry\ReInquiryForm;
  11 +use Illuminate\Console\Command;
  12 +
  13 +/**
  14 + * Class SyncInquiry
  15 + * @package App\Console\Commands\Inquiry
  16 + */
  17 +class SyncInquiry extends Command
  18 +{
  19 + /**
  20 + * The name and signature of the console command.
  21 + *
  22 + * @var string
  23 + */
  24 + protected $signature = 'sync_inquiry';
  25 +
  26 + /**
  27 + * The console command description.
  28 + *
  29 + * @var string
  30 + */
  31 + protected $description = '同步询盘信息';
  32 +
  33 + /**
  34 + * Create a new command instance.
  35 + *
  36 + * @return void
  37 + */
  38 + public function __construct()
  39 + {
  40 + parent::__construct();
  41 + }
  42 +
  43 + /**
  44 + * TODO 定时任务,去同步询盘列表
  45 + * FIXME 不在同步时直接拆分转发目标, 是考虑到之后有其他渠道也需要转发, 就只需要在询盘表添加数据即可完成转发功能
  46 + * @return bool
  47 + */
  48 + public function handle()
  49 + {
  50 + while (true) {
  51 + $result = $this->getInquiry();
  52 + if ($result->isEmpty())
  53 + return true;
  54 + // 询盘数据入库
  55 + foreach ($result as $key=>$val) {
  56 + ReInquiryForm::createInquiry();
  57 + }
  58 + }
  59 + return true;
  60 + }
  61 +
  62 + /**
  63 + * 获取远程询盘信息
  64 + * @return bool
  65 + */
  66 + public function getInquiry()
  67 + {
  68 +
  69 + return true;
  70 + }
  71 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2024/10/8
  6 + * Time: 15:32
  7 + */
  8 +namespace App\Http\Controllers\Aside\Task;
  9 +
  10 +use App\Enums\Common\Code;
  11 +use App\Http\Controllers\Aside\BaseController;
  12 +use App\Models\Inquiry\ReInquiryDetail;
  13 +use App\Models\Inquiry\ReInquiryForm;
  14 +use App\Models\Inquiry\ReInquiryTask;
  15 +use Illuminate\Http\Request;
  16 +
  17 +/**
  18 + * Class AdsController
  19 + * @package App\Http\Controllers\Aside\Special
  20 + */
  21 +class AdsController extends BaseController
  22 +{
  23 +
  24 + /**
  25 + * 广告列表
  26 + * @param Request $request
  27 + * @return \Illuminate\Http\JsonResponse
  28 + */
  29 + public function fbAdsList(Request $request)
  30 + {
  31 + $ads_id = trim($request->input('ads_id'));
  32 + $industry = trim($request->input('industry'));
  33 + $result = ReInquiryTask::where(['status' => ReInquiryTask::STATUS_OPEN])
  34 + ->when($ads_id, function ($query, $ads_id) {
  35 + return $query->where('ad_id', 'like', '%' . $ads_id . '%');
  36 + })
  37 + ->when($industry, function ($query, $industry) {
  38 + return $query->where('industry', $industry);
  39 + })
  40 + ->orderBy('id', 'desc')
  41 + ->paginate();
  42 + return $this->response('success', Code::SUCCESS, $result);
  43 + }
  44 +
  45 + /**
  46 + * 新增或修改广告
  47 + * @param Request $request
  48 + * @return \Illuminate\Http\JsonResponse
  49 + */
  50 + public function setFbAds(Request $request)
  51 + {
  52 + $id = intval($request->input('id'));
  53 + $title = trim($request->input('title'));
  54 + $industry = trim($request->input('industry'));
  55 + $ad_id = trim($request->input('ad_id'));
  56 + $ad_url = trim($request->input('ad_url'));
  57 + $ad_img = trim($request->input('ad_img'));
  58 + $num = intval($request->input('num'));
  59 + $status = intval($request->input('status'));
  60 + if (empty($title) || empty($ad_id))
  61 + return $this->response('请填写完整信息!', Code::USER_ERROR, []);
  62 +
  63 + ReInquiryTask::createTask($id, $title, $industry, $ad_id, $ad_url, $ad_img, $num, $status);
  64 + return $this->response('success', Code::SUCCESS, []);
  65 + }
  66 +
  67 + /**
  68 + * 设置转发站点
  69 + * @param Request $request
  70 + */
  71 + public function setRelaySite(Request $request)
  72 + {}
  73 +
  74 + /**
  75 + * 验证站点5.0还是6.0, 代理商信息
  76 + * @param Request $request
  77 + */
  78 + public function checkDomain(Request $request)
  79 + {}
  80 +
  81 + /**
  82 + * FB广告产生询盘列表
  83 + * @param Request $request
  84 + * @return \Illuminate\Http\JsonResponse
  85 + */
  86 + public function fbInquiryList(Request $request)
  87 + {
  88 + $status = intval($request->input('status'));
  89 + $result = ReInquiryForm::when($status, function ($query, $status) {
  90 + return $query->where('status', $status);
  91 + })
  92 + ->orderBy('id', 'desc')
  93 + ->paginate();
  94 + return $this->response('success', Code::SUCCESS, $result);
  95 + }
  96 +
  97 + /**
  98 + * FB询盘转发详情
  99 + * @param Request $request
  100 + * @return \Illuminate\Http\JsonResponse
  101 + */
  102 + public function fbRelayDetail(Request $request)
  103 + {
  104 + $status = intval($request->input('status'));
  105 + $result = ReInquiryDetail::with('detailLog')
  106 + ->when($status, function ($query, $status) {
  107 + return $query->where('status', $status);
  108 + })
  109 + ->orderBy('id', 'desc')
  110 + ->paginate();
  111 + return $this->response('success', Code::SUCCESS, $result);
  112 + }
  113 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2024/9/30
  6 + * Time: 14:56
  7 + */
  8 +namespace App\Models\Inquiry;
  9 +
  10 +use Illuminate\Database\Eloquent\Model;
  11 +
  12 +/**
  13 + * 询盘转发详情
  14 + * Class ReInquiryDetail
  15 + * @package App\Models\Inquiry
  16 + */
  17 +class ReInquiryDetail extends Model
  18 +{
  19 + /**
  20 + * @var string
  21 + */
  22 + protected $table = 'gl_re_inquiry_detail';
  23 +
  24 + /**
  25 + * 任务状态, 0:初始化,1:待处理,2:处理成功,3:抛弃数据,9:处理失败
  26 + */
  27 + const STATUS_INIT = 0;
  28 + const STATUS_PEND = 1;
  29 + const STATUS_SUCCESS = 2;
  30 + const STATUS_FORGO = 3;
  31 + const STATUS_FAIL = 9;
  32 +
  33 + /**
  34 + * 状态映射
  35 + * @return array
  36 + */
  37 + public static function statusMap()
  38 + {
  39 + return [
  40 + self::STATUS_INIT => '初始化',
  41 + self::STATUS_PEND => '待处理',
  42 + self::STATUS_SUCCESS => '处理成功',
  43 + self::STATUS_FORGO => '抛弃数据',
  44 + self::STATUS_FAIL => '处理失败',
  45 + ];
  46 + }
  47 +
  48 + /**
  49 + * 创建询盘转发详情待处理任务
  50 + * @param $task_id
  51 + * @param $form_id
  52 + * @param $re_website
  53 + * @param $country
  54 + * @param $ip
  55 + * @param $name
  56 + * @param $email
  57 + * @param $phone
  58 + * @param $message
  59 + * @param $text_id
  60 + * @param $device_port
  61 + * @param $user_agent
  62 + * @param $referrer
  63 + * @param $urls
  64 + * @param $is_v6
  65 + * @param $start_at
  66 + * @param int $status
  67 + * @return ReInquiryDetail
  68 + */
  69 + public static function createInquiry($task_id, $form_id, $re_website, $country, $ip, $name, $email, $phone, $message, $text_id, $device_port,
  70 + $user_agent, $referrer, $urls, $is_v6, $start_at, $status = self::STATUS_INIT)
  71 + {
  72 + $self = new self();
  73 + $self->task_id = $task_id;
  74 + $self->form_id = $form_id;
  75 + $self->re_website = $re_website;
  76 + $self->country = $country;
  77 + $self->ip = $ip;
  78 + $self->name = $name;
  79 + $self->email = $email;
  80 + $self->phone = $phone;
  81 + $self->message = $message;
  82 + $self->text_id = $text_id;
  83 + $self->device_port = $device_port;
  84 + $self->user_agent = $user_agent;
  85 + $self->referrer = $referrer;
  86 + $self->urls = json_encode($urls);
  87 + $self->is_v6 = $is_v6;
  88 + $self->num = count($urls) + 1;
  89 + $self->start_at = $start_at;
  90 + $self->status = $status;
  91 + $self->save();
  92 + return $self;
  93 + }
  94 +
  95 + /**
  96 + * 转发日志详情
  97 + * @return \Illuminate\Database\Eloquent\Relations\HasMany
  98 + */
  99 + public function detailLog()
  100 + {
  101 + return $this->hasMany(ReInquiryDetailLog::class, 'detail_id', 'id');
  102 + }
  103 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2024/10/08
  6 + * Time: 14:10
  7 + */
  8 +namespace App\Models\Inquiry;
  9 +
  10 +use Illuminate\Database\Eloquent\Model;
  11 +
  12 +/**
  13 + * 转发详情日志
  14 + * Class ReInquiryDetailLog
  15 + * @package App\Models\Inquiry
  16 + */
  17 +class ReInquiryDetailLog extends Model
  18 +{
  19 + /**
  20 + * @var string
  21 + */
  22 + protected $table = 'gl_re_inquiry_detail_log';
  23 +
  24 + /**
  25 + * 任务状态, 0:初始化,1:待处理,2:处理成功,9:处理失败
  26 + */
  27 + const STATUS_INIT = 0;
  28 + const STATUS_PEND = 1;
  29 + const STATUS_SUCCESS = 2;
  30 + const STATUS_FAIL = 9;
  31 +
  32 + /**
  33 + * 执行类型, 1:访问, 2:询盘
  34 + */
  35 + const TYPE_VISIT = 1;
  36 + const TYPE_INQUIRY = 2;
  37 +
  38 + /**
  39 + * 状态映射
  40 + * @return array
  41 + */
  42 + public static function statusMap()
  43 + {
  44 + return [
  45 + self::STATUS_INIT => '初始化',
  46 + self::STATUS_PEND => '待处理',
  47 + self::STATUS_SUCCESS => '处理成功',
  48 + self::STATUS_FAIL => '处理失败',
  49 + ];
  50 + }
  51 +
  52 +
  53 + /**
  54 + * 创建转发详情日志
  55 + * @param $detail_id
  56 + * @param $type
  57 + * @param $pre
  58 + * @param $url
  59 + * @param $start_at
  60 + * @return ReInquiryDetailLog
  61 + */
  62 + public static function createInquiryLog($detail_id, $type, $pre, $url, $start_at)
  63 + {
  64 + $self = self::where(compact('detail_id', 'type', 'pre'))->first();
  65 + if ($self)
  66 + return $self;
  67 + $self = new self();
  68 + $self->detail_id = $detail_id;
  69 + $self->type = $type;
  70 + $self->pre = $pre;
  71 + $self->url = $url;
  72 + $self->start_at = $start_at;
  73 + $self->save();
  74 + return $self;
  75 + }
  76 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2024/9/30
  6 + * Time: 14:31
  7 + */
  8 +namespace App\Models\Inquiry;
  9 +
  10 +use Illuminate\Database\Eloquent\Model;
  11 +
  12 +/**
  13 + * 广告询盘表单内容
  14 + * Class ReInquiryForm
  15 + * @package App\Models\Inquiry
  16 + */
  17 +class ReInquiryForm extends Model
  18 +{
  19 + /**
  20 + * @var string
  21 + */
  22 + protected $table = 'gl_re_inquiry_form';
  23 +
  24 + /**
  25 + * 任务状态, 1:待处理,2:处理成功,3:抛弃数据,9:处理失败
  26 + */
  27 + const STATUS_INIT = 1;
  28 + const STATUS_SUCCESS = 2;
  29 + const STATUS_FORGO = 3;
  30 + const STATUS_FAIL = 9;
  31 +
  32 + /**
  33 + * 状态映射
  34 + * @return array
  35 + */
  36 + public static function statusMap()
  37 + {
  38 + return [
  39 + self::STATUS_INIT => '待处理',
  40 + self::STATUS_SUCCESS => '处理成功',
  41 + self::STATUS_FORGO => '抛弃数据',
  42 + self::STATUS_FAIL => '处理失败',
  43 + ];
  44 + }
  45 +
  46 + /**
  47 + * 创建询盘表单信息
  48 + * @param $id
  49 + * @param $origin_id
  50 + * @param $ad_set_id
  51 + * @param $ad_set_name
  52 + * @param $ad_id
  53 + * @param $ad_name
  54 + * @param $full_name
  55 + * @param $email
  56 + * @param $phone
  57 + * @param $whatsapp
  58 + * @param $message
  59 + * @param $country
  60 + * @param $inquiry_date
  61 + * @return mixed
  62 + */
  63 + public static function createInquiry($id, $origin_id, $ad_set_id, $ad_set_name, $ad_id, $ad_name, $full_name, $email, $phone, $whatsapp, $message, $country, $inquiry_date)
  64 + {
  65 + $self = self::where(['id' => $id])->first();
  66 + if (empty($self)) {
  67 + $self = new self();
  68 + // 同步 表单内容,以ID为唯一值
  69 + $self->id = $id;
  70 + }
  71 + $self->origin_id = $origin_id;
  72 + $self->ad_set_id = $ad_set_id;
  73 + $self->ad_set_name = $ad_set_name;
  74 + $self->ad_id = $ad_id;
  75 + $self->ad_name = $ad_name;
  76 + $self->full_name = $full_name;
  77 + $self->email = $email;
  78 + $self->phone = $phone;
  79 + $self->whatsapp = $whatsapp;
  80 + $self->message = $message;
  81 + $self->inquiry_date = $inquiry_date;
  82 + $self->country = $country;
  83 + $self->save();
  84 + return $self;
  85 + }
  86 +
  87 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2024/9/30
  6 + * Time: 14:12
  7 + */
  8 +namespace App\Models\Inquiry;
  9 +
  10 +use Illuminate\Database\Eloquent\Model;
  11 +
  12 +/**
  13 + * 广告转询盘任务
  14 + * Class ReInquiryTask
  15 + * @package App\Models\Inquiry
  16 + */
  17 +class ReInquiryTask extends Model
  18 +{
  19 + /**
  20 + * @var string
  21 + */
  22 + protected $table = 'gl_re_inquiry_task';
  23 +
  24 + /**
  25 + * 任务状态, 1:开启(默认), 0:关闭
  26 + */
  27 + const STATUS_OPEN = 1;
  28 + const STATUS_CLOSE = 0;
  29 +
  30 + /**
  31 + * 创建询盘任务
  32 + * @param $id
  33 + * @param $title
  34 + * @param $industry
  35 + * @param $ad_id
  36 + * @param $ad_url
  37 + * @param $ad_img
  38 + * @param $num
  39 + * @param int $status
  40 + * @return ReInquiryTask
  41 + */
  42 + public static function createTask($id, $title, $industry, $ad_id, $ad_url, $ad_img, $num, $status = self::STATUS_OPEN)
  43 + {
  44 + $self = self::where(['id' => $id])->first();
  45 + if (empty($self))
  46 + $self = new self();
  47 + $self->title = $title;
  48 + $self->industry = $industry;
  49 + $self->ad_id = $ad_id;
  50 + $self->ad_url = $ad_url;
  51 + $self->ad_img = $ad_img;
  52 + $self->num = $num;
  53 + $self->status = $status;
  54 + $self->save();
  55 + return $self;
  56 + }
  57 +
  58 + /**
  59 + * @param $value
  60 + * @return mixed
  61 + */
  62 + public function getTargetAttribute($value)
  63 + {
  64 + return json_decode($value, true);
  65 + }
  66 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2024/9/30
  6 + * Time: 14:23
  7 + */
  8 +namespace App\Models\Inquiry;
  9 +
  10 +use Illuminate\Database\Eloquent\Model;
  11 +
  12 +/**
  13 + * 询盘内置文案
  14 + * Class ReInquiryText
  15 + * @package App\Models\Inquiry
  16 + */
  17 +class ReInquiryText extends Model
  18 +{
  19 + /**
  20 + * @var string
  21 + */
  22 + protected $table = 'gl_re_inquiry_text';
  23 +
  24 + /**
  25 + * 文案状态, 1:开启(默认), 2:禁用
  26 + */
  27 + const STATUS_USABLE = 1;
  28 + const STATUS_DISABLE = 2;
  29 +
  30 + /**
  31 + * 创建询盘内置文案
  32 + * @param $id
  33 + * @param $title
  34 + * @param $content
  35 + * @param int $status
  36 + * @return ReInquiryText
  37 + */
  38 + public static function createText($id, $title, $content, $status = self::STATUS_USABLE)
  39 + {
  40 + $self = self::where(['id' => $id])->first();
  41 + if (empty($self)) {
  42 + $self = new self();
  43 + // 同步 询盘文案,以ID为唯一值
  44 + $self->id = $id;
  45 + }
  46 + $self->title = $title;
  47 + $self->content = $content;
  48 + $self->status = $status;
  49 + $self->save();
  50 + return $self;
  51 + }
  52 +
  53 +}
@@ -172,6 +172,13 @@ return [ @@ -172,6 +172,13 @@ return [
172 'emergency' => [ 172 'emergency' => [
173 'path' => storage_path('logs/laravel.log'), 173 'path' => storage_path('logs/laravel.log'),
174 ], 174 ],
  175 +
  176 + 'inquiry_relay' => [
  177 + 'driver' => 'daily',
  178 + 'path' => storage_path('logs/inquiry_relay/laravel.log'),
  179 + 'level' => 'debug',
  180 + 'days' => 14,
  181 + ],
175 ], 182 ],
176 //操作日志 183 //操作日志
177 'operator_log' =>[ 184 'operator_log' =>[
@@ -473,6 +473,15 @@ Route::middleware(['aloginauth'])->group(function () { @@ -473,6 +473,15 @@ Route::middleware(['aloginauth'])->group(function () {
473 Route::any('/saveTask', [Aside\AutoPull\AutoPullController::class, 'saveTask'])->name('admin.auto_pull_saveTask'); 473 Route::any('/saveTask', [Aside\AutoPull\AutoPullController::class, 'saveTask'])->name('admin.auto_pull_saveTask');
474 Route::any('/taskMap', [Aside\AutoPull\AutoPullController::class, 'taskMap'])->name('admin.auto_pull_taskMap'); 474 Route::any('/taskMap', [Aside\AutoPull\AutoPullController::class, 'taskMap'])->name('admin.auto_pull_taskMap');
475 }); 475 });
  476 +
  477 + // 任务相关
  478 + Route::prefix('task')->group(function () {
  479 + // FB广告相关路由
  480 + Route::any('/fb_list', [Aside\Task\AdsController::class, 'fbAdsList'])->name('admin.fb_ads_task_list');
  481 + Route::any('/fb_set', [Aside\Task\AdsController::class, 'setFbAds'])->name('admin.fb_ads_task_set');
  482 + Route::any('/fb_inquiry_list', [Aside\Task\AdsController::class, 'fbInquiryList'])->name('admin.fb_ads_inquiry_list');
  483 + Route::any('/fb_relay_detail_list', [Aside\Task\AdsController::class, 'fbRelayDetail'])->name('admin.fb_ads_relay_detail_list');
  484 + });
476 }); 485 });
477 486
478 //无需登录验证的路由组 487 //无需登录验证的路由组