作者 刘锟

Merge remote-tracking branch 'origin/master' into akun

正在显示 46 个修改的文件 包含 1217 行增加91 行删除
... ... @@ -73,6 +73,7 @@ class AiBlogListTask extends Command
$saveData = [];
$result = $aiBlogService->getAiBlogList($page,15);
if(!isset($result['status']) || $result['status'] != 200){
echo '请示失败。'.json_encode($result, JSON_UNESCAPED_UNICODE);
return true;
}
$total_page = $result['data']['total_page'];
... ...
... ... @@ -43,7 +43,7 @@ class RemainDay extends Command
* @var 暂停的项目
*/
protected $ceaseProjectId = [
354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250, 2193, 2399, 1685, 3931
354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250, 2193, 2399, 1685, 3931,2273,3647
];//需要单独处理的项目
/**
* The console command description.
... ...
... ... @@ -12,6 +12,7 @@ use App\Helper\Gpt;
use App\Helper\Translate;
use App\Helper\Validate;
use App\Models\Ai\AiCommand;
use App\Models\Inquiry\InquiryRelayDetailLog;
use App\Models\Inquiry\ReInquiryConfig;
use App\Models\Inquiry\ReInquiryDetail;
use App\Models\Inquiry\ReInquiryDetailLog;
... ... @@ -24,6 +25,7 @@ use App\Models\WebSetting\WebLanguage;
use GuzzleHttp\Exception\ConnectException;
use Illuminate\Console\Command;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
... ... @@ -433,7 +435,12 @@ class RelayInquiry extends Command
}
//是否有必选的渠道 渠道有一个及以上必选 就在组内随机一个
$require_agent_group = [];
foreach ($task['target'] as $item) {
foreach ($task['target'] as $k=>$item) {
//没有广告费的 按频率来 x天一封 发过了先踢掉 优先级高于必选
if(!$this->checkFrequency($item)){
unset($item[$k]);
continue;
}
if (!empty($item['is_require'])) {
$require_agent_group[] = $item['agent_group'];
}
... ... @@ -517,7 +524,7 @@ class RelayInquiry extends Command
$pre = 0;
$start_time = time();
$seconds = $this->delay_seconds($form->inquiry_date);
$seconds = $this->delay_seconds($form->inquiry_date, $domain, $task);
$email = '';
if($is_inquiry) {
$exists = ReInquiryDetail::where('re_website', $domain)->where('email', $form->email)->first();
... ... @@ -547,6 +554,31 @@ class RelayInquiry extends Command
return true;
}
public function checkFrequency($item)
{
//设置了频率的
if (!empty($item['frequency'])) {
$item['is_ad_fee'] = 0; //v5都没有
if($item['is_v6']){
$project = Project::getProjectByDomain($item['url']);
if($project && $project->deploy_build){
$item['is_ad_fee'] = $project->deploy_build->ads_price ? 1 : 0;
}
}
//没有广告费 是否X天内发送过
if(!$item['is_ad_fee']){
$inquiry_log = InquiryRelayDetailLog::where('type', InquiryRelayDetailLog::TYPE_INQUIRY)
->where('start_at', '>', date('Y-m-d H:i:s', strtotime('- ' . $item['frequency'] . ' day')))
->first();
if($inquiry_log){
$this->output('频率限制');
return false;
}
}
}
return true;
}
public function relayShopDetail($task, $form)
{
$this->output('获取商城转发对象');
... ... @@ -580,7 +612,7 @@ class RelayInquiry extends Command
$referrer = $this->getReferer($country_name, $lang);
$start_time = time();
$seconds = $this->delay_seconds($form->inquiry_date);
$seconds = $this->delay_seconds($form->inquiry_date, $domain, $task);
$exists = ReInquiryDetail::where('re_website', $domain)->where('email', $form->email)->first();
if($exists){
$this->output('转发站点邮件已存在');
... ... @@ -616,7 +648,7 @@ class RelayInquiry extends Command
$user_agent = $form->email ? Arr::random($this->pc_ua) : Arr::random($this->mobile_ua);
$start_time = time();
$seconds = $this->delay_seconds($form->inquiry_date);
$seconds = $this->delay_seconds($form->inquiry_date, $postid, $task);
$exists = ReInquiryDetail::where('re_website', $postid)->where('email', $form->email)->first();
if($exists){
$this->output('转发站点邮件已存在');
... ... @@ -796,7 +828,7 @@ class RelayInquiry extends Command
{
$cache_key = 'inquiry_ads_tasks';
$ads = Cache::get($cache_key, function () use ($cache_key) {
$ads = ReInquiryTask::where(['status' => ReInquiryTask::STATUS_OPEN])->get(['id', 'ad_id', 'num', 'target', 'is_replace_text', 'ai_param', 'shop_site', 'fob_pro']);
$ads = ReInquiryTask::where(['status' => ReInquiryTask::STATUS_OPEN])->get(['id', 'ad_id', 'num', 'target', 'is_replace_text', 'ai_param', 'shop_site', 'fob_pro', 'second_push_rate']);
$array = [];
foreach ($ads as $key=>$val) {
$ad_ids = explode(',', $val['ad_id']);
... ... @@ -945,8 +977,36 @@ class RelayInquiry extends Command
* @author zbj
* @date 2025/7/16
*/
public function delay_seconds($inquiry_date)
public function delay_seconds($inquiry_date, $domain, $task)
{
$inquiry_date = Carbon::make($inquiry_date);
//当天的
if($inquiry_date->isToday()){
//广告投放日(周一、二、三、四) 第一封询盘100%及时推送
$is_timely = true; //是否及时推送
if(in_array($inquiry_date->weekday(), [1,2,3,4])) {
//是否今天的第一封询盘
$detail = ReInquiryDetail::where('re_website', $domain)->where('start_at', '>=', $inquiry_date->startOfDay()->toDatetimeString())->first();
if($detail){
$is_timely = false; //只有周一到周四的非第一封询盘 根据概率及时推送
}
}
//概率及时推送
if(!$is_timely && $task->second_push_rate != 100){
//按概率
$res = $this->get_rand([$task->second_push_rate, 100 - $task->second_push_rate]);
if($res == 1){
$this->output('非广告投放日第一封询盘 概率' . (100 - $task->second_push_rate) . '%延迟推送');
//随机分配到未投放广告日期
$now = Carbon::now();
// 随机开始时间(本周四或现在)
$startTime = max($now->timestamp, $now->startOfWeek(4)->timestamp);
$random = mt_rand($startTime, $now->endOfWeek()->timestamp);
return $random - $now->timestamp;
}
}
}
$seconds = rand(300, 2 * 3600); // 默认 从5分钟-2小时后开始
$time_diff = time() - strtotime($inquiry_date); //2小时前-24小时内的 当天发完
if ($time_diff > 2 * 3600 && $time_diff <= 24 * 3600) {
... ...
... ... @@ -21,8 +21,11 @@ use App\Models\Project\Payment;
use App\Models\Project\Project;
use App\Models\Project\ProjectAiSetting;
use App\Models\Project\ProjectWhiteHatAffix;
use App\Models\RouteMap\RouteMap;
use App\Models\Template\BTemplateMain;
use App\Models\Template\TemplateTypeMain;
use App\Models\WebSetting\Translate;
use App\Models\WebSetting\TranslateData;
use App\Models\WebSetting\WebSetting;
use App\Models\WorkOrder\TicketLog;
use App\Models\WorkOrder\Tickets;
... ... @@ -51,30 +54,7 @@ class lyhDemo extends Command
protected $description = '更新路由';
public function handle(){
$projectModel = new Payment();
$lists = $projectModel->list(['renewal_record'=>['not like','"expire_at": null']]);
foreach ($lists as $item){
foreach ($item['renewal_record'] as $key => $val){
if(!isset($val['end_time']) && !empty($val['expire_at'])){
$val['end_time'] = $val['expire_at'];
}
$item['renewal_record'][$key] = $val;
}
$projectModel->edit(['renewal_record'=>json_encode($item['renewal_record'],true)],['id'=>$item['id']]);
}
return true;
}
public function getExpectResult(){
$geo_service = new GeoService();
$question = 'Top AI Coffee Robot';
$answer = "Top AI Coffee Robot\" refers to advanced robotic systems that combine **precision automation, artificial intelligence, and specialty coffee expertise** to create high-quality beverages with minimal human intervention. Here's a breakdown of key features, leading examples, and benefits:\n\n### Core Features of Top AI Coffee Robots:\n1. **AI-Driven Customization** \n - Analyzes user preferences (strength, milk type, sweetness) via app profiles or voice commands. \n - Learns from feedback to refine future orders (e.g., \"less bitter than last time\"). \n2. **Robotic Precision Brewing** \n - Industrial arms handle grinding, tamping, steaming milk, and latte art with sub-millimeter accuracy. \n - Sensors monitor temperature, extraction time, and pressure for optimal flavor.";
$expect = "While I don't have specific information on the RobotAnno coffee machine, in general";
$str = "客户提出的问题:{$question},客户得到的回复:{$answer},客户需要预期:{$expect},请分析得到的回复和预期是否一致,仅回复我是或者否";
$data = $geo_service->getChatResult($str, 'gpt-4o-mini');
if(isset($data['text']) && $data['text'] == '是'){
}
return $this->translate_action();
}
/**
... ... @@ -257,9 +237,133 @@ class lyhDemo extends Command
echo "字段 $field 小写替换出错:" . $e->getMessage() . PHP_EOL;
}
}
echo '执行结束' . PHP_EOL;
DB::disconnect('custom_mysql');
}
public function translate_action()
{
ProjectServer::useProject(655);
$this->model = new Translate();
$lists = DB::connection('custom_mysql')->table('gl_translate_copy1')->where('url','!=','All')->get()->toArray();
foreach ($lists as $item) {
$item = (array)$item;
$sourceInfo = $this->getRouteSource($item['url']);
$info = $this->model->read(['language_id'=>$item['language_id'],'source_id'=>$sourceInfo['source_id'],'url'=>$item['url'],'project_id'=>655,'type'=>$item['type']]);
if($info === false){
$param = [
'type'=>$item['type'] ?? 1,
'project_id'=>655,
'url'=>$item['url'],
'language_id'=>$item['language_id'],
'alias'=>$item['alias'],
'source'=>$sourceInfo['source'],
'source_id'=>$sourceInfo['source_id'],
'is_list'=>$sourceInfo['is_list'],
'is_custom'=>$sourceInfo['is_custom'],
'page'=>$sendData['page'] ?? 0
];
$id = $this->model->addReturnId($param);
TranslateData::insert(['trans_id'=>$id,'data'=>$item['data']]);
}else{
TranslateData::where(['trans_id'=>$info['id']])->update(['data'=>$item['data']]);
}
}
DB::disconnect('custom_mysql');
}
public function getRouteSource($route){
$routes = $route;
$data = ['source'=>0,'source_id'=>0,'is_list'=>0,'is_custom'=>0,'page'=>0];
if(strtolower($route) == 'all'){
return $data;
}
if($route == 'index' || $route == '/'){
$data['source'] = 1;
return $data;
}
$route = basename($route);
$page = 0;
if (is_numeric($route)) {
$arr = explode('/',$routes);
$page = $route;
$route = $arr[0];
}
$routeModel = new RouteMap();
$routeInfo = $routeModel->read(['route'=>$route]);
if($routeInfo === false){
if(in_array($route,['products','news','blog'])){
//固定路由
$data['page'] = $page;
$data['is_list'] = 1;
if($route == 'products'){
$data['source'] = 2;
}elseif ($route == 'news'){
$data['source'] = 4;
}else{
$data['source'] = 3;
}
return $data;
}
return $data;
}
$data = $this->resultData($routeInfo,$data);
$data['page'] = $page;
return $data;
}
public function resultData($routeInfo,$data){
if($routeInfo['source'] == RouteMap::SOURCE_PAGE){
if($routeInfo['source_id']){
$data = ['source'=>9,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>0];
}
}
if($routeInfo['source'] == RouteMap::SOURCE_PRODUCT){
if($routeInfo['source_id']){
$data = ['source'=>2,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>0];
}
}
if($routeInfo['source'] == RouteMap::SOURCE_PRODUCT_CATE){
if($routeInfo['source_id']){
$data = ['source'=>2,'source_id'=>$routeInfo['source_id'],'is_list'=>1,'is_custom'=>0];
}
}
if($routeInfo['source'] == RouteMap::SOURCE_BLOG){
if($routeInfo['source_id']){
$data = ['source'=>3,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>0];
}
}
if($routeInfo['source'] == RouteMap::SOURCE_BLOG_CATE){
if($routeInfo['source_id']){
$data = ['source'=>3,'source_id'=>$routeInfo['source_id'],'is_list'=>1,'is_custom'=>0];
}
}
if($routeInfo['source'] == RouteMap::SOURCE_NEWS){
if($routeInfo['source_id']){
$data = ['source'=>4,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>0];
}
}
if($routeInfo['source'] == RouteMap::SOURCE_NEWS_CATE){
if($routeInfo['source_id']){
$data = ['source'=>4,'source_id'=>$routeInfo['source_id'],'is_list'=>1,'is_custom'=>0];
}
}
if($routeInfo['source'] == RouteMap::SOURCE_PRODUCT_KEYWORD){
if($routeInfo['source_id']){
$data = ['source'=>8,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>0];
}
}
if($routeInfo['source'] == RouteMap::SOURCE_MODULE){
if($routeInfo['source_id']){
$data = ['source'=>7,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>1];
}
}
if($routeInfo['source'] == RouteMap::SOURCE_MODULE_CATE){
if($routeInfo['source_id']){
$data = ['source'=>7,'source_id'=>$routeInfo['source_id'],'is_list'=>1,'is_custom'=>1];
}
}
return $data;
}
}
... ...
... ... @@ -97,7 +97,7 @@ class SyncSubmitTask extends Command
}
$task_info->save();
Log::channel('inquiry')->error($task_id . '处理失败', [$e->getMessage(), $e->getFile(), $e->getLine()]);
$this->output('任务失败:' . $e->getMessage());
$this->output('任务失败:' . $e->getMessage() . $e->getFile() . $e->getLine());
}
$use_time = time() - $time;
... ...
... ... @@ -83,7 +83,7 @@ class UpdateKeyword extends Command
if($info['update_method'] != 1){
$idArr = shuffle($idArr);
}
if(!$idArr){
if(!is_array($idArr)){
return false;
}
$result = $this->splitArrayIntoParts($idArr,$number);
... ...
... ... @@ -245,4 +245,41 @@ class Arr extends \Illuminate\Support\Arr
}, $arr));
return json_encode(array_values(array_unique(array_filter($array))));
}
/**
* 数组转文本html数组
* @param $array
* @param $indentLevel
* @return array
* @author zbj
* @date 2025/9/26
*/
public static function formatForHtml($array, $indentLevel = 0) {
$result = [];
$indent = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $indentLevel);
foreach ($array as $key => $value) {
$isNumericKey = is_numeric($key);
if (is_array($value)) {
if (!$isNumericKey) {
$result[] = "{$indent}{$key}:<br/>";
$nestedResult = self::formatForHtml($value, $indentLevel + 1);
} else {
$key && $result[] = '<br/>';
$nestedResult = self::formatForHtml($value, $indentLevel);
}
$result = array_merge($result, $nestedResult);
} else {
if ($isNumericKey) {
$result[] = "{$indent}{$value}<br/>";
} else {
$result[] = "{$indent}{$key}: {$value}<br/>";
}
}
}
return $result;
}
}
... ...
... ... @@ -1590,7 +1590,7 @@ if (!function_exists('httpGetSsl')) {
}
/**
* @remark :截取自付出啊
* @remark :截取字符串
* @name :truncate_words
* @author :lyh
* @method :post
... ...
... ... @@ -20,14 +20,83 @@ use Illuminate\Support\Facades\Cache;
*/
class BaseController extends Controller
{
public $param;
public $request;
protected $param = [];//所有请求参数
protected $token = ''; //token
protected $request = [];//助手函数
protected $page = 1;//当前页
protected $row = 20;//每页条数
protected $header = [];//设置请求头参数
protected $order = 'created_at';
protected $order_type = 'desc';
protected $map = [];//处理后的参数
public function __construct(Request $request)
{
$this->request = $request;
$this->param = $this->request->all();
$this->getParam();
}
/**
* @remark :请求参数处理
* @name :getParam
* @author :lyh
* @method :post
* @time :2023/6/17 16:34
*/
public function getParam(){
foreach ($this->param as $k => $v){
if(is_array($v)){
$this->map[$k] = $v;
}else{
$this->getMap($k,$v);
}
}
}
/**
* @remark :搜索参数处理
* @name :getMap
* @author :lyh
* @method :post
* @time :2023/8/28 10:22
*/
public function getMap($k,$v){
switch ($k){
case "order":
$this->order = $v;
break;
case "order_type":
$this->order_type = $v;
break;
case 'page':
$this->page = $v;
break;
case 'row':
case 'size':
$this->row = $v;
break;
case "name":
$this->map['name'] = ['like','%'.$v.'%'];
break;
case "start_at":
$this->_btw[0] = $v;
$this->_btw[1] = date('Y-m-d H:i:s',time());
$this->map['created_at'] = ['between', $this->_btw];
break;
case "end_at":
$this->_btw[1] = $v;
$this->map['created_at'] = ['between', $this->_btw];
break;
default:
if (!empty($v) || $v == 0) {
$this->map[$k] = $v;
}
break;
}
}
/**
* @param array $data
* @param string $message
... ...
<?php
/**
* @remark :
* @name :TicketUploadDataController.php
* @author :lyh
* @method :post
* @time :2025/9/25 09:40
*/
namespace App\Http\Controllers\Api\WorkOrder;
use App\Enums\Common\Code;
use App\Http\Controllers\Api\BaseController;
use App\Models\Blog\BlogCategory;
use App\Models\News\NewsCategory;
use App\Models\Product\Category;
use App\Models\Product\Keyword;
use App\Models\Ticket\TicketUploadData;
use App\Services\ProjectServer;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
/**
* @remark :上传产品/博客/新闻模块
* @name :TicketUploadDataController
* @author :lyh
* @method :post
* @time :2025/9/25 09:40
*/
class TicketUploadDataController extends BaseController
{
public function __construct(Request $request)
{
parent::__construct($request);
$this->model = new TicketUploadData();
}
/**
* @remark :已提交列表
* @name :lists
* @author :lyh
* @method :post
* @time :2025/9/25 10:28
*/
public function lists()
{
$this->request->validate([
'project_id' => 'required',
], [
'project_id.required' => 'project_id不能为空',
]);
$data = $this->model->lists($this->map, $this->page, $this->row, $this->order);
ProjectServer::useProject($this->map['project_id']);
if(!empty($data) && !empty($data['list'])){
foreach ($data['list'] as &$item) {
$item = $this->getHandleFileImage($item);
$item['text']['cate_name'] = $this->cateText($item['type'],$item['text']['category_id'] ?? []);
}
}
DB::disconnect('custom_mysql');
$this->response('success', Code::SUCCESS, $data);
}
/**
* @remark :处理数据
* @name :getHandleFileImage
* @author :lyh
* @method :post
* @time :2025/9/25 16:53
*/
public function getHandleFileImage($v){
if($v['type'] == 1){
if(!empty($v['text']['image'])){
foreach ($v['text']['image'] as $gallery_k => $gallery_v){
$gallery_v['url'] = getImageUrl($gallery_v['url']);
$v['text']['image'][$gallery_k] = $gallery_v;
}
}
}else{
if(isset($v['text']['image']) && !empty($v['text']['image'])){
$v['text']['image'] = getImageUrl($v['text']['image']);
}
}
return $v;
}
/**
* @remark :获取分类名称
* @name :cateText
* @author :lyh
* @method :post
* @time :2025/9/29 17:18
*/
public function cateText($type,$category_id,$keyword_id = [],$is_array = false)
{
if(empty($category_id)){
return '';
}else{
$filed = 'name';
if($type == 1){
$cateModel = new Category();
$filed = 'title';
}elseif ($type == 2){
$cateModel = new BlogCategory();
}else{
$cateModel = new NewsCategory();
}
if($is_array){
$cate_arr = $cateModel->whereIn('id', (array)$category_id)
->pluck($filed, 'id')
->toArray();
if($type == 1){
$keywodModel = new KeyWord();
$keywod_arr = $keywodModel->whereIn('id', (array)$keyword_id)
->pluck($filed, 'id')
->toArray();
return ['keywod_arr' => $keywod_arr, 'cate_arr' => $cate_arr];
}
return ['cate_arr' => $cate_arr];
}else{
$cateArr = $cateModel->selectField(['id'=>['in',$category_id]],$filed);
return implode(',',$cateArr);
}
}
}
/**
* @remark :获取数据详情
* @name :info
* @author :lyh
* @method :post
* @time :2025/9/25 10:35
*/
public function info()
{
$this->request->validate([
'id' => 'required',
], [
'id.required' => 'id不能为空',
]);
$info = $this->model->read($this->param);
if($info === false){
$this->response('当前数据不存在或已被删除',Code::SYSTEM_ERROR);
}
ProjectServer::useProject($info['project_id']);
$info['text']['cate_name'] = $this->cateText($info['type'],$info['text']['category_id'] ?? [],$info['text']['keyword_id'] ?? [],true);
$info = $this->getHandleFileImage($info);
DB::disconnect('custom_mysql');
$this->response('success', Code::SUCCESS, $info);
}
/**
* @remark :提交数据
* @name :save
* @author :lyh
* @method :post
* @time :2025/9/25 09:48
*/
public function save()
{
$this->request->validate([
'project_id' => 'required',
'type' => 'required',
'text' => 'required'
], [
'project_id.required' => 'project_id不能为空',
'type.required' => '上传类型不能为空',
'text' => '数据详情不为空'
]);
//验证当前数据是否已提交
$this->param['text'] = json_encode($this->param['text'], true);
if(isset($this->param['id']) && !empty($this->param['id'])){
//执行编辑
$info = $this->model->read(['id'=>$this->param['id']]);
if($info['status'] == 0){
$this->model->edit($this->param,['id'=>$this->param['id']]);
}else{
$this->response('当前状态不允许编辑', Code::SYSTEM_ERROR);
}
$this->response('success');
}else{
$info = $this->model->read(['project_id' => $this->param['project_id'], 'type' => $this->param['type'], 'text' => $this->param['text'], 'status' => 0]);
if ($info === false) {
$id = $this->model->addReturnId($this->param);
} else {
$id = $info['id'];
}
$data = ['id' => $id];
$this->response('success', Code::SUCCESS, $data);
}
}
/**
* @remark :根据项目获取分类
* @name :getProductCate
* @author :lyh
* @method :post
* @time :2025/9/25 15:41
*/
public function getProductCate()
{
$this->request->validate([
'project_id' => 'required',
'type' => 'required',
'search' => 'required'
], [
'project_id.required' => 'project_id不能为空',
'type.required' => 'type不能为空',
'search.required' => '搜索参数不能为空',
]);
ProjectServer::useProject($this->param['project_id']);
if ($this->param['type'] == 1) {
//todo::搜索获取分类
$productCateModel = new Category();
$data = $productCateModel->lists(['title' => ['like','%' . $this->param['search'] . '%']], 1, 20,'id',['id','title as name']);
} else {
$keywordModel = new Keyword();
$data = $keywordModel->lists(['title' => ['like','%' . $this->param['search'] . '%']], 1, 20,'id',['id','title as name']);
}
DB::disconnect('custom_mysql');
$this->response('success', Code::SUCCESS, $data);
}
/**
* @remark :获取博客分类
* @name :getBlogCate
* @author :lyh
* @method :post
* @time :2025/9/25 15:42
*/
public function getBlogCate()
{
$this->request->validate([
'project_id' => 'required',
'search' => 'required'
], [
'project_id.required' => 'project_id不能为空',
'search.required' => '搜索参数不能为空',
]);
ProjectServer::useProject($this->param['project_id']);
$blogCateModel = new BlogCategory();
$data = $blogCateModel->lists(['name' => ['like' ,'%' . $this->param['search'] . '%']], 1, 20,'id',['id','name']);
DB::disconnect('custom_mysql');
$this->response('success', Code::SUCCESS, $data);
}
/**
* @remark :获取新闻分类
* @name :getNewsCate
* @author :lyh
* @method :post
* @time :2025/9/25 15:43
*/
public function getNewsCate()
{
$this->request->validate([
'project_id' => 'required',
'search' => 'required'
], [
'project_id.required' => 'project_id不能为空',
'search.required' => '搜索参数不能为空',
]);
ProjectServer::useProject($this->param['project_id']);
$newsCateModel = new NewsCategory();
$data = $newsCateModel->lists(['name' => ['like' , '%' . $this->param['search'] . '%']], 1, 20,'id',['id','name']);
DB::disconnect('custom_mysql');
$this->response('success', Code::SUCCESS, $data);
}
}
... ...
... ... @@ -789,6 +789,8 @@ class ProjectController extends BaseController
$company = $this->param['company'] ?? '';
$order_by_field = $request->input('order_by_field', 'id');
$order_by_sort = $request->input('order_by_sort', 'desc');
$start_time = $this->param['start_time'] ?? '';
$end_time = $this->param['end_time'] ?? '';
if(!$source_id && !$id){
$this->response('参数异常',Code::SYSTEM_ERROR);
... ... @@ -815,7 +817,7 @@ class ProjectController extends BaseController
$data = Project::with(['deploy_build', 'deploy_optimize', 'online_check'])
->where('delete_status', 0)
->where(function ($query) use ($channel_id, $type, $company, $id, $notice_order_id){
->where(function ($query) use ($channel_id, $type, $company, $id, $notice_order_id, $start_time, $end_time){
if ($channel_id) {
$query->where('channel->channel_id', $channel_id);
}
... ... @@ -831,6 +833,9 @@ class ProjectController extends BaseController
if ($notice_order_id) {
$query->whereIn('notice_order_id', $notice_order_id);
}
if ($start_time && $end_time ) {
$query->whereBetween('uptime', [$start_time, $end_time]);
}
})->orderBy($order_by_field, $order_by_sort)->paginate($size)->toArray();
$list = [];
foreach ($data['list'] as $item){
... ...
... ... @@ -65,17 +65,64 @@ class AdsController extends BaseController
->orderBy('id', 'desc')
->paginate($page_size)
->toArray();
$ids = array_column($result['list'], 'id');
$ad_ids = [];
foreach (array_column($result['list'], 'ad_id') as $ad_id){
foreach (explode(',', $ad_id) as $item){
$ad_ids[] = $item;
}
}
$requiry_nums = ReInquiryDetail::select('task_id', DB::raw('COUNT(*) as count'))
->whereIn('task_id', $ids)->where('status', ReInquiryDetail::STATUS_SUCCESS)
->groupBy('task_id')->pluck('count', 'task_id')->toArray();
$form_nums = ReInquiryForm::select('ad_id', DB::raw('COUNT(*) as count'))
->whereIn('ad_id', $ad_ids)->groupBy('ad_id')->pluck('count', 'ad_id')->toArray();
$relay_site_total = 0;
$fb_projects = ReInquiryCount::getFobProjects();
$sites = ReInquiryTask::select('target', 'shop_site', 'fob_pro')->get()->toArray();
$targets = $shop_sites = $fob_pros = [];
foreach ($sites as $site){
foreach ($site['target'] as $v){
if(isset($targets[$v['url']])){
$targets[$v['url']] = $targets[$v['url']] + 1;
}else{
$targets[$v['url']] = 1;
}
}
foreach ($site['shop_site'] as $v){
if(isset($shop_sites[$v])){
$shop_sites[$v] = $shop_sites[$v] + 1;
}else{
$shop_sites[$v] = 1;
}
}
foreach ($site['fob_pro'] as $v){
if(isset($fob_pros[$v])){
$fob_pros[$v] = $fob_pros[$v] + 1;
}else{
$fob_pros[$v] = 1;
}
}
}
foreach ($result['list'] as &$item){
$relay_site_total += count($item['target']);
$item['requiry_num'] = ReInquiryDetail::where('task_id', $item['id'])->where('status', ReInquiryDetail::STATUS_SUCCESS)->count();
$item['form_num'] = ReInquiryForm::whereIn('ad_id', explode(',', $item['ad_id']))->count();
// $item['requiry_num'] = ReInquiryDetail::where('task_id', $item['id'])->where('status', ReInquiryDetail::STATUS_SUCCESS)->count();
// $item['form_num'] = ReInquiryForm::whereIn('ad_id', explode(',', $item['ad_id']))->count();
$item['requiry_num'] = $requiry_nums[$item['id']] ?? 0;
$item['form_num'] = 0;
foreach (explode(',', $item['ad_id']) as $v){
$item['form_num'] += $form_nums[$v] ?? 0;
}
//关联网站是否有重复的
if($item['fob_pro']){
$fb_projects = ReInquiryCount::getFobProjects();
foreach ($item['fob_pro'] as $k => $fob_pro){
$repeat = ReInquiryTask::where('fob_pro', 'like', '%"'.$fob_pro.'"%')->where('id', '<>', $item['id'])->first();
$repeat = $fob_pros[$fob_pro] > 1;
$fob_info = collect($fb_projects)->where('postid', $fob_pro)->first();
$item['fob_pro_list'][$k] = [
'is_repeat' => $repeat ? 1 : 0,
... ... @@ -85,7 +132,7 @@ class AdsController extends BaseController
}
if($item['shop_site']) {
foreach ($item['shop_site'] as $k => $site) {
$repeat = ReInquiryTask::where('target', 'like', '%"' . $site . '"%')->where('id', '<>', $item['id'])->first();
$repeat = $shop_sites[$site] > 1;
$item['shop_site_list'][$k] = [
'is_repeat' => $repeat ? 1 : 0,
'url' => $site,
... ... @@ -93,7 +140,7 @@ class AdsController extends BaseController
}
}
foreach ($item['target'] as $k=>$target){
$repeat = ReInquiryTask::where('target', 'like', '%"'.$target['url'].'"%')->where('id', '<>', $item['id'])->first();
$repeat = $targets[$target['url']] > 1;
$item['target'][$k]['is_repeat'] = $repeat ? 1 : 0;
$item['target'][$k]['is_ad_fee'] = 0;
if($item['target'][$k]['is_v6']){
... ... @@ -112,6 +159,15 @@ class AdsController extends BaseController
}
$result['relay_site_total'] = $relay_site_total;
$result['default_ai_param'] = ReInquiryConfig::getDefaultConfigCache(ReInquiryConfig::TYPE_AI_PARAM);
$result['frequency_map'] = [
'1' => '一天一封询盘',
'2' => '两天一封询盘',
'3' => '三天一封询盘',
'4' => '四天一封询盘',
'5' => '五天一封询盘',
'6' => '六天一封询盘',
'0' => '不限制',
];
return $this->response('success', Code::SUCCESS, $result);
}
... ... @@ -134,6 +190,7 @@ class AdsController extends BaseController
$status = intval($request->input('status'));
$is_replace_text = intval($request->input('is_replace_text'));
$ai_param = $request->input('ai_param');
$second_push_rate = $request->input('second_push_rate');
if (empty($title) || empty($ad_id))
return $this->response('请填写完整信息!', Code::USER_ERROR, []);
... ... @@ -152,7 +209,7 @@ class AdsController extends BaseController
return $this->response('英文缩写参考不能为空!', Code::USER_ERROR, []);
}
}
$task = ReInquiryTask::createTask($id, $title, $industry, $ad_id, $ad_url, $ad_img, $num, $status, $is_replace_text, $ai_param, $is_show_fb_source);
$task = ReInquiryTask::createTask($id, $title, $industry, $ad_id, $ad_url, $ad_img, $num, $status, $is_replace_text, $ai_param, $is_show_fb_source, $second_push_rate);
//是否显示FB标识
foreach ($task['target'] as $target){
... ...
<?php
/**
* @remark :
* @name :TicketUploadDataController.php
* @author :lyh
* @method :post
* @time :2025/9/25 14:00
*/
namespace App\Http\Controllers\Aside\Ticket;
use App\Enums\Common\Code;
use App\Http\Controllers\Aside\BaseController;
use App\Http\Logic\Aside\Ticket\TicketUploadDataLogic;
use Illuminate\Http\Request;
/**
* @remark :工单上传列表审核功能
* @name :TicketUploadDataController
* @author :lyh
* @method :post
* @time :2025/9/25 14:01
*/
class TicketUploadDataController extends BaseController
{
public function __construct(Request $request)
{
parent::__construct($request);
$this->logic = new TicketUploadDataLogic();
}
/**
* @remark :获取审核列表
* @name :lists
* @author :lyh
* @method :post
* @time :2025/9/25 14:02
*/
public function lists(){
$this->request->validate([
'project_id'=>'required'
],[
'project_id.required' => 'project_id不能为空',
]);
if(isset($this->map['text']) && !empty($this->map['text'])){
$this->map['text'] = ['like','%'.$this->map['text'].'%'];
}
$data = $this->logic->getDataList($this->map,$this->page,$this->row,$this->order);
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :获取数据详情
* @name :detail
* @author :lyh
* @method :post
* @time :2025/9/26 09:29
*/
public function detail(){
$this->request->validate([
'id'=>'required'
],[
'id.required' => '主键ID不能为空',
]);
$data = $this->logic->getDetail();
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :人工审核
* @name :save
* @author :lyh
* @method :post
* @time :2025/9/25 14:14
*/
public function save()
{
$this->request->validate([
'status'=>'required',
'id'=>'required'
],[
'status.required' => '提交状态不能为空',
'id.required' => '主键ID不能为空',
]);
$data = $this->logic->saveData();
$this->response('success',Code::SUCCESS,$data);
}
}
... ...
... ... @@ -82,8 +82,8 @@ class AiBlogController extends BaseController
* @method :post
* @time :2023/7/5 14:33
*/
public function save(AiBlogLogic $aiBlogLogic){
// $aiBlogRequest->validated();
public function save(AiBlogRequest $aiBlogRequest,AiBlogLogic $aiBlogLogic){
$aiBlogRequest->validated();
$aiBlogLogic->blogSave();
$this->response('success');
}
... ...
... ... @@ -218,14 +218,8 @@ class BlogController extends BaseController
public function edit_seo(BlogLogic $blogLogic){
$this->request->validate([
'id'=>['required'],
'seo_title'=>['required'],
'seo_description'=>['required'],
'seo_keywords'=>['required'],
],[
'id.required' => 'ID不能为空',
'seo_title.required' => 'seo_title不能为空',
'seo_description.required' => 'seo_description不能为空',
'seo_keywords.required' => 'seo_description不能为空',
]);
$blogLogic->edit_seo();
$this->response('success');
... ...
... ... @@ -198,13 +198,19 @@ class CustomModuleContentController extends BaseController
*/
public function save(CustomModuleContentLogic $logic){
$this->request->validate([
'name'=>['required'],
'name'=>['required','max:200'],
'route'=>['required'],
'module_id'=>['required']
'module_id'=>['required'],
// 'seo_title'=>['max:70'],
'seo_keywords'=>['max:300'],
'seo_description'=>['max:200'],
],[
'name.required' => '分类名称不能为空',
'route.required' => '分类路由不能为空',
'module_id.required' => '所选模块id不能为空'
'module_id.required' => '所选模块id不能为空',
// 'seo_title.max' => 'SEO标题不能超过70个字符',
'seo_keywords.max' => 'SEO关键词不能超过300个字符',
'seo_description.max' => 'SEO描述不能超过200个字符',
]);
$data = $logic->contentSave();
$this->response('success',Code::SUCCESS,$data);
... ...
... ... @@ -211,14 +211,8 @@ class NewsController extends BaseController
public function edit_seo(NewsLogic $newsLogic){
$this->request->validate([
'id'=>['required'],
'seo_title'=>['required'],
'seo_description'=>['required'],
'seo_keywords'=>['required'],
],[
'id.required' => 'ID不能为空',
'seo_title.required' => 'seo_title不能为空',
'seo_description.required' => 'seo_description不能为空',
'seo_keywords.required' => 'seo_description不能为空',
]);
$newsLogic->edit_seo();
$this->response('success');
... ...
... ... @@ -155,8 +155,8 @@ class RankDataController extends BaseController
'cnt_first' => '排名第一',
'cnt_home' => '第一页',
'cnt_thirty' => '前三页',
'cnt_fifty' => '前五页',
'cnt_hundred' => '前十页',
// 'cnt_fifty' => '前五页',
// 'cnt_hundred' => '前十页',
'reach' => '是否达标',
];
}
... ...
<?php
/**
* @remark :
* @name :TicketUploadDataLogic.php
* @author :lyh
* @method :post
* @time :2025/9/25 14:03
*/
namespace App\Http\Logic\Aside\Ticket;
use App\Helper\Arr;
use App\Http\Logic\Aside\BaseLogic;
use App\Models\Blog\Blog;
use App\Models\Blog\BlogCategory;
use App\Models\News\News;
use App\Models\News\NewsCategory;
use App\Models\Product\Category;
use App\Models\Product\CategoryRelated;
use App\Models\Product\Keyword;
use App\Models\Product\KeywordRelated;
use App\Models\Product\Product;
use App\Models\RouteMap\RouteMap;
use App\Models\Ticket\TicketUploadData;
use App\Services\ProjectServer;
use Illuminate\Support\Facades\DB;
class TicketUploadDataLogic extends BaseLogic
{
public function __construct()
{
parent::__construct();
$this->param = $this->requestAll;
$this->model = new TicketUploadData();
}
/**
* @remark :获取审核列表
* @name :getDataList
* @author :lyh
* @method :post
* @time :2025/9/25 14:17
*/
public function getDataList($map = [],$page = 1,$row = 20,$order = 'id'){
if(isset($this->map['text']) && !empty($this->map['text'])){
$this->map['text'] = ['like','%'.$this->map['text'].'%'];
}
ProjectServer::useProject($map['project_id']);
$data = $this->model->lists($map,$page,$row,$order);
if(!empty($data) && !empty($data['list'])){
foreach ($data['list'] as &$v){
$v = $this->getHandleFileImage($v);
$v['text']['cate_name'] = $this->cateText($v['type'],$v['text']['category_id'] ?? []);
}
}
DB::disconnect('custom_mysql');
return $this->success($data);
}
/**
* @remark :处理数据
* @name :getHandleFileImage
* @author :lyh
* @method :post
* @time :2025/9/25 16:53
*/
public function getHandleFileImage($v){
if($v['type'] == 1){
if(!empty($v['text']['image'])){
foreach ($v['text']['image'] as $gallery_k => $gallery_v){
$gallery_v['url'] = getImageUrl($gallery_v['url']);
$v['text']['image'][$gallery_k] = $gallery_v;
}
}
}else{
if(isset($v['text']['image']) && !empty($v['text']['image'])){
$v['text']['image'] = getImageUrl($v['text']['image']);
}
}
return $this->success($v);
}
/**
* @remark :获取分类名称
* @name :cateText
* @author :lyh
* @method :post
* @time :2025/9/29 17:18
*/
public function cateText($type,$category_id = [],$keyword_id = [],$is_array = false)
{
if(empty($category_id)){
return '';
}else{
$filed = 'name';
if($type == 1){
$cateModel = new Category();
$keywodModel = new KeyWord();
$filed = 'title';
}elseif ($type == 2){
$cateModel = new BlogCategory();
}else{
$cateModel = new NewsCategory();
}
if($is_array){
$cate_arr = $cateModel->whereIn('id', (array)$category_id)
->pluck($filed, 'id')
->toArray();
if($type == 1){
$keywod_arr = $keywodModel->whereIn('id', (array)$keyword_id)
->pluck($filed, 'id')
->toArray();
return ['keywod_arr' => $keywod_arr, 'cate_arr' => $cate_arr];
}
return ['cate_arr' => $cate_arr];
}else{
$cateArr = $cateModel->selectField(['id'=>['in',$category_id]],$filed);
return implode(',',$cateArr);
}
}
}
/**
* @remark :获取当前数据详情
* @name :getDetail
* @author :lyh
* @method :post
* @time :2025/9/26 09:31
*/
public function getDetail(){
$info = $this->model->read(['id'=>$this->param['id']]);
if($info === false){
$this->fail('当前数据不存在或已被删除');
}
ProjectServer::useProject($info['project_id']);
$info['text']['cate_name'] = $this->cateText($info['type'],$info['text']['category_id'] ?? [],$info['text']['keyword_id'] ?? [],true);
$info = $this->getHandleFileImage($info);
DB::disconnect('custom_mysql');
return $this->success($info);
}
/**
* @remark :保存数据
* @name :saveData
* @author :lyh
* @method :post
* @time :2025/9/25 17:01
*/
public function saveData()
{
//获取当前数据详情
$info = $this->model->read(['id'=>$this->param['id']]);
if($info === false){
$this->fail('当前数据不存在或已被删除');
}
//审核成功执行
if($this->param['status'] == 1){
ProjectServer::useProject($info['project_id']);
if($info['type'] == 1){
$this->saveProductData($info);
}elseif ($info['type'] == 2){
$this->saveBlogData($info);
}else{
$this->saveNewsData($info);
}
DB::disconnect('custom_mysql');
}
$data = $this->model->edit(['status'=>$this->param['status'],'operator_id'=>$this->manager['id'],'remark'=>$this->param['remark'] ?? ''],['id'=>$this->param['id']]);
return $this->success($data);
}
/**
* @remark :保存数据详情
* @name :saveData
* @author :lyh
* @method :post
* @time :2025/9/25 14:17
*/
public function saveProductData($info){
if(isset($info['text']['keyword_id']) && !empty($info['text']['keyword_id'])){
$keyword_id = ','.Arr::arrToSet($info['text']['keyword_id']).',';
}
if(isset($info['text']['category_id']) && !empty($info['text']['category_id'])) {
$category_id = ','.Arr::arrToSet($info['text']['category_id']).',';
}
if(isset($info['text']['image']) && !empty($info['text']['image'])){
foreach ($info['text']['image'] as $k => $v){
$v['url'] = str_replace_url($v['url']);
$info['text']['image'][$k] = $v;
}
$thumb = Arr::a2s($info['text']['image'][0] ?? []);
$info['text']['image'] = Arr::a2s($info['text']['image'] ?? []);
}else{
$thumb = $info['text']['image'] = Arr::a2s([]);
}
try {
$productModel = new Product();
$data = [
'project_id' => $info['project_id'],
'title' => $info['text']['title'],
'thumb'=>$thumb,
'gallery'=>$info['text']['image'] ?? [],
'intro'=>$info['text']['remark'],
'category_id'=>$category_id ?? '',
'keyword_id'=>$keyword_id ?? '',
'status'=>0,
];
$id = $productModel->addReturnId($data);
CategoryRelated::saveRelated($id, $info['text']['category_id'] ?? []);//分类关联
KeywordRelated::saveRelated($id,$info['text']['keyword_id'] ?? []);//关键字关联
$route = RouteMap::setRoute($data['title'],RouteMap::SOURCE_PRODUCT,$id,$info['project_id']);
$this->model->edit(['route'=>$route],['id'=>$id]);
}catch (\Exception $e){
$this->fail('保存失败,请联系管理员');
}
return $this->success();
}
/**
* @remark :保存blog数据
* @name :saveBlogData
* @author :lyh
* @method :post
* @time :2025/9/25 16:26
*/
public function saveBlogData($info)
{
if(isset($info['text']['category_id']) && !empty($info['text']['category_id'])) {
$category_id = ','.Arr::arrToSet($info['text']['category_id']).',';
}
if(isset($info['text']['image'])){
$info['text']['image'] = str_replace_url($info['text']['image'] ?? '');
}
$data = [
'project_id' => $info['project_id'],
'name' => $info['text']['title'],
'image'=>$info['text']['image'],
'text'=>$info['text']['remark'],
'category_id'=>$category_id ?? '',
'status'=>0,
];
try {
$blogModel = new Blog();
$id = $blogModel->addReturnId($data);
$route = RouteMap::setRoute($data['name'],RouteMap::SOURCE_BLOG,$id,$info['project_id']);
$this->model->edit(['url'=>$route],['id'=>$id]);
}catch (\Exception $e){
$this->fail('保存失败,请联系管理员');
}
return $this->success();
}
/**
* @remark :保存新闻数据
* @name :saveNewsData
* @author :lyh
* @method :post
* @time :2025/9/25 16:34
*/
public function saveNewsData($info)
{
if(isset($info['text']['category_id']) && !empty($info['text']['category_id'])) {
$category_id = ','.Arr::arrToSet($info['text']['category_id']).',';
}
if(isset($info['text']['image'])){
$info['text']['image'] = str_replace_url($info['text']['image'] ?? '');
}
$data = [
'project_id' => $info['project_id'],
'name' => $info['text']['title'],
'image'=>$info['text']['image'],
'text'=>$info['text']['remark'],
'category_id'=>$category_id ?? '',
'status'=>0,
];
try {
$newsModel = new News();
$id = $newsModel->addReturnId($data);
$route = RouteMap::setRoute($data['name'],RouteMap::SOURCE_NEWS,$id,$info['project_id']);
$this->model->edit(['route'=>$route],['id'=>$id]);
}catch (\Exception $e){
$this->fail('保存失败,请联系管理员');
}
return $this->success();
}
}
... ...
... ... @@ -58,6 +58,9 @@ class AiBlogLogic extends BaseLogic
if(!empty($this->param['image'])){
$this->param['image'] = str_replace_url($this->param['image']);
}
if(!isset($this->param['seo_title']) || empty($this->param['seo_title'])){
$this->param['seo_title'] = truncate_text($this->param['new_title'],70);
}
$this->param['route'] = RouteMap::setRoute($this->param['route'], RouteMap::SOURCE_AI_BLOG, $this->param['id'], $this->user['project_id']);
$anchor = $this->param['anchor'] ?? [];
$this->param['anchor'] = json_encode($anchor,true);
... ... @@ -153,7 +156,7 @@ class AiBlogLogic extends BaseLogic
//删除路由映射
RouteMap::delRoute(RouteMap::SOURCE_AI_BLOG, $id, $this->user['project_id']);
$this->model->del(['id'=>$id]);
$this->curlDelRoute(['old_route'=>$info['route']]);
$this->curlDelRoute(['old_route'=>$info['route'],'path'=>'blog']);
}
Artisan::call('save_ai_blog_list', ['project_id' => $this->user['project_id']]);
}catch (\Exception $e){
... ...
... ... @@ -91,6 +91,7 @@ class AiVideoLogic extends BaseLogic
//删除路由映射
RouteMap::delRoute(RouteMap::SOURCE_AI_VIDEO, $id, $this->user['project_id']);
$this->model->del(['id'=>$id]);
$this->curlDelRoute(['old_route'=>$info['route'],'path'=>'video']);
}
}catch (\Exception $e){
$this->fail('删除失败,请联系管理员');
... ...
... ... @@ -30,6 +30,9 @@ class BlogCategoryLogic extends BaseLogic
public function categorySave(){
//验证名称是否存在
$this->verifyParamName($this->param['name']);
if(!isset($this->param['seo_title']) || empty($this->param['seo_title'])){
$this->param['seo_title'] = truncate_text($this->param['name'],70);
}
DB::beginTransaction();
try {
if(isset($this->param['id']) && !empty($this->param['id'])){
... ...
... ... @@ -201,6 +201,9 @@ class BlogLogic extends BaseLogic
$this->fail('发布时间需大于当天');
}
}
if(!isset($param['seo_title']) || empty($param['seo_title'])){
$param['seo_title'] = truncate_text($param['name'],70);
}
return $this->success($param);
}
... ...
... ... @@ -234,6 +234,9 @@ class CustomModuleContentLogic extends BaseLogic
$param['video']['video_image'] = str_replace_url($param['video']['video_image']);
$param['video'] = Arr::a2s($param['video'] ?? []);
}
if(!isset($param['seo_title']) || empty($param['seo_title'])){
$param['seo_title'] = truncate_text($param['name'],70);
}
return $this->success($param);
}
... ...
... ... @@ -49,6 +49,7 @@ class GeoQuestionResLogic extends BaseLogic
public function getResultList($map = [],$page = 1,$row = 20,$order = 'created_at',$sort = 'desc'){
unset($map['sort']);
$map['project_id'] = $this->user['project_id'];
$map['hit'] = ['!=',0];
$filed = ['id','project_id','question_id','platform','is_match','question','en_question','keywords','url','label','cosine','created_at','updated_at'];
if(!empty($map['created_at'])){
$map['created_at'] = ['between',[$map['created_at'].' 00:00:00',$map['created_at'].' 23:59:59']];
... ...
... ... @@ -48,7 +48,7 @@ class CountLogic extends BaseLogic
$domain = parse_url($this->user['domain'], PHP_URL_HOST); // 直接取域名部分
$inquiry_list = (new FormGlobalsoApi())->getInquiryAll($domain,$this->user['is_upgrade']);
if($inquiry_list !== false){
if($inquiry_list['status'] != 400){
if(isset($inquiry_list['status']) && $inquiry_list['status'] != 400){
$info['inquiry_num'] = $inquiry_list['data']['count'];
Cache::add('inquiry_num_'.$this->user['project_id'],$inquiry_list['data']['count'],3600);
}
... ...
... ... @@ -49,6 +49,9 @@ class NewsCategoryLogic extends BaseLogic
if(isset($param['image']) && !empty($param['image'])){
$param['image'] = str_replace_url($param['image']);
}
if(!isset($param['seo_title']) || empty($param['seo_title'])){
$param['seo_title'] = truncate_text($param['name'],70);
}
return $this->success($param);
}
/**
... ...
... ... @@ -225,6 +225,9 @@ class NewsLogic extends BaseLogic
if(isset($param['related_product_id'])){
$param['related_product_id'] = implode(',',$param['related_product_id']);
}
if(!isset($param['seo_title']) || empty($param['seo_title'])){
$param['seo_title'] = truncate_text($param['name'],70);
}
return $this->success($param);
}
... ...
... ... @@ -157,6 +157,9 @@ class CategoryLogic extends BaseLogic
}else{
$param['cate_tak'] = json_encode([]);;
}
if(!isset($param['seo_title']) || empty($param['seo_title'])){
$param['seo_title'] = truncate_text($param['title'],70);
}
return $this->success($param);
}
... ...
... ... @@ -123,6 +123,8 @@ class KeywordLogic extends BaseLogic
}
if(!empty($param['seo_title'])){
$param['seo_title'] = ucfirst($param['seo_title']);
}else{
$param['seo_title'] = truncate_text($param['title'],70);
}
$param['first_word'] = $this->model->first_word($param['title']);
return $param;
... ...
... ... @@ -44,6 +44,9 @@ class ProductLogic extends BaseLogic
if(isset($this->param['id']) && !empty($this->param['id'])){
$data = $this->editProduct();
}else{
if(!isset($this->param['seo_title']) || empty($this->param['seo_title'])){
$this->param['seo_title'] = $this->param['title'];
}
$data = $this->addProduct();
}
CategoryRelated::saveRelated($data['id'], $this->param['category_id'] ?? []);//分类关联
... ... @@ -389,6 +392,9 @@ class ProductLogic extends BaseLogic
$param['attr_id'] = Arr::arrToSet($param['attr_id'] ?? '');
$param['describe'] = Arr::a2s($param['describe'] ?? []);
$param['describe_id'] = Arr::arrToSet($param['describe_id'] ?? '');
if(!isset($param['seo_mate']['seo_title']) || empty($param['seo_mate']['seo_title'])){
$param['seo_mate']['seo_title'] = truncate_text($param['title'],70);
}
$param['seo_mate'] = Arr::a2s($param['seo_mate'] ?? []);
$param['related_product_id'] = Arr::arrToSet($param['related_product_id'] ?? '');
if(isset($param['icon'])){
... ...
... ... @@ -554,8 +554,8 @@ class RankDataLogic extends BaseLogic
$without_project_ids = []; //不用处理排名的项目
$without_extension_project_ids = [658]; //是否达标只统计主词的
$extension_project_ids = [354]; //扩展词也到达标的
$compliance_project_ids = [2163,257,823,1750,497]; //直接达标处理的
$ceaseProjectId = [354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250,2193,2399,1685, 3931];//暂停的项目
$compliance_project_ids = [2163,257,823,1750,497,1006]; //直接达标处理的
$ceaseProjectId = [354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250,2193,2399,1685, 3931,2273,3647];//暂停的项目
$uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目
//一个项目多个api_no
$multiple_api_no_project_ids = [
... ...
... ... @@ -25,6 +25,9 @@ class AiBlogRequest extends FormRequest
{
return [
'new_title'=>'required',
// 'seo_title'=>'max:70',
'seo_keywords'=>'max:300',
'seo_description'=>'max:200',
];
}
... ... @@ -32,6 +35,9 @@ class AiBlogRequest extends FormRequest
{
return [
'new_title.required' => '新标题不能为空',
// 'seo_title.max' => 'SEO标题不能超过70个字符',
'seo_keywords.max' => 'SEO关键词不能超过300个字符',
'seo_description.max' => 'SEO描述不能超过200个字符',
];
}
}
... ...
... ... @@ -24,7 +24,10 @@ class BlogCategoryRequest extends FormRequest
public function rules()
{
return [
'name'=>'required|max:100',
'name'=>'required|max:200',
// 'seo_title'=>'max:70',
'seo_keywords'=>'max:300',
'seo_des'=>'max:200',
];
}
... ... @@ -32,7 +35,10 @@ class BlogCategoryRequest extends FormRequest
{
return [
'name.required'=>'请填写名称',
'name.max'=>'名称最大100字',
'name.max'=>'名称最大200字',
// 'seo_title.max' => 'SEO标题不能超过70个字符',
'seo_keywords.max' => 'SEO关键词不能超过300个字符',
'seo_des.max' => 'SEO描述不能超过200个字符',
];
}
}
... ...
... ... @@ -25,10 +25,11 @@ class BlogRequest extends FormRequest
{
return [
'name'=>'required|max:200',
'seo_keywords'=>'max:500',
'remark'=>'max:1000',
'url'=>'required',
// 'text'=>'max:5000',
// 'seo_title'=>'max:70',
'seo_keywords'=>'max:300',
'seo_description'=>'max:200',
];
}
... ... @@ -38,9 +39,10 @@ class BlogRequest extends FormRequest
'name.required'=>'请填写名称',
'name.max'=>'名称超过最长长度200',
'url.required'=>'链接不能为空',
'seo_keywords.max'=>'seo_keywords太长,请重新编辑',
// 'seo_title.max' => 'SEO标题不能超过70个字符',
'seo_keywords.max' => 'SEO关键词不能超过300个字符',
'seo_description.max' => 'SEO描述不能超过200个字符',
'remark.max'=>'描述超过最长长度1000',
// 'text.max'=>'详情内容超过最大长度',
];
}
}
... ...
... ... @@ -24,7 +24,10 @@ class NewsCategoryRequest extends FormRequest
public function rules()
{
return [
'name'=>'required|max:100',
'name'=>'required|max:200',
// 'seo_title'=>'max:70',
'seo_keywords'=>'max:300',
'seo_des'=>'max:200',
];
}
... ... @@ -33,6 +36,9 @@ class NewsCategoryRequest extends FormRequest
return [
'name.required'=>'请填写名称',
'name.max'=>'名称最大100字',
// 'seo_title.max' => 'SEO标题不能超过70个字符',
'seo_keywords.max' => 'SEO关键词不能超过300个字符',
'seo_des.max' => 'SEO描述不能超过200个字符',
];
}
}
... ...
... ... @@ -25,8 +25,10 @@ class NewsRequest extends FormRequest
{
return [
'name'=>'required|max:200',
// 'remark'=>'max:2000',
'url'=>'required',
// 'seo_title' => 'max:70',
'seo_keywords' => 'max:300',
'seo_description' => 'max:200',
];
}
... ... @@ -36,7 +38,9 @@ class NewsRequest extends FormRequest
'name.required'=>'请填写名称',
'name.max'=>'名称超过最长长度200',
'url.required'=>'链接不能为空',
// 'remark.max'=>'描述超过最长长度2000'
// 'seo_title.max' => 'SEO标题不能超过70个字符',
'seo_keywords.max' => 'SEO关键词不能超过300个字符',
'seo_description.max' => 'SEO描述不能超过200个字符',
];
}
}
... ...
... ... @@ -32,9 +32,8 @@ class CategoryRequest extends FormRequest
return [
'title'=>'required|max:200',
'route'=>'required',
// 'image'=>'required',
// 'keywords'=>'max:50',
// 'describe'=>'max:200',
'seo_keywords'=>'max:300',
'seo_des'=>'max:200',
];
}
... ... @@ -44,9 +43,8 @@ class CategoryRequest extends FormRequest
'title.required' => '请输入分类名称',
'title.max' => '分类名称不能超过200个字符',
'route.required' => '路由不能为空',
// 'image.required' => '请上传分类图片',
// 'keywords.max' => '分类关键词不能超过50个字符',
// 'describe.max' => '分类描述不能超过200个字符',
'seo_keywords.max' => 'SEO关键词不能超过300个字符',
'seo_des.max' => 'SEO描述不能超过200个字符',
];
}
... ...
... ... @@ -31,9 +31,9 @@ class KeywordRequest extends FormRequest
{
return [
'title'=>'required|max:200',
'seo_title'=>'max:255',
'seo_keywords'=>'max:500',
'seo_description'=>'max:500',
// 'seo_title'=>'max:70',
'seo_keywords'=>'max:300',
'seo_description'=>'max:200',
'related_news_ids'=>'array|max:2',
'related_blog_ids'=>'array|max:2',
];
... ... @@ -44,9 +44,9 @@ class KeywordRequest extends FormRequest
return [
'title.required' => '请输入关键词',
'title.max' => '关键词不能超过200个字符',
'seo_title.max' => 'SEO标题不能超过255个字符',
'seo_keywords.max' => 'SEO关键词不能超过500个字符',
'seo_description.max' => 'SEO描述不能超过500个字符',
// 'seo_title.max' => 'SEO标题不能超过70个字符',
'seo_keywords.max' => 'SEO关键词不能超过300个字符',
'seo_description.max' => 'SEO描述不能超过200个字符',
'related_news_ids.max' => '关联新闻不能超过两条',
'related_blog_ids.max' => '关联博客不能超过两条',
];
... ...
... ... @@ -38,6 +38,8 @@ class ProductRequest extends FormRequest
return [
'title' => 'required|max:200',
'route' => 'required|max:200',
'seo_mate.keywords' => 'max:300',
'seo_mate.description' => 'max:200',
'status' => ['required', Rule::in(array_keys(Product::statusMap()))],
];
}
... ... @@ -51,6 +53,9 @@ class ProductRequest extends FormRequest
'route.max' => '产品链接不能超过200个字符',
'status.required' => '请选择产品状态',
'status.in' => '产品状态值异常',
// 可选的 seo_mate 子字段的提示
'seo_mate.keywords.max' => 'SEO 关键字不能超过200个字符',
'seo_mate.description.max' => 'SEO 描述不能超过200个字符',
];
}
... ...
... ... @@ -2,6 +2,7 @@
namespace App\Models\Inquiry;
use App\Helper\Arr;
use App\Helper\FormGlobalsoApi;
use App\Models\Base;
use App\Utils\LogUtils;
... ... @@ -83,6 +84,12 @@ class InquiryFormData extends Base
$v = getImageUrl($v['path']);
$data[$k] = $v;
}
if(is_string($v)){
$arr = json_decode($v, true);
if(is_array($arr)){
$v = implode('', Arr::formatForHtml($arr));
}
}
//其他字段补充到message里
if(!in_array($k, ['name', 'email', 'message', 'phone', 'ip', 'date', 'cname', 'domain', 'edition', 'domain_host_url'])){
$data['message'].= "<br/>" . $k .': ' . $v;
... ... @@ -110,6 +117,34 @@ class InquiryFormData extends Base
return $model->id;
}
/**
* 特殊项目 邮件模版
* FIXME 后期有多个特殊项目,需要按照项目ID设置模板
* @param $name
* @param $email
* @param $phone
* @param $message
* @param $domain
* @param $country
* @return string
*/
public static function specialInquiryTemplate($name, $email, $phone, $message, $domain, $country)
{
$template = "
客户姓名:$name
客户邮箱:$email
客户电话:$phone
--------------------------------------------------------------------
询盘内容:
$message
--------------------------------------------------------------------
发送询盘网址: $domain
客户IP地址: [ip]
IP所在国家/地区: $country
--------------------------------------------------------------------";
return $template;
}
public function setDataAttribute($value)
{
$this->attributes['data'] = json_encode($value);
... ...
... ... @@ -9,6 +9,7 @@ use App\Models\Base;
use App\Models\Domain\DomainInfo;
use App\Models\Project\Project;
use App\Models\Task\TaskOwner;
use App\Services\DingService;
use App\Utils\HttpUtils;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
... ... @@ -68,6 +69,18 @@ class ReInquiryCount extends Base
$model->task_ids = $model->task_ids + [$task_id];
$model->num = $model->num + $num;
$model->save();
//数量首次达到100, 给钉钉推送消息
if($num > 0 && $model->num == 100){
(new DingService())->handle([
'keyword' => '询盘数量通知',
'msg' =>
'项目名称:' . $model->company . PHP_EOL .
'项目域名:' . $model->domain . PHP_EOL .
'询盘数量:' . $model->num,
'isAtAll' => false, // 是否@所有人
], 'https://oapi.dingtalk.com/robot/send?access_token=cd5733d3e6b810a501e3ea20df7c99ecb616aa6754fa048348837d088c1f5b2c');
}
}
public function setTaskIdsAttribute($value)
... ... @@ -105,7 +118,7 @@ class ReInquiryCount extends Base
if(!$res){
$res = HttpUtils::get('https://fob.ai.cc/api/get_bind_project_list', []);
$res = json_decode($res, true)['data'] ?? [];
Cache::put($cache_key, $res, 120);
Cache::put($cache_key, $res, 2 * 3600);
}
return $res;
}
... ...
... ... @@ -41,7 +41,7 @@ class ReInquiryTask extends Base
* @param int $status
* @return ReInquiryTask
*/
public static function createTask($id, $title, $industry, $ad_id, $ad_url, $ad_img, $num, $status, $is_replace_text, $ai_param, $is_show_fb_source)
public static function createTask($id, $title, $industry, $ad_id, $ad_url, $ad_img, $num, $status, $is_replace_text, $ai_param, $is_show_fb_source, $second_push_rate)
{
$self = self::where(['id' => $id])->first();
if (empty($self))
... ... @@ -56,6 +56,7 @@ class ReInquiryTask extends Base
$self->is_replace_text = $is_replace_text;
$self->ai_param = $ai_param;
$self->is_show_fb_source = $is_show_fb_source;
$self->second_push_rate = $second_push_rate;
$self->save();
return $self;
}
... ... @@ -73,6 +74,7 @@ class ReInquiryTask extends Base
$item['agent_group'] = $item['agent_group'] ?? '';
$item['is_require'] = $item['is_require'] ?? 0;
$item['price'] = $item['price'] ?? 0;
$item['frequency'] = $item['frequency'] ?? '3'; //默认频率3天一次
}
return $value;
}
... ...
<?php
/**
* @remark :
* @name :TicketUploadData.php
* @author :lyh
* @method :post
* @time :2025/9/25 09:33
*/
namespace App\Models\Ticket;
use App\Helper\Arr;
use App\Models\Base;
/**
* @remark :工单内上传数据
* @name :TicketUploadData
* @author :lyh
* @method :post
* @time :2025/9/25 09:34
*/
class TicketUploadData extends Base
{
protected $table = 'gl_tickets_upload_data';
public function getTextAttribute($value){
if(!empty($value)){
$value = Arr::s2a($value);
}
return $value;
}
}
... ...
... ... @@ -94,3 +94,13 @@ Route::prefix('tickets')->group(function () {
});
Route::any('/get_project_records', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'get_project_records'])->name('tickets.get_project_records');
Route::get('/pushTicketByBot/{friend_id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'pushTicketByBot'])->summary('企微群@机器人触发工单推送')->name('tickets.pushTicketByBot');
//保存工单提交数据(产品,新闻,博客)详情
Route::prefix('ticket_upload')->group(function () {
Route::any('/', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'lists'])->name('ticket_upload.lists');
Route::any('/info', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'info'])->name('ticket_upload.info');
Route::any('/save', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'save'])->name('ticket_upload.save');
Route::any('/getProductCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getProductCate'])->name('ticket_upload.getProductCate');
Route::any('/getBlogCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getBlogCate'])->name('ticket_upload.getBlogCate');
Route::any('/getNewsCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getNewsCate'])->name('ticket_upload.getNewsCate');
});
... ...
... ... @@ -644,6 +644,12 @@ Route::middleware(['aloginauth'])->group(function () {
Route::any('/monthManageList', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'monthManageList'])->name('ticket_count_monthManageList');//月统计数据
Route::any('/manageTicketCount', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'manageTicketCount'])->name('ticket_count_manageTicketCount');
});
//ticket
Route::prefix('ticket_upload')->group(function () {
Route::any('/', [Aside\Ticket\TicketUploadDataController::class,'lists'])->name('ticket_upload_lists');
Route::any('/save', [Aside\Ticket\TicketUploadDataController::class,'save'])->name('ticket_upload_save');
Route::any('/detail', [Aside\Ticket\TicketUploadDataController::class,'detail'])->name('ticket_upload_detail');
});
});
//无需登录验证的路由组
... ...