作者 zhl

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

@@ -43,7 +43,7 @@ class RemainDay extends Command @@ -43,7 +43,7 @@ class RemainDay extends Command
43 * @var 暂停的项目 43 * @var 暂停的项目
44 */ 44 */
45 protected $ceaseProjectId = [ 45 protected $ceaseProjectId = [
46 - 354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250, 2193, 2399, 1685, 3931 46 + 354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250, 2193, 2399, 1685, 3931,2273,3647
47 ];//需要单独处理的项目 47 ];//需要单独处理的项目
48 /** 48 /**
49 * The console command description. 49 * The console command description.
@@ -982,17 +982,17 @@ class RelayInquiry extends Command @@ -982,17 +982,17 @@ class RelayInquiry extends Command
982 $inquiry_date = Carbon::make($inquiry_date); 982 $inquiry_date = Carbon::make($inquiry_date);
983 //当天的 983 //当天的
984 if($inquiry_date->isToday()){ 984 if($inquiry_date->isToday()){
985 - //广告投放日(周一、二、三) 第一封询盘100%及时推送  
986 - $is_first = false;  
987 - if(in_array($inquiry_date->weekday(), [1,2,3])) { 985 + //广告投放日(周一、二、三、四) 第一封询盘100%及时推送
  986 + $is_timely = true; //是否及时推送
  987 + if(in_array($inquiry_date->weekday(), [1,2,3,4])) {
988 //是否今天的第一封询盘 988 //是否今天的第一封询盘
989 $detail = ReInquiryDetail::where('re_website', $domain)->where('start_at', '>=', $inquiry_date->startOfDay()->toDatetimeString())->first(); 989 $detail = ReInquiryDetail::where('re_website', $domain)->where('start_at', '>=', $inquiry_date->startOfDay()->toDatetimeString())->first();
990 - if(!$detail){  
991 - $is_first = true; 990 + if($detail){
  991 + $is_timely = false; //只有周一到周四的非第一封询盘 根据概率及时推送
992 } 992 }
993 } 993 }
994 - //非广告投放日第一封询盘  
995 - if(!$is_first && $task->second_push_rate != 100){ 994 + //概率及时推送
  995 + if(!$is_timely && $task->second_push_rate != 100){
996 //按概率 996 //按概率
997 $res = $this->get_rand([$task->second_push_rate, 100 - $task->second_push_rate]); 997 $res = $this->get_rand([$task->second_push_rate, 100 - $task->second_push_rate]);
998 if($res == 1){ 998 if($res == 1){
@@ -21,8 +21,11 @@ use App\Models\Project\Payment; @@ -21,8 +21,11 @@ use App\Models\Project\Payment;
21 use App\Models\Project\Project; 21 use App\Models\Project\Project;
22 use App\Models\Project\ProjectAiSetting; 22 use App\Models\Project\ProjectAiSetting;
23 use App\Models\Project\ProjectWhiteHatAffix; 23 use App\Models\Project\ProjectWhiteHatAffix;
  24 +use App\Models\RouteMap\RouteMap;
24 use App\Models\Template\BTemplateMain; 25 use App\Models\Template\BTemplateMain;
25 use App\Models\Template\TemplateTypeMain; 26 use App\Models\Template\TemplateTypeMain;
  27 +use App\Models\WebSetting\Translate;
  28 +use App\Models\WebSetting\TranslateData;
26 use App\Models\WebSetting\WebSetting; 29 use App\Models\WebSetting\WebSetting;
27 use App\Models\WorkOrder\TicketLog; 30 use App\Models\WorkOrder\TicketLog;
28 use App\Models\WorkOrder\Tickets; 31 use App\Models\WorkOrder\Tickets;
@@ -51,30 +54,7 @@ class lyhDemo extends Command @@ -51,30 +54,7 @@ class lyhDemo extends Command
51 protected $description = '更新路由'; 54 protected $description = '更新路由';
52 55
53 public function handle(){ 56 public function handle(){
54 - $projectModel = new Payment();  
55 - $lists = $projectModel->list(['renewal_record'=>['not like','"expire_at": null']]);  
56 - foreach ($lists as $item){  
57 - foreach ($item['renewal_record'] as $key => $val){  
58 - if(!isset($val['end_time']) && !empty($val['expire_at'])){  
59 - $val['end_time'] = $val['expire_at'];  
60 - }  
61 - $item['renewal_record'][$key] = $val;  
62 - }  
63 - $projectModel->edit(['renewal_record'=>json_encode($item['renewal_record'],true)],['id'=>$item['id']]);  
64 - }  
65 - return true;  
66 - }  
67 -  
68 - public function getExpectResult(){  
69 - $geo_service = new GeoService();  
70 - $question = 'Top AI Coffee Robot';  
71 - $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.";  
72 - $expect = "While I don't have specific information on the RobotAnno coffee machine, in general";  
73 - $str = "客户提出的问题:{$question},客户得到的回复:{$answer},客户需要预期:{$expect},请分析得到的回复和预期是否一致,仅回复我是或者否";  
74 - $data = $geo_service->getChatResult($str, 'gpt-4o-mini');  
75 - if(isset($data['text']) && $data['text'] == '是'){  
76 -  
77 - } 57 + return $this->translate_action();
78 } 58 }
79 59
80 /** 60 /**
@@ -257,9 +237,133 @@ class lyhDemo extends Command @@ -257,9 +237,133 @@ class lyhDemo extends Command
257 echo "字段 $field 小写替换出错:" . $e->getMessage() . PHP_EOL; 237 echo "字段 $field 小写替换出错:" . $e->getMessage() . PHP_EOL;
258 } 238 }
259 } 239 }
260 -  
261 echo '执行结束' . PHP_EOL; 240 echo '执行结束' . PHP_EOL;
  241 + DB::disconnect('custom_mysql');
  242 + }
262 243
  244 + public function translate_action()
  245 + {
  246 + ProjectServer::useProject(655);
  247 + $this->model = new Translate();
  248 + $lists = DB::connection('custom_mysql')->table('gl_translate_copy1')->where('url','!=','All')->get()->toArray();
  249 + foreach ($lists as $item) {
  250 + $item = (array)$item;
  251 + $sourceInfo = $this->getRouteSource($item['url']);
  252 + $info = $this->model->read(['language_id'=>$item['language_id'],'source_id'=>$sourceInfo['source_id'],'url'=>$item['url'],'project_id'=>655,'type'=>$item['type']]);
  253 + if($info === false){
  254 + $param = [
  255 + 'type'=>$item['type'] ?? 1,
  256 + 'project_id'=>655,
  257 + 'url'=>$item['url'],
  258 + 'language_id'=>$item['language_id'],
  259 + 'alias'=>$item['alias'],
  260 + 'source'=>$sourceInfo['source'],
  261 + 'source_id'=>$sourceInfo['source_id'],
  262 + 'is_list'=>$sourceInfo['is_list'],
  263 + 'is_custom'=>$sourceInfo['is_custom'],
  264 + 'page'=>$sendData['page'] ?? 0
  265 + ];
  266 + $id = $this->model->addReturnId($param);
  267 + TranslateData::insert(['trans_id'=>$id,'data'=>$item['data']]);
  268 + }else{
  269 + TranslateData::where(['trans_id'=>$info['id']])->update(['data'=>$item['data']]);
  270 + }
  271 + }
263 DB::disconnect('custom_mysql'); 272 DB::disconnect('custom_mysql');
264 } 273 }
  274 +
  275 + public function getRouteSource($route){
  276 + $routes = $route;
  277 + $data = ['source'=>0,'source_id'=>0,'is_list'=>0,'is_custom'=>0,'page'=>0];
  278 + if(strtolower($route) == 'all'){
  279 + return $data;
  280 + }
  281 + if($route == 'index' || $route == '/'){
  282 + $data['source'] = 1;
  283 + return $data;
  284 + }
  285 + $route = basename($route);
  286 + $page = 0;
  287 + if (is_numeric($route)) {
  288 + $arr = explode('/',$routes);
  289 + $page = $route;
  290 + $route = $arr[0];
  291 + }
  292 + $routeModel = new RouteMap();
  293 + $routeInfo = $routeModel->read(['route'=>$route]);
  294 + if($routeInfo === false){
  295 + if(in_array($route,['products','news','blog'])){
  296 + //固定路由
  297 + $data['page'] = $page;
  298 + $data['is_list'] = 1;
  299 + if($route == 'products'){
  300 + $data['source'] = 2;
  301 + }elseif ($route == 'news'){
  302 + $data['source'] = 4;
  303 + }else{
  304 + $data['source'] = 3;
  305 + }
  306 + return $data;
  307 + }
  308 + return $data;
  309 + }
  310 + $data = $this->resultData($routeInfo,$data);
  311 + $data['page'] = $page;
  312 + return $data;
  313 + }
  314 +
  315 + public function resultData($routeInfo,$data){
  316 + if($routeInfo['source'] == RouteMap::SOURCE_PAGE){
  317 + if($routeInfo['source_id']){
  318 + $data = ['source'=>9,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>0];
  319 + }
  320 + }
  321 + if($routeInfo['source'] == RouteMap::SOURCE_PRODUCT){
  322 + if($routeInfo['source_id']){
  323 + $data = ['source'=>2,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>0];
  324 + }
  325 + }
  326 + if($routeInfo['source'] == RouteMap::SOURCE_PRODUCT_CATE){
  327 + if($routeInfo['source_id']){
  328 + $data = ['source'=>2,'source_id'=>$routeInfo['source_id'],'is_list'=>1,'is_custom'=>0];
  329 + }
  330 + }
  331 + if($routeInfo['source'] == RouteMap::SOURCE_BLOG){
  332 + if($routeInfo['source_id']){
  333 + $data = ['source'=>3,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>0];
  334 + }
  335 + }
  336 + if($routeInfo['source'] == RouteMap::SOURCE_BLOG_CATE){
  337 + if($routeInfo['source_id']){
  338 + $data = ['source'=>3,'source_id'=>$routeInfo['source_id'],'is_list'=>1,'is_custom'=>0];
  339 + }
  340 + }
  341 + if($routeInfo['source'] == RouteMap::SOURCE_NEWS){
  342 + if($routeInfo['source_id']){
  343 + $data = ['source'=>4,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>0];
  344 + }
  345 + }
  346 + if($routeInfo['source'] == RouteMap::SOURCE_NEWS_CATE){
  347 + if($routeInfo['source_id']){
  348 + $data = ['source'=>4,'source_id'=>$routeInfo['source_id'],'is_list'=>1,'is_custom'=>0];
  349 + }
  350 + }
  351 + if($routeInfo['source'] == RouteMap::SOURCE_PRODUCT_KEYWORD){
  352 + if($routeInfo['source_id']){
  353 + $data = ['source'=>8,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>0];
  354 + }
  355 + }
  356 + if($routeInfo['source'] == RouteMap::SOURCE_MODULE){
  357 + if($routeInfo['source_id']){
  358 + $data = ['source'=>7,'source_id'=>$routeInfo['source_id'],'is_list'=>0,'is_custom'=>1];
  359 + }
  360 + }
  361 + if($routeInfo['source'] == RouteMap::SOURCE_MODULE_CATE){
  362 + if($routeInfo['source_id']){
  363 + $data = ['source'=>7,'source_id'=>$routeInfo['source_id'],'is_list'=>1,'is_custom'=>1];
  364 + }
  365 + }
  366 + return $data;
  367 + }
  368 +
265 } 369 }
@@ -97,7 +97,7 @@ class SyncSubmitTask extends Command @@ -97,7 +97,7 @@ class SyncSubmitTask extends Command
97 } 97 }
98 $task_info->save(); 98 $task_info->save();
99 Log::channel('inquiry')->error($task_id . '处理失败', [$e->getMessage(), $e->getFile(), $e->getLine()]); 99 Log::channel('inquiry')->error($task_id . '处理失败', [$e->getMessage(), $e->getFile(), $e->getLine()]);
100 - $this->output('任务失败:' . $e->getMessage()); 100 + $this->output('任务失败:' . $e->getMessage() . $e->getFile() . $e->getLine());
101 } 101 }
102 102
103 $use_time = time() - $time; 103 $use_time = time() - $time;
@@ -245,4 +245,41 @@ class Arr extends \Illuminate\Support\Arr @@ -245,4 +245,41 @@ class Arr extends \Illuminate\Support\Arr
245 }, $arr)); 245 }, $arr));
246 return json_encode(array_values(array_unique(array_filter($array)))); 246 return json_encode(array_values(array_unique(array_filter($array))));
247 } 247 }
  248 +
  249 +
  250 + /**
  251 + * 数组转文本html数组
  252 + * @param $array
  253 + * @param $indentLevel
  254 + * @return array
  255 + * @author zbj
  256 + * @date 2025/9/26
  257 + */
  258 + public static function formatForHtml($array, $indentLevel = 0) {
  259 + $result = [];
  260 + $indent = str_repeat('    ', $indentLevel);
  261 +
  262 + foreach ($array as $key => $value) {
  263 + $isNumericKey = is_numeric($key);
  264 +
  265 + if (is_array($value)) {
  266 + if (!$isNumericKey) {
  267 + $result[] = "{$indent}{$key}:<br/>";
  268 + $nestedResult = self::formatForHtml($value, $indentLevel + 1);
  269 + } else {
  270 + $key && $result[] = '<br/>';
  271 + $nestedResult = self::formatForHtml($value, $indentLevel);
  272 + }
  273 + $result = array_merge($result, $nestedResult);
  274 + } else {
  275 + if ($isNumericKey) {
  276 + $result[] = "{$indent}{$value}<br/>";
  277 + } else {
  278 + $result[] = "{$indent}{$key}: {$value}<br/>";
  279 + }
  280 + }
  281 + }
  282 +
  283 + return $result;
  284 + }
248 } 285 }
@@ -20,14 +20,83 @@ use Illuminate\Support\Facades\Cache; @@ -20,14 +20,83 @@ use Illuminate\Support\Facades\Cache;
20 */ 20 */
21 class BaseController extends Controller 21 class BaseController extends Controller
22 { 22 {
23 - public $param;  
24 - public $request; 23 + protected $param = [];//所有请求参数
  24 + protected $token = ''; //token
  25 + protected $request = [];//助手函数
  26 + protected $page = 1;//当前页
  27 + protected $row = 20;//每页条数
  28 + protected $header = [];//设置请求头参数
  29 + protected $order = 'created_at';
  30 + protected $order_type = 'desc';
  31 + protected $map = [];//处理后的参数
  32 +
25 33
26 public function __construct(Request $request) 34 public function __construct(Request $request)
27 { 35 {
28 $this->request = $request; 36 $this->request = $request;
29 $this->param = $this->request->all(); 37 $this->param = $this->request->all();
  38 + $this->getParam();
  39 + }
  40 +
  41 + /**
  42 + * @remark :请求参数处理
  43 + * @name :getParam
  44 + * @author :lyh
  45 + * @method :post
  46 + * @time :2023/6/17 16:34
  47 + */
  48 + public function getParam(){
  49 + foreach ($this->param as $k => $v){
  50 + if(is_array($v)){
  51 + $this->map[$k] = $v;
  52 + }else{
  53 + $this->getMap($k,$v);
  54 + }
  55 + }
30 } 56 }
  57 +
  58 + /**
  59 + * @remark :搜索参数处理
  60 + * @name :getMap
  61 + * @author :lyh
  62 + * @method :post
  63 + * @time :2023/8/28 10:22
  64 + */
  65 + public function getMap($k,$v){
  66 + switch ($k){
  67 + case "order":
  68 + $this->order = $v;
  69 + break;
  70 + case "order_type":
  71 + $this->order_type = $v;
  72 + break;
  73 + case 'page':
  74 + $this->page = $v;
  75 + break;
  76 + case 'row':
  77 + case 'size':
  78 + $this->row = $v;
  79 + break;
  80 + case "name":
  81 + $this->map['name'] = ['like','%'.$v.'%'];
  82 + break;
  83 + case "start_at":
  84 + $this->_btw[0] = $v;
  85 + $this->_btw[1] = date('Y-m-d H:i:s',time());
  86 + $this->map['created_at'] = ['between', $this->_btw];
  87 + break;
  88 + case "end_at":
  89 + $this->_btw[1] = $v;
  90 + $this->map['created_at'] = ['between', $this->_btw];
  91 + break;
  92 + default:
  93 + if (!empty($v) || $v == 0) {
  94 + $this->map[$k] = $v;
  95 + }
  96 + break;
  97 + }
  98 + }
  99 +
31 /** 100 /**
32 * @param array $data 101 * @param array $data
33 * @param string $message 102 * @param string $message
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :TicketUploadDataController.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/9/25 09:40
  8 + */
  9 +
  10 +namespace App\Http\Controllers\Api\WorkOrder;
  11 +
  12 +use App\Enums\Common\Code;
  13 +use App\Http\Controllers\Api\BaseController;
  14 +use App\Models\Blog\BlogCategory;
  15 +use App\Models\News\NewsCategory;
  16 +use App\Models\Product\Category;
  17 +use App\Models\Product\Keyword;
  18 +use App\Models\Ticket\TicketUploadData;
  19 +use App\Services\ProjectServer;
  20 +use Illuminate\Http\Request;
  21 +use Illuminate\Support\Facades\DB;
  22 +
  23 +/**
  24 + * @remark :上传产品/博客/新闻模块
  25 + * @name :TicketUploadDataController
  26 + * @author :lyh
  27 + * @method :post
  28 + * @time :2025/9/25 09:40
  29 + */
  30 +class TicketUploadDataController extends BaseController
  31 +{
  32 + public function __construct(Request $request)
  33 + {
  34 + parent::__construct($request);
  35 + $this->model = new TicketUploadData();
  36 + }
  37 +
  38 + /**
  39 + * @remark :已提交列表
  40 + * @name :lists
  41 + * @author :lyh
  42 + * @method :post
  43 + * @time :2025/9/25 10:28
  44 + */
  45 + public function lists()
  46 + {
  47 + $this->request->validate([
  48 + 'project_id' => 'required',
  49 + ], [
  50 + 'project_id.required' => 'project_id不能为空',
  51 + ]);
  52 + $data = $this->model->lists($this->map, $this->page, $this->row, $this->order);
  53 + $this->response('success', Code::SUCCESS, $data);
  54 + }
  55 +
  56 + /**
  57 + * @remark :获取数据详情
  58 + * @name :info
  59 + * @author :lyh
  60 + * @method :post
  61 + * @time :2025/9/25 10:35
  62 + */
  63 + public function info()
  64 + {
  65 + $this->request->validate([
  66 + 'id' => 'required',
  67 + ], [
  68 + 'id.required' => 'id不能为空',
  69 + ]);
  70 + $data = $this->model->read($this->param);
  71 + $this->response('success', Code::SUCCESS, $data);
  72 + }
  73 +
  74 + /**
  75 + * @remark :提交数据
  76 + * @name :save
  77 + * @author :lyh
  78 + * @method :post
  79 + * @time :2025/9/25 09:48
  80 + */
  81 + public function save()
  82 + {
  83 + $this->request->validate([
  84 + 'project_id' => 'required',
  85 + 'type' => 'required',
  86 + 'text' => 'required'
  87 + ], [
  88 + 'project_id.required' => 'project_id不能为空',
  89 + 'type.required' => '上传类型不能为空',
  90 + 'text' => '数据详情不为空'
  91 + ]);
  92 + //验证当前数据是否已提交
  93 + $this->param['text'] = json_encode($this->param['text'], true);
  94 + $info = $this->model->read(['project_id' => $this->$this->param['project_id'], 'type' => $this->param['type'], 'text' => $this->param['text'], 'status' => 0]);
  95 + if ($info === false) {
  96 + $id = $this->model->addReturnId($this->param);
  97 + } else {
  98 + $id = $info['id'];
  99 + }
  100 + $data = ['id' => $id];
  101 + $this->response('success', Code::SUCCESS, $data);
  102 + }
  103 +
  104 + /**
  105 + * @remark :根据项目获取分类
  106 + * @name :getProductCate
  107 + * @author :lyh
  108 + * @method :post
  109 + * @time :2025/9/25 15:41
  110 + */
  111 + public function getProductCate()
  112 + {
  113 + $this->request->validate([
  114 + 'project_id' => 'required',
  115 + 'type' => 'required',
  116 + 'search' => 'required'
  117 + ], [
  118 + 'project_id.required' => 'project_id不能为空',
  119 + 'type.required' => 'type不能为空',
  120 + 'search.required' => '搜索参数不能为空',
  121 + ]);
  122 + ProjectServer::useProject($this->param['project_id']);
  123 + if ($this->param['type'] == 1) {
  124 + //todo::搜索获取分类
  125 + $productCateModel = new Category();
  126 + $data = $productCateModel->lists(['title' => ['like' => '%' . $this->param['search'] . '%']], 1, 20);
  127 + } else {
  128 + $keywordModel = new Keyword();
  129 + $data = $keywordModel->lists(['title' => ['like' => '%' . $this->param['search'] . '%']], 1, 20);
  130 + }
  131 + DB::disconnect('custom_mysql');
  132 + $this->response('success', Code::SUCCESS, $data);
  133 + }
  134 +
  135 + /**
  136 + * @remark :获取博客分类
  137 + * @name :getBlogCate
  138 + * @author :lyh
  139 + * @method :post
  140 + * @time :2025/9/25 15:42
  141 + */
  142 + public function getBlogCate()
  143 + {
  144 + $this->request->validate([
  145 + 'project_id' => 'required',
  146 + 'search' => 'required'
  147 + ], [
  148 + 'project_id.required' => 'project_id不能为空',
  149 + 'search.required' => '搜索参数不能为空',
  150 + ]);
  151 + ProjectServer::useProject($this->param['project_id']);
  152 + $blogCateModel = new BlogCategory();
  153 + $data = $blogCateModel->lists(['name' => ['like' => '%' . $this->param['search'] . '%']], 1, 20);
  154 + DB::disconnect('custom_mysql');
  155 + $this->response('success', Code::SUCCESS, $data);
  156 + }
  157 +
  158 + /**
  159 + * @remark :获取新闻分类
  160 + * @name :getNewsCate
  161 + * @author :lyh
  162 + * @method :post
  163 + * @time :2025/9/25 15:43
  164 + */
  165 + public function getNewsCate()
  166 + {
  167 + $this->request->validate([
  168 + 'project_id' => 'required',
  169 + 'search' => 'required'
  170 + ], [
  171 + 'project_id.required' => 'project_id不能为空',
  172 + 'search.required' => '搜索参数不能为空',
  173 + ]);
  174 + ProjectServer::useProject($this->param['project_id']);
  175 + $newsCateModel = new NewsCategory();
  176 + $data = $newsCateModel->lists(['name' => ['like' => '%' . $this->param['search'] . '%']], 1, 20);
  177 + DB::disconnect('custom_mysql');
  178 + $this->response('success', Code::SUCCESS, $data);
  179 + }
  180 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :TicketUploadDataController.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/9/25 14:00
  8 + */
  9 +
  10 +namespace App\Http\Controllers\Aside\Ticket;
  11 +
  12 +use App\Enums\Common\Code;
  13 +use App\Http\Controllers\Aside\BaseController;
  14 +use App\Http\Logic\Aside\Ticket\TicketUploadDataLogic;
  15 +use Illuminate\Http\Request;
  16 +
  17 +/**
  18 + * @remark :工单上传列表审核功能
  19 + * @name :TicketUploadDataController
  20 + * @author :lyh
  21 + * @method :post
  22 + * @time :2025/9/25 14:01
  23 + */
  24 +class TicketUploadDataController extends BaseController
  25 +{
  26 + public function __construct(Request $request)
  27 + {
  28 + parent::__construct($request);
  29 + $this->logic = new TicketUploadDataLogic();
  30 + }
  31 +
  32 + /**
  33 + * @remark :获取审核列表
  34 + * @name :lists
  35 + * @author :lyh
  36 + * @method :post
  37 + * @time :2025/9/25 14:02
  38 + */
  39 + public function lists(){
  40 + if(isset($this->map['text']) && !empty($this->map['text'])){
  41 + $this->map['text'] = ['like','%'.$this->map['text'].'%'];
  42 + }
  43 + $data = $this->logic->getDataList($this->map,$this->page,$this->row,$this->order);
  44 + $this->response('success',Code::SUCCESS,$data);
  45 + }
  46 +
  47 + /**
  48 + * @remark :获取数据详情
  49 + * @name :detail
  50 + * @author :lyh
  51 + * @method :post
  52 + * @time :2025/9/26 09:29
  53 + */
  54 + public function detail(){
  55 + $this->request->validate([
  56 + 'id'=>'required'
  57 + ],[
  58 + 'id.required' => '主键ID不能为空',
  59 + ]);
  60 + $data = $this->logic->getDetail();
  61 + $this->response('success',Code::SUCCESS,$data);
  62 + }
  63 +
  64 + /**
  65 + * @remark :人工审核
  66 + * @name :save
  67 + * @author :lyh
  68 + * @method :post
  69 + * @time :2025/9/25 14:14
  70 + */
  71 + public function save()
  72 + {
  73 + $this->request->validate([
  74 + 'status'=>'required',
  75 + 'id'=>'required'
  76 + ],[
  77 + 'status.required' => '提交状态不能为空',
  78 + 'id.required' => '主键ID不能为空',
  79 + ]);
  80 + $data = $this->logic->saveData();
  81 + $this->response('success',Code::SUCCESS,$data);
  82 + }
  83 +}
@@ -155,8 +155,8 @@ class RankDataController extends BaseController @@ -155,8 +155,8 @@ class RankDataController extends BaseController
155 'cnt_first' => '排名第一', 155 'cnt_first' => '排名第一',
156 'cnt_home' => '第一页', 156 'cnt_home' => '第一页',
157 'cnt_thirty' => '前三页', 157 'cnt_thirty' => '前三页',
158 - 'cnt_fifty' => '前五页',  
159 - 'cnt_hundred' => '前十页', 158 +// 'cnt_fifty' => '前五页',
  159 +// 'cnt_hundred' => '前十页',
160 'reach' => '是否达标', 160 'reach' => '是否达标',
161 ]; 161 ];
162 } 162 }
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :TicketUploadDataLogic.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/9/25 14:03
  8 + */
  9 +
  10 +namespace App\Http\Logic\Aside\Ticket;
  11 +
  12 +use App\Helper\Arr;
  13 +use App\Http\Logic\Aside\BaseLogic;
  14 +use App\Models\Blog\Blog;
  15 +use App\Models\News\News;
  16 +use App\Models\Product\CategoryRelated;
  17 +use App\Models\Product\KeywordRelated;
  18 +use App\Models\Product\Product;
  19 +use App\Models\RouteMap\RouteMap;
  20 +use App\Models\Ticket\TicketUploadData;
  21 +use App\Services\ProjectServer;
  22 +use Illuminate\Support\Facades\DB;
  23 +
  24 +class TicketUploadDataLogic extends BaseLogic
  25 +{
  26 + public function __construct()
  27 + {
  28 + parent::__construct();
  29 + $this->param = $this->requestAll;
  30 + $this->model = new TicketUploadData();
  31 + }
  32 +
  33 + /**
  34 + * @remark :获取审核列表
  35 + * @name :getDataList
  36 + * @author :lyh
  37 + * @method :post
  38 + * @time :2025/9/25 14:17
  39 + */
  40 + public function getDataList($map = [],$page = 1,$row = 20,$order = 'id'){
  41 + if(isset($this->map['text']) && !empty($this->map['text'])){
  42 + $this->map['text'] = ['like','%'.$this->map['text'].'%'];
  43 + }
  44 + $data = $this->model->lists($map,$page,$row,$order);
  45 + foreach ($data as &$v){
  46 + $v = $this->getHandleFileImage($v);
  47 + }
  48 + return $this->success($data);
  49 + }
  50 +
  51 + /**
  52 + * @remark :处理数据
  53 + * @name :getHandleFileImage
  54 + * @author :lyh
  55 + * @method :post
  56 + * @time :2025/9/25 16:53
  57 + */
  58 + public function getHandleFileImage($v){
  59 + if($v['type'] == 1){
  60 + if(!empty($v['text']['image'])){
  61 + foreach ($v['text']['image'] as $gallery_k => $gallery_v){
  62 + $gallery_v['url'] = getImageUrl($gallery_v['url'],$this->user['storage_type'] ?? 0,$this->user['project_location']);
  63 + $info['text']['image'][$gallery_k] = $gallery_v;
  64 + }
  65 + }
  66 + }else{
  67 + $v['text']['image'] = getImageUrl($v['text']['image'],$this->user['storage_type'],$this->user['project_location']);
  68 + }
  69 + return $this->success($v);
  70 + }
  71 +
  72 + /**
  73 + * @remark :获取当前数据详情
  74 + * @name :getDetail
  75 + * @author :lyh
  76 + * @method :post
  77 + * @time :2025/9/26 09:31
  78 + */
  79 + public function getDetail(){
  80 + $info = $this->model->read(['id'=>$this->param['id']]);
  81 + if($info === false){
  82 + $this->fail('当前数据不存在或已被删除');
  83 + }
  84 + $info = $this->getHandleFileImage($info);
  85 + return $this->success($info);
  86 + }
  87 +
  88 + /**
  89 + * @remark :保存数据
  90 + * @name :saveData
  91 + * @author :lyh
  92 + * @method :post
  93 + * @time :2025/9/25 17:01
  94 + */
  95 + public function saveData()
  96 + {
  97 + //获取当前数据详情
  98 + $info = $this->model->read(['id'=>$this->param['id']]);
  99 + if($info === false){
  100 + $this->fail('当前数据不存在或已被删除');
  101 + }
  102 + //审核成功执行
  103 + if($this->param['status'] == 1){
  104 + ProjectServer::useProject($info['project_id']);
  105 + if($info['type'] == 1){
  106 + $this->saveProductData($info);
  107 + }elseif ($info['type'] == 2){
  108 + $this->saveBlogData($info);
  109 + }else{
  110 + $this->saveNewsData($info);
  111 + }
  112 + DB::disconnect('custom_mysql');
  113 + }
  114 + $data = $this->model->edit(['status'=>$this->param['status'],'operator_id'=>$this->manager['id'],'remark'=>$this->param['remark'] ?? ''],['id'=>$this->param['id']]);
  115 + return $this->success($data);
  116 + }
  117 +
  118 + /**
  119 + * @remark :保存数据详情
  120 + * @name :saveData
  121 + * @author :lyh
  122 + * @method :post
  123 + * @time :2025/9/25 14:17
  124 + */
  125 + public function saveProductData($info){
  126 + if(isset($info['text']['keyword_id']) && !empty($info['text']['keyword_id'])){
  127 + $keyword_id = ','.Arr::arrToSet($info['text']['keyword_id']).',';
  128 + }
  129 + if(isset($info['text']['category_id']) && !empty($info['text']['category_id'])) {
  130 + $category_id = ','.Arr::arrToSet($info['text']['category_id']).',';
  131 + }
  132 + if(isset($info['text']['image']) && !empty($info['text']['image'])){
  133 + foreach ($info['text']['image'] as $k => $v){
  134 + $v['url'] = str_replace_url($v['url']);
  135 + $info['text']['image'][$k] = $v;
  136 + }
  137 + $info['text']['image'] = Arr::a2s($info['text']['image'] ?? []);
  138 + }else{
  139 + $info['text']['image'] = Arr::a2s([]);
  140 + }
  141 + try {
  142 + $productModel = new Product();
  143 + $data = [
  144 + 'project_id' => $info['project_id'],
  145 + 'title' => $info['text']['title'],
  146 + 'thumb'=>json_encode($info['text']['image'][0] ?? [],true),
  147 + 'gallery'=>json_encode($info['text']['image'] ?? [],true),
  148 + 'intro'=>$info['text']['remark'],
  149 + 'category_id'=>$category_id ?? '',
  150 + 'keyword_id'=>$keyword_id ?? '',
  151 + 'status'=>0,
  152 + ];
  153 + $id = $productModel->addReturnId($data);
  154 + CategoryRelated::saveRelated($id, $info['text']['category_id'] ?? []);//分类关联
  155 + KeywordRelated::saveRelated($id,$info['text']['keyword_id'] ?? []);//关键字关联
  156 + $route = RouteMap::setRoute($data['title'],RouteMap::SOURCE_PRODUCT,$id,$info['project_id']);
  157 + $this->model->edit(['route'=>$route],['id'=>$id]);
  158 + }catch (\Exception $e){
  159 + $this->fail('保存失败,请联系管理员');
  160 + }
  161 + return $this->success();
  162 + }
  163 +
  164 + /**
  165 + * @remark :保存blog数据
  166 + * @name :saveBlogData
  167 + * @author :lyh
  168 + * @method :post
  169 + * @time :2025/9/25 16:26
  170 + */
  171 + public function saveBlogData($info)
  172 + {
  173 + if(isset($info['text']['category_id']) && !empty($info['text']['category_id'])) {
  174 + $category_id = ','.Arr::arrToSet($info['text']['category_id']).',';
  175 + }
  176 + if(isset($info['text']['image'])){
  177 + $info['text']['image'] = str_replace_url($info['text']['image'] ?? '');
  178 + }
  179 + $data = [
  180 + 'project_id' => $info['project_id'],
  181 + 'name' => $info['text']['title'],
  182 + 'image'=>$info['text']['image'],
  183 + 'text'=>$info['text']['remark'],
  184 + 'category_id'=>$category_id ?? '',
  185 + 'status'=>0,
  186 + ];
  187 + try {
  188 + $blogModel = new Blog();
  189 + $id = $blogModel->addReturnId($data);
  190 + $route = RouteMap::setRoute($data['name'],RouteMap::SOURCE_BLOG,$id,$info['project_id']);
  191 + $this->model->edit(['url'=>$route],['id'=>$id]);
  192 + }catch (\Exception $e){
  193 + $this->fail('保存失败,请联系管理员');
  194 + }
  195 + return $this->success();
  196 + }
  197 +
  198 + /**
  199 + * @remark :保存新闻数据
  200 + * @name :saveNewsData
  201 + * @author :lyh
  202 + * @method :post
  203 + * @time :2025/9/25 16:34
  204 + */
  205 + public function saveNewsData($info)
  206 + {
  207 + if(isset($info['text']['category_id']) && !empty($info['text']['category_id'])) {
  208 + $category_id = ','.Arr::arrToSet($info['text']['category_id']).',';
  209 + }
  210 + if(isset($info['text']['image'])){
  211 + $info['text']['image'] = str_replace_url($info['text']['image'] ?? '');
  212 + }
  213 + $data = [
  214 + 'project_id' => $info['project_id'],
  215 + 'name' => $info['text']['title'],
  216 + 'image'=>$info['text']['image'],
  217 + 'text'=>$info['text']['remark'],
  218 + 'category_id'=>$category_id ?? '',
  219 + 'status'=>0,
  220 + ];
  221 + try {
  222 + $newsModel = new News();
  223 + $id = $newsModel->addReturnId($data);
  224 + $route = RouteMap::setRoute($data['name'],RouteMap::SOURCE_NEWS,$id,$info['project_id']);
  225 + $this->model->edit(['route'=>$route],['id'=>$id]);
  226 + }catch (\Exception $e){
  227 + $this->fail('保存失败,请联系管理员');
  228 + }
  229 + return $this->success();
  230 + }
  231 +}
