InquiryForwardLogic.php 13.1 KB
<?php

namespace App\Http\Logic\Aside\Optimize;

use App\Helper\Common;
use App\Helper\Gpt;
use App\Helper\Translate;
use App\Http\Logic\Aside\BaseLogic;
use App\Models\Ai\AiCommand;
use App\Models\Inquiry\AreaTimezone;
use App\Models\Inquiry\InquiryInfo;
use App\Models\Inquiry\InquiryProject;
use App\Models\Inquiry\InquiryProjectRoute;
use App\Models\Inquiry\InquiryRelayDetail;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

/**
 * @remark :询盘中心
 * @class  :InquiryForwardLogic.php
 * @author :akun
 * @time   :2025/2/21 11:17
 */
class InquiryForwardLogic extends BaseLogic
{

    public function __construct()
    {
        parent::__construct();
        $this->param = $this->requestAll;
        $this->model = new InquiryInfo();
    }

    /**
     * 获取询盘类型
     * @return array
     * @author Akun
     * @date 2025/02/21 11:19
     */
    public function getType()
    {
        $type = $this->model->typeMap();
        $list = [];
        foreach ($type as $k => $v) {
            $list[] = [
                'id' => $k,
                'name' => $v
            ];
        }
        return $this->success($list);
    }

    /**
     * 获取询盘列表
     * @param $map
     * @param $page
     * @param $row
     * @param string $order
     * @param string[] $filed
     * @return array
     * @author Akun
     * @date 2025/02/21 11:19
     */
    public function getInquiryLists($map, $page, $row, $order = 'id', $filed = ['*'])
    {
        $lists = $this->model->lists($map, $page, $row, $order, $filed);
        //统计各个状态询盘总数
        unset($map['status']);
        $lists['count_stat'] = [
            'all_count' => $this->formatQuery($map,new InquiryInfo())->count(),
            'un_count' => $this->formatQuery($map,new InquiryInfo())->where('status', InquiryInfo::STATUS_INIT)->count(),
            'suc_count' => $this->formatQuery($map,new InquiryInfo())->where('status', InquiryInfo::STATUS_FINISH)->count(),
            'inv_count' => $this->formatQuery($map,new InquiryInfo())->where('status', InquiryInfo::STATUS_INVALID)->count(),
        ];

        return $this->success($lists);
    }

    /**
     * 获取询盘详情
     * @return array
     * @throws \App\Exceptions\AsideGlobalException
     * @throws \App\Exceptions\BsideGlobalException
     * @author Akun
     * @date 2025/03/01 11:20
     */
    public function infoInquiry()
    {
        $info = $this->model->read(['id' => $this->param['id']], ['id', 'url', 'url_title', 'url_keyword', 'name', 'email', 'phone', 'ip', 'country', 'message']);
        if ($info === false) {
            $this->fail('获取询盘详情失败');
        }
        return $this->success($info);
    }

    /**
     * 转发询盘
     * @return array
     * @throws \App\Exceptions\AsideGlobalException
     * @throws \App\Exceptions\BsideGlobalException
     * @author Akun
     * @date 2025/02/21 14:54
     */
    public function inquiryForward()
    {
        $info = $this->model->read(['id' => $this->param['id']]);
        if ($info === false) {
            $this->fail('获取询盘详情失败');
        }
        if ($info['status'] != InquiryInfo::STATUS_INIT) {
            $this->fail('当前询盘状态无法转发');
        }

        DB::beginTransaction();
        try {
            $num = 0;
            $now = date('Y-m-d H:i:s');
            if (is_array($this->param['forward_url'])) {
                $forward_url = $this->param['forward_url'];
            } else {
                $forward_url = explode(',', $this->param['forward_url']);
            }
            foreach ($forward_url as $url) {
                $url = trim($url);
                $domain_array = parse_url($url);
                $website = $domain_array['host'] ?? '';
                if (!$website) {
                    continue;
                }

                //获取站点对应项目版本
                $project_version = InquiryProject::select(['version'])->where('domain', 'like', '%' . $website . '%')->first();
                if (!$project_version) {
                    continue;
                }
                $is_v6 = $project_version->version == 6 ? 1 : 0;


                //获取发送时间
                if (isset($this->param['inquiry_date']) && $this->param['inquiry_date']) {
                    //填写了时间,直接使用
                    $start_at = $this->param['inquiry_date'];
                } else {
                    //未填写时间
                    //1.根据时差获取当地随机10-18点时间
                    $timezoneModel = new AreaTimezone();
                    $country_area = $timezoneModel->read(['name' => $info['country']], ['diff']);
                    $diff = $country_area ? $country_area['diff'] : 0;
                    if ($diff > 0) {
                        $area_time = date('Y-m-d H:i:s', strtotime($now . ' +' . $diff . ' hours'));
                    } elseif ($diff < 0) {
                        $area_time = date('Y-m-d H:i:s', strtotime($now . ' -' . abs($diff) . ' hours'));
                    } else {
                        $area_time = $now;
                    }
                    $area_timestamp = strtotime($area_time);
                    $area_hour = date('H', $area_timestamp);
                    if ($area_hour < 18) {
                        //当地时间为18点前
                        $area_day = date('Y-m-d', $area_timestamp);
                        $area_start_time = $area_hour < 10 ? '10:00:00' : date('H:i:s', $area_timestamp);
                    } else {
                        //当地时间为18点后,顺延一天
                        $area_day = date('Y-m-d', strtotime($area_time . ' +1 day'));
                        $area_start_time = '10:00:00';
                    }
                    $start_time = strtotime($area_day . ' ' . $area_start_time);
                    $end_time = strtotime($area_day . ' 18:00:00');
                    $random_timestamp = mt_rand($start_time, $end_time);
                    $area_date = date('Y-m-d H:i:s', $random_timestamp);

                    //2.再根据时差将随机生成的当地时间换算成国内时间
                    if ($diff > 0) {
                        $start_at = date('Y-m-d H:i:s', strtotime($area_date . ' -' . $diff . ' hours'));
                    } elseif ($diff < 0) {
                        $start_at = date('Y-m-d H:i:s', strtotime($area_date . ' +' . abs($diff) . ' hours'));
                    } else {
                        $start_at = $area_date;
                    }
                }

                //换算后的国内时间小于当前时间,使用当前时间
                if ($start_at < $now) {
                    $start_at = $now;
                }

                InquiryRelayDetail::createInquiry($info['id'], $website, $info['country'], $this->param['ip'], $this->param['name'], $this->param['email'], $this->param['phone'] ?? '', $this->param['message'], $is_v6, json_encode([$url]), $start_at);

                $num += 1;
            }

            //更改询盘状态及转发数量
            $this->model->edit(['status' => InquiryInfo::STATUS_FINISH, 'num' => $num], ['id' => $this->param['id']]);

            DB::commit();
        } catch (\Exception $e) {
            DB::rollback();

            @file_put_contents(storage_path('logs/lk_error.log'), $e->getMessage());
            $this->fail('转发询盘失败');
        }

        return $this->success();
    }

    /**
     * 获取随机ip
     * @return array
     * @throws \App\Exceptions\AsideGlobalException
     * @throws \App\Exceptions\BsideGlobalException
     * @author Akun
     * @date 2025/02/26 15:50
     */
    public function getIp()
    {
        $ip = DB::table('gl_xunpan_ipdata')->where('ip_area', $this->param['country'])->inRandomOrder()->value('ip');
        if (!$ip) {
            $this->fail('当前国家无法获取随机ip');
        }

        return $this->success(['ip' => $ip]);
    }