@@ -48,7 +48,7 @@ class CountLogic extends BaseLogic @@ -48,7 +48,7 @@ class CountLogic extends BaseLogic
48 $domain = parse_url($this->user['domain'], PHP_URL_HOST); // 直接取域名部分 48 $domain = parse_url($this->user['domain'], PHP_URL_HOST); // 直接取域名部分
49 $inquiry_list = (new FormGlobalsoApi())->getInquiryAll($domain,$this->user['is_upgrade']); 49 $inquiry_list = (new FormGlobalsoApi())->getInquiryAll($domain,$this->user['is_upgrade']);
50 if($inquiry_list !== false){ 50 if($inquiry_list !== false){
51 - if($inquiry_list['status'] != 400){ 51 + if(isset($inquiry_list['status']) && $inquiry_list['status'] != 400){
52 $info['inquiry_num'] = $inquiry_list['data']['count']; 52 $info['inquiry_num'] = $inquiry_list['data']['count'];
53 Cache::add('inquiry_num_'.$this->user['project_id'],$inquiry_list['data']['count'],3600); 53 Cache::add('inquiry_num_'.$this->user['project_id'],$inquiry_list['data']['count'],3600);
54 } 54 }
@@ -555,7 +555,7 @@ class RankDataLogic extends BaseLogic @@ -555,7 +555,7 @@ class RankDataLogic extends BaseLogic
555 $without_extension_project_ids = [658]; //是否达标只统计主词的 555 $without_extension_project_ids = [658]; //是否达标只统计主词的
556 $extension_project_ids = [354]; //扩展词也到达标的 556 $extension_project_ids = [354]; //扩展词也到达标的
557 $compliance_project_ids = [2163,257,823,1750,497]; //直接达标处理的 557 $compliance_project_ids = [2163,257,823,1750,497]; //直接达标处理的
558 - $ceaseProjectId = [354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250,2193,2399,1685, 3931];//暂停的项目 558 + $ceaseProjectId = [354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250,2193,2399,1685, 3931,2273,3647];//暂停的项目
559 $uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目 559 $uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目
560 //一个项目多个api_no 560 //一个项目多个api_no
561 $multiple_api_no_project_ids = [ 561 $multiple_api_no_project_ids = [
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 2
3 namespace App\Models\Inquiry; 3 namespace App\Models\Inquiry;
4 4
  5 +use App\Helper\Arr;
5 use App\Helper\FormGlobalsoApi; 6 use App\Helper\FormGlobalsoApi;
6 use App\Models\Base; 7 use App\Models\Base;
7 use App\Utils\LogUtils; 8 use App\Utils\LogUtils;
@@ -83,6 +84,12 @@ class InquiryFormData extends Base @@ -83,6 +84,12 @@ class InquiryFormData extends Base
83 $v = getImageUrl($v['path']); 84 $v = getImageUrl($v['path']);
84 $data[$k] = $v; 85 $data[$k] = $v;
85 } 86 }
  87 + if(is_string($v)){
  88 + $arr = json_decode($v, true);
  89 + if(is_array($arr)){
  90 + $v = implode('', Arr::formatForHtml($arr));
  91 + }
  92 + }
86 //其他字段补充到message里 93 //其他字段补充到message里
87 if(!in_array($k, ['name', 'email', 'message', 'phone', 'ip', 'date', 'cname', 'domain', 'edition', 'domain_host_url'])){ 94 if(!in_array($k, ['name', 'email', 'message', 'phone', 'ip', 'date', 'cname', 'domain', 'edition', 'domain_host_url'])){
88 $data['message'].= "<br/>" . $k .': ' . $v; 95 $data['message'].= "<br/>" . $k .': ' . $v;
@@ -9,6 +9,7 @@ use App\Models\Base; @@ -9,6 +9,7 @@ use App\Models\Base;
9 use App\Models\Domain\DomainInfo; 9 use App\Models\Domain\DomainInfo;
10 use App\Models\Project\Project; 10 use App\Models\Project\Project;
11 use App\Models\Task\TaskOwner; 11 use App\Models\Task\TaskOwner;
  12 +use App\Services\DingService;
12 use App\Utils\HttpUtils; 13 use App\Utils\HttpUtils;
13 use Illuminate\Database\Eloquent\Model; 14 use Illuminate\Database\Eloquent\Model;
14 use Illuminate\Support\Facades\Cache; 15 use Illuminate\Support\Facades\Cache;
@@ -68,6 +69,18 @@ class ReInquiryCount extends Base @@ -68,6 +69,18 @@ class ReInquiryCount extends Base
68 $model->task_ids = $model->task_ids + [$task_id]; 69 $model->task_ids = $model->task_ids + [$task_id];
69 $model->num = $model->num + $num; 70 $model->num = $model->num + $num;
70 $model->save(); 71 $model->save();
  72 +
  73 + //数量首次达到100, 给钉钉推送消息
  74 + if($num > 0 && $model->num == 100){
  75 + (new DingService())->handle([
  76 + 'keyword' => '询盘数量通知',
  77 + 'msg' =>
  78 + '项目名称:' . $model->company . PHP_EOL .
  79 + '项目域名:' . $model->domain . PHP_EOL .
  80 + '询盘数量:' . $model->num,
  81 + 'isAtAll' => false, // 是否@所有人
  82 + ], 'https://oapi.dingtalk.com/robot/send?access_token=cd5733d3e6b810a501e3ea20df7c99ecb616aa6754fa048348837d088c1f5b2c');
  83 + }
71 } 84 }
72 85
73 public function setTaskIdsAttribute($value) 86 public function setTaskIdsAttribute($value)
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :TicketUploadData.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/9/25 09:33
  8 + */
  9 +
  10 +namespace App\Models\Ticket;
  11 +
  12 +use App\Helper\Arr;
  13 +use App\Models\Base;
  14 +
  15 +/**
  16 + * @remark :工单内上传数据
  17 + * @name :TicketUploadData
  18 + * @author :lyh
  19 + * @method :post
  20 + * @time :2025/9/25 09:34
  21 + */
  22 +class TicketUploadData extends Base
  23 +{
  24 + protected $table = 'gl_ticket_upload_data';
  25 +
  26 + public function getTextAttribute($value){
  27 + if(!empty($value)){
  28 + $value = Arr::s2a($value);
  29 + }
  30 + return $value;
  31 + }
  32 +}
@@ -94,3 +94,13 @@ Route::prefix('tickets')->group(function () { @@ -94,3 +94,13 @@ Route::prefix('tickets')->group(function () {
94 }); 94 });
95 Route::any('/get_project_records', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'get_project_records'])->name('tickets.get_project_records'); 95 Route::any('/get_project_records', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'get_project_records'])->name('tickets.get_project_records');
96 Route::get('/pushTicketByBot/{friend_id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'pushTicketByBot'])->summary('企微群@机器人触发工单推送')->name('tickets.pushTicketByBot'); 96 Route::get('/pushTicketByBot/{friend_id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'pushTicketByBot'])->summary('企微群@机器人触发工单推送')->name('tickets.pushTicketByBot');
  97 +//保存工单提交数据(产品,新闻,博客)详情
  98 +Route::prefix('ticket_upload')->group(function () {
  99 + Route::any('/', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'lists'])->name('ticket_upload.lists');
  100 + Route::any('/info', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'info'])->name('ticket_upload.info');
  101 + Route::any('/save', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'save'])->name('ticket_upload.save');
  102 + Route::any('/getProductCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getProductCate'])->name('ticket_upload.getProductCate');
  103 + Route::any('/getBlogCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getBlogCate'])->name('ticket_upload.getBlogCate');
  104 + Route::any('/getNewsCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getNewsCate'])->name('ticket_upload.getNewsCate');
  105 +});
  106 +
@@ -644,6 +644,12 @@ Route::middleware(['aloginauth'])->group(function () { @@ -644,6 +644,12 @@ Route::middleware(['aloginauth'])->group(function () {
644 Route::any('/monthManageList', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'monthManageList'])->name('ticket_count_monthManageList');//月统计数据 644 Route::any('/monthManageList', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'monthManageList'])->name('ticket_count_monthManageList');//月统计数据
645 Route::any('/manageTicketCount', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'manageTicketCount'])->name('ticket_count_manageTicketCount'); 645 Route::any('/manageTicketCount', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'manageTicketCount'])->name('ticket_count_manageTicketCount');
646 }); 646 });
  647 + //ticket
  648 + Route::prefix('ticket_upload')->group(function () {
  649 + Route::any('/', [Aside\Ticket\TicketUploadDataController::class,'lists'])->name('ticket_upload_lists');
  650 + Route::any('/save', [Aside\Ticket\TicketUploadDataController::class,'save'])->name('ticket_upload_save');
  651 + Route::any('/detail', [Aside\Ticket\TicketUploadDataController::class,'detail'])->name('ticket_upload_detail');
  652 + });
647 }); 653 });
648 654
649 //无需登录验证的路由组 655 //无需登录验证的路由组