    /**
     * 关键词查询项目着陆页
     * @return int|mixed
     * @author Akun
     * @date 2025/02/26 17:13
     */
    public function searchKeywords()
    {
        $num = $this->param['num'] ?? 3;

        $model = new InquiryProjectRoute();
        if ($this->param['type'] == 1) {
            //使用全文索引搜索
            $routeQuery = $model->select(['project_id', 'route'])->whereRaw("MATCH(title) AGAINST(? IN BOOLEAN MODE)", [$this->param['keywords']]);
        } else {
            //使用like查询
            $routeQuery = $model->select(['project_id', 'route'])->where('title', 'like', '%' . $this->param['keywords'] . '%');
        }

        $re_route = $routeQuery->inRandomOrder()->take(100)->get()->toArray();

        $lists = [];
        if (count($re_route) > 0) {
            //根据项目id查询项目,并根据询盘量排序
            $project_ids = array_column($re_route, 'project_id');
            $re_project = InquiryProject::select(['id', 'project', 'channel', 'domain'])->whereIn('id', $project_ids)->orderBy('recent_inquiry', 'asc')->get();

            if ($re_project->count() > 0) {
                //根据代理商去重
                $channel = [];
                foreach ($re_project as $vp) {
                    $vp_channel = explode(',', $vp->channel);
                    $has_channel = 0;
                    foreach ($vp_channel as $vpc) {
                        if (in_array($vpc, $channel)) {
                            $has_channel = 1;
                        }
                    }

                    if ($has_channel == 0) {
                        $channel = array_merge($channel, $vp_channel);

                        $route = '';
                        foreach ($re_route as $vr) {
                            if ($vr['project_id'] == $vp->id) {
                                $route = $vr['route'];
                                break;
                            }
                        }
                        if (substr($route, -5) != '.html') {
                            $route = $route . '/';
                        }

                        $lists[] = [
                            'id' => $vp->id,
                            'project' => $vp->project,
                            'route' => $vp->domain . $route
                        ];
                    }
                }
            }
        }

        return $this->success(array_slice($lists, 0, $num, true));
    }

    /**
     * AI重写询盘文案
     * @return array
     * @throws \App\Exceptions\AsideGlobalException
     * @throws \App\Exceptions\BsideGlobalException
     * @author Akun
     * @date 2025/02/27 10:40
     */
    public function aiRewrite()
    {
        $ai_info = AiCommand::select(['ai', 'not_use_probability'])->where('key', 'inquiry_text_rewrite')->first();
        if (!$ai_info) {
            $this->fail('AI重写指令未配置');
        }

        $ai_command = $ai_info['ai'];
        $not_use_probability = $ai_info['not_use_probability'];
        $in_content = $this->param['message'];

        // 当原始询盘内容长度大于15个字符, 60%几率直接发送原始内容。
        if (strlen($in_content) >= 15) {
            $randomNumber = rand(0, 100);
            if ($randomNumber < $not_use_probability) {
                return $this->success(['ai_message' => $in_content]);
            }
        }

        $translateSl = Translate::translateSl($in_content);
        $lang = $translateSl['texts']['sl'] ?? 'en';
        if ($lang == 'en' || $lang == 'ja' || $lang == 'ko' || Str::contains($lang, 'zh')) {
            $lang = 'en';
        }

        $ai_command = str_replace('{incontent}', Arr::random(explode("\r\n", $in_content)), $ai_command);

        $text = Gpt::instance()->openai_chat_qqs($ai_command);
        if ($lang != 'en' && !Str::contains($lang, 'zh')) {
            $text = Translate::tran($text, $lang);
        }

        return $this->success(['ai_message' => Common::deal_str($text)]);
    }

    /**
     * 设置询盘无效
     * @return array
     * @throws \App\Exceptions\AsideGlobalException
     * @throws \App\Exceptions\BsideGlobalException
     * @author Akun
     * @date 2025/02/27 15:36
     */
    public function expiredInquiry()
    {
        if (isset($this->param['type']) && $this->param['type'] == 1) {
            //启用
            $status = InquiryInfo::STATUS_INIT;
        } else {
            //无效
            $status = InquiryInfo::STATUS_INVALID;
        }
        $rs = $this->model->edit(['status' => $status], ['id' => $this->param['id']]);

        if ($rs === false) {
            $this->fail('设置失败');
        }
        return $this->success();
    }

    /**
     * 获取询盘转发详情列表
     * @param $map
     * @param $page
     * @param $row
     * @param string $order
     * @param string[] $filed
     * @return array
     * @author Akun
     * @date 2025/03/01 9:22
     */
    public function getInquiryDetailLists($map, $page, $row, $order = 'id', $filed = ['*'])
    {
        $model = new InquiryRelayDetail();
        $lists = $model->listsWith($map, $page, $row, $order, $filed, 'desc', ['detailLog']);
        return $this->success($lists);
    }
}