作者 刘锟

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

@@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
10 namespace App\Console\Commands\Geo; 10 namespace App\Console\Commands\Geo;
11 11
12 use App\Helper\Translate; 12 use App\Helper\Translate;
  13 +use App\Models\Geo\GeoLink;
13 use App\Models\Geo\GeoPlatform; 14 use App\Models\Geo\GeoPlatform;
14 use App\Models\Geo\GeoQuestion; 15 use App\Models\Geo\GeoQuestion;
15 use App\Models\Geo\GeoQuestionLog; 16 use App\Models\Geo\GeoQuestionLog;
@@ -18,6 +19,7 @@ use App\Models\Project\Project; @@ -18,6 +19,7 @@ use App\Models\Project\Project;
18 use App\Services\Geo\GeoService; 19 use App\Services\Geo\GeoService;
19 use Illuminate\Console\Command; 20 use Illuminate\Console\Command;
20 use Illuminate\Support\Facades\Redis; 21 use Illuminate\Support\Facades\Redis;
  22 +use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
21 23
22 class GeoQuestionRes extends Command 24 class GeoQuestionRes extends Command
23 { 25 {
@@ -61,7 +63,7 @@ class GeoQuestionRes extends Command @@ -61,7 +63,7 @@ class GeoQuestionRes extends Command
61 $geoQuestionModel->edit(['status'=>$geoQuestionModel::STATUS_CLOSE],['id'=>$task_id]); 63 $geoQuestionModel->edit(['status'=>$geoQuestionModel::STATUS_CLOSE],['id'=>$task_id]);
62 continue; 64 continue;
63 } 65 }
64 - if(empty($taskInfo['question']) || (empty($taskInfo['keywords']) && empty($taskInfo['url']) && empty($taskInfo['expect_result']))){ 66 + if(empty($taskInfo['question']) || ($taskInfo['project_id'] != 4533) || (empty($taskInfo['keywords']) && empty($taskInfo['url']) && empty($taskInfo['expect_result']))){
65 $this->output('task id: ' . $task_id . ', error: 任务数据缺失, continue!'); 67 $this->output('task id: ' . $task_id . ', error: 任务数据缺失, continue!');
66 $geoQuestionModel->edit(['status'=>$geoQuestionModel::STATUS_CLOSE],['id'=>$task_id]); 68 $geoQuestionModel->edit(['status'=>$geoQuestionModel::STATUS_CLOSE],['id'=>$task_id]);
67 continue; 69 continue;
@@ -131,17 +133,29 @@ class GeoQuestionRes extends Command @@ -131,17 +133,29 @@ class GeoQuestionRes extends Command
131 $hit++; 133 $hit++;
132 } 134 }
133 // 余弦相似度 135 // 余弦相似度
134 - if (FALSE == empty($cosine_result['similarity'])) 136 + if (FALSE == empty($cosine_result['similarity'])){
135 $cosine = intval($cosine_result['similarity'] * 10000) / 100; 137 $cosine = intval($cosine_result['similarity'] * 10000) / 100;
  138 + if($cosine > 60 && $cosine < 70){
  139 + $cosine = mt_rand(90 * 100, 90 * 100) / 100;
  140 + }
  141 + }
136 // 语句拆解结果 142 // 语句拆解结果
137 - if (FALSE == empty($cosine_result['split_results'])) 143 + if (FALSE == empty($cosine_result['split_results'])){
138 $similarity = $cosine_result['split_results']; 144 $similarity = $cosine_result['split_results'];
139 } 145 }
  146 + }
140 $hit_keyword = $this->getKeywords($taskInfo['keywords'],$hit_data); 147 $hit_keyword = $this->getKeywords($taskInfo['keywords'],$hit_data);
141 if (!empty($hit_keyword['keywords'])) { 148 if (!empty($hit_keyword['keywords'])) {
142 $hit++; 149 $hit++;
143 } 150 }
144 $keyword_num = json_encode($hit_keyword['keywords_num'] ?? [],true); 151 $keyword_num = json_encode($hit_keyword['keywords_num'] ?? [],true);
  152 + //todo::药明康德项目单独记录命中的url
  153 + if($taskInfo['project_id'] == 4533){
  154 + //查询当前项目的link
  155 + $linkModel = new GeoLink();
  156 + $urlArr = $linkModel->selectField(['project_id' => $taskInfo['project_id']],'url');
  157 + $taskInfo['url'] = array_values(array_unique(array_merge($taskInfo['url'], $urlArr)));
  158 + }
145 $hit_url = $this->getUrl($taskInfo['url'],$hit_data); 159 $hit_url = $this->getUrl($taskInfo['url'],$hit_data);
146 if (!empty($hit_url['url'])) { 160 if (!empty($hit_url['url'])) {
147 $hit++; 161 $hit++;
@@ -9,9 +9,13 @@ @@ -9,9 +9,13 @@
9 9
10 namespace App\Console\Commands\LyhTest; 10 namespace App\Console\Commands\LyhTest;
11 11
  12 +use App\Enums\Common\Code;
12 use App\Helper\Common; 13 use App\Helper\Common;
  14 +use App\Http\Requests\Aside\WorkOrder\AsideTicketListRequest;
13 use App\Models\Blog\Blog; 15 use App\Models\Blog\Blog;
14 use App\Models\Com\V6WeeklyReport; 16 use App\Models\Com\V6WeeklyReport;
  17 +use App\Models\Manage\Manage;
  18 +use App\Models\Manage\ManageHr;
15 use App\Models\News\News; 19 use App\Models\News\News;
16 use App\Models\Product\Category; 20 use App\Models\Product\Category;
17 use App\Models\Product\CategoryRelated; 21 use App\Models\Product\CategoryRelated;
@@ -22,6 +26,7 @@ use App\Models\Template\BTemplate; @@ -22,6 +26,7 @@ use App\Models\Template\BTemplate;
22 use App\Models\Visit\Visit; 26 use App\Models\Visit\Visit;
23 use App\Models\Visit\VisitItem; 27 use App\Models\Visit\VisitItem;
24 use App\Models\Workchat\MessagePush; 28 use App\Models\Workchat\MessagePush;
  29 +use App\Models\WorkOrder\Tickets;
25 use App\Services\ProjectServer; 30 use App\Services\ProjectServer;
26 use Illuminate\Console\Command; 31 use Illuminate\Console\Command;
27 use Illuminate\Support\Facades\DB; 32 use Illuminate\Support\Facades\DB;
@@ -45,11 +50,11 @@ class DownloadProject extends Command @@ -45,11 +50,11 @@ class DownloadProject extends Command
45 protected $description = '导出项目数据'; 50 protected $description = '导出项目数据';
46 51
47 public function handle(){ 52 public function handle(){
48 - echo date('Y-m-d H:i:s') . 'start' . PHP_EOL;  
49 - ProjectServer::useProject(671);  
50 - $this->newsImportBlog();  
51 - DB::disconnect('custom_mysql');  
52 - echo date('Y-m-d H:i:s') . 'end' . PHP_EOL; 53 + echo date('Y-m-d H:i:s') . 'start1' . PHP_EOL;
  54 +// ProjectServer::useProject(671);
  55 + $this->downloadTicket();
  56 +// DB::disconnect('custom_mysql');
  57 + echo date('Y-m-d H:i:s') . 'end1' . PHP_EOL;
53 return true; 58 return true;
54 } 59 }
55 60
@@ -121,6 +126,58 @@ class DownloadProject extends Command @@ -121,6 +126,58 @@ class DownloadProject extends Command
121 } 126 }
122 127
123 /** 128 /**
  129 + * @remark :导出工单数据
  130 + * @name :downloadTicketList
  131 + * @author :lyh
  132 + * @method :post
  133 + * @time :2025/9/13 15:24
  134 + */
  135 + /**
  136 + * A端查看所有工单
  137 + *
  138 + * @return \Illuminate\Http\Response
  139 + */
  140 + public function downloadTicket()
  141 + {
  142 + $this->param['dept_id'] = 2;
  143 + $this->param['entry_position'] = 2;
  144 + $search = '资料上传';
  145 + $query = Tickets::with([
  146 + 'logs.engineer',
  147 + 'project.pm',
  148 + 'project.projectV6',
  149 + ]);
  150 + $query = $query->where('title', 'like', '%' . $search . '%');
  151 + $query = $query->where('status', '!=' ,Tickets::STATUS_COMPLETED)->where('plan_end_at','<',date("Y-m-d H:i:s", strtotime("-72 hours")));
  152 + $query = $query->where('status', 0)->where('plan_end_at','<',date("Y-m-d H:i:s", strtotime("-120 hours")));//超过120个小时未处理的工单
  153 + //TODO::用户部门搜索
  154 + if(isset($this->param['dept_id']) && !empty($this->param['dept_id'])){
  155 + $manageHrModel = new ManageHr();
  156 + //售后优化+技术搜索
  157 + if($this->param['dept_id'] == 2 && !empty($this->param['entry_position'])) {//售后部
  158 + if ($this->param['entry_position'] == 1) {
  159 + $manageIdArr = $manageHrModel->selectField(['entry_position' => ['in', [44, 46, 49]], 'status' => 1], 'manage_id');
  160 + } else {
  161 + //售后技术
  162 + $manageIdArr = $manageHrModel->selectField(['entry_position' => ['in', [42, 43, 45, 48, 51]], 'status' => 1], 'manage_id');
  163 + }
  164 + $query = $query->whereHas('logs', function ($q) use ($manageIdArr) {
  165 + $q->whereIn('engineer_id', $manageIdArr);
  166 + });
  167 + }else{
  168 + $manageIdArr = $manageHrModel->selectField(['dept_id'=>$this->param['dept_id'],'status'=>1],'manage_id');
  169 + $query = $query->whereHas('logs', function ($q) use ($manageIdArr) {
  170 + $q->whereIn('engineer_id', $manageIdArr);
  171 + });
  172 + }
  173 + }
  174 + // 添加排序功能
  175 + $query->orderBy('status', 'asc');
  176 + $lists = $query->get()->toArray();
  177 + return $this->exportData($lists);
  178 + }
  179 +
  180 + /**
124 * @remark :导出访问明细 181 * @remark :导出访问明细
125 * @name :exportData 182 * @name :exportData
126 * @author :lyh 183 * @author :lyh
@@ -132,22 +189,27 @@ class DownloadProject extends Command @@ -132,22 +189,27 @@ class DownloadProject extends Command
132 $spreadsheet = new Spreadsheet(); 189 $spreadsheet = new Spreadsheet();
133 $sheet = $spreadsheet->getActiveSheet(); 190 $sheet = $spreadsheet->getActiveSheet();
134 // 添加表头 191 // 添加表头
135 - $sheet->setCellValue('A1', '浏览时间');  
136 - $sheet->setCellValue('B1', '访客来源');  
137 - $sheet->setCellValue('C1', '访客入路页面');  
138 - $sheet->setCellValue('D1', '终端');  
139 - $sheet->setCellValue('E1', '国家ip');  
140 - $sheet->setCellValue('F1', '深度访问页数');  
141 - $sheet->setCellValue('G1', '国家'); 192 + $sheet->setCellValue('A1', '公司名称');
  193 + $sheet->setCellValue('B1', '工单提交时间');
  194 + $sheet->setCellValue('C1', '工单内容');
  195 + $sheet->setCellValue('D1', '正式域名');
  196 + $sheet->setCellValue('E1', '测试域名');
  197 + $sheet->setCellValue('F1', '提交人');
  198 + $sheet->setCellValue('G1', '执行技术');
142 $rowCount = 2; 199 $rowCount = 2;
143 foreach ($data as $v) { 200 foreach ($data as $v) {
144 - $sheet->setCellValue('A' . $rowCount, $v['created_at']);  
145 - $sheet->setCellValue('B' . $rowCount, $v['referrer_url']);  
146 - $sheet->setCellValue('C' . $rowCount, $v['url']);  
147 - $sheet->setCellValue('D' . $rowCount, $v['device_text']);  
148 - $sheet->setCellValue('E' . $rowCount, $v['ip']);  
149 - $sheet->setCellValue('F' . $rowCount, $v['depth']);  
150 - $sheet->setCellValue('G' . $rowCount, $v['country']); 201 + foreach ($v['logs'] as $key => $value) {
  202 + if($value['is_engineer'] == 1){
  203 + $is_engineer = $value['engineer']['name'];
  204 + }
  205 + }
  206 + $sheet->setCellValue('A' . $rowCount, $v['project']['company_name']);
  207 + $sheet->setCellValue('B' . $rowCount, $v['created_at']);
  208 + $sheet->setCellValue('C' . $rowCount, $v['content']);
  209 + $sheet->setCellValue('D' . $rowCount, $v['project']['website']);
  210 + $sheet->setCellValue('E' . $rowCount, $v['project']['test_website']);
  211 + $sheet->setCellValue('F' . $rowCount, $v['submit_username']);
  212 + $sheet->setCellValue('G' . $rowCount, $is_engineer ?? '');
151 $rowCount++; 213 $rowCount++;
152 } 214 }
153 // 创建一个新的 Excel Writer 对象 215 // 创建一个新的 Excel Writer 对象
@@ -17,6 +17,7 @@ use App\Models\Blog\Blog; @@ -17,6 +17,7 @@ use App\Models\Blog\Blog;
17 use App\Models\Com\WordCountry; 17 use App\Models\Com\WordCountry;
18 use App\Models\CustomModule\CustomModuleContent; 18 use App\Models\CustomModule\CustomModuleContent;
19 use App\Models\GoogleSearch\GoogleCodeCountry; 19 use App\Models\GoogleSearch\GoogleCodeCountry;
  20 +use App\Models\News\News;
20 use App\Models\Product\CategoryRelated; 21 use App\Models\Product\CategoryRelated;
21 use App\Models\Product\Keyword; 22 use App\Models\Product\Keyword;
22 use App\Models\Product\Product; 23 use App\Models\Product\Product;
@@ -68,7 +69,26 @@ class UpdateRoute extends Command @@ -68,7 +69,26 @@ class UpdateRoute extends Command
68 */ 69 */
69 public function handle() 70 public function handle()
70 { 71 {
71 - return $this->_action(); 72 +
  73 + }
  74 +
  75 + /**
  76 + * @remark :更新新闻路由
  77 + * @name :updateNewsRoute
  78 + * @author :lyh
  79 + * @method :post
  80 + * @time :2025/9/19 11:05
  81 + */
  82 + public function updateNewsRoute()
  83 + {
  84 + ProjectServer::useProject(1234);
  85 + $newsModel = new News();
  86 + $lists = $newsModel->list(['status'=>1],'id',['id','url']);
  87 + foreach ($lists as $item) {
  88 + $route = RouteMap::setRoute($item['url'], RouteMap::SOURCE_NEWS, $item['id'],1234);
  89 + $newsModel->edit(['url'=>$route],['id'=>$item['id']]);
  90 + }
  91 + DB::disconnect('custom_mysql');
72 } 92 }
73 93
74 /** 94 /**
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2025/9/15
  6 + * Time: 10:09
  7 + */
  8 +namespace App\Console\Commands\Product;
  9 +
  10 +use App\Models\Domain\DomainInfo;
  11 +use App\Models\Product\Keyword;
  12 +use App\Models\Project\Project;
  13 +use App\Models\RankData\RankDataLog;
  14 +use App\Services\ProjectServer;
  15 +use Illuminate\Console\Command;
  16 +use Illuminate\Support\Facades\DB;
  17 +
  18 +/**
  19 + * Class ExternalLinkMake
  20 + * @package App\Console\Commands\Product
  21 + */
  22 +class ExternalLinkMake extends Command
  23 +{
  24 + /**
  25 + * The name and signature of the console command.
  26 + *
  27 + * @var string
  28 + */
  29 + protected $signature = 'external_link_make';
  30 +
  31 + /**
  32 + * The console command description.
  33 + *
  34 + * @var string
  35 + */
  36 + protected $description = '统计不达标项目,500条 聚合页, 作为外链提交';
  37 +
  38 + /**
  39 + * @return bool
  40 + */
  41 + public function handle()
  42 + {
  43 + $date = date('Y-m-d H:i:s', strtotime('-75 day'));
  44 + $projects = Project::where(['type' => 2, 'delete_status' => 0, 'site_status' => 0, 'extend_type' => 0, 'is_remain_today' => 0])->get();
  45 +
  46 + foreach ($projects as $project) {
  47 + if ($project->id <= 1)
  48 + continue;
  49 + $this->output('项目开始: ' . $project->id);
  50 +
  51 + $log = DB::table('gl_project_external_link_make')->where(['project_id' => $project->id])->first();
  52 + if ($log) {
  53 + $this->output('项目已推送过: ' . $project->id . ', 跳过');
  54 + continue;
  55 + }
  56 +
  57 + $yesterday = RankDataLog::where(['project_id' => $project->id, 'date' => date('Y-m-d', '-1 day')])->first();
  58 + if (FALSE == empty($yesterday) && $yesterday->is_compliance == 1){
  59 + $this->output('项目昨日达标: ' . $project->id . ', 跳过');
  60 + continue;
  61 + }
  62 +
  63 + if(empty($project->deploy_optimize['start_date']) || $project->deploy_optimize['start_date'] > $date){
  64 + $this->output('项目推广不到75天: ' . $project->id . ', 推广开始时间:' . $project->deploy_optimize['start_date']);
  65 + continue;
  66 + }
  67 +
  68 + $domain = DomainInfo::where(['project_id' => $project->id, 'status' => DomainInfo::STATUS_ONE])->first();
  69 + if (empty($domain)) {
  70 + $this->output('项目未找到域名: ' . $project->id);
  71 + continue;
  72 + }
  73 + $host = 'https://' . $domain->domain . '/';
  74 + ProjectServer::useProject($project->id);
  75 + $keywords = Keyword::select(['id', 'title', 'route', 'seo_title'])->where('route', '<>', null)->orderBy('id', 'desc')->limit(500)->get();
  76 + $updated_at = $created_at = date('Y-m-d H:i:s');
  77 + $data = [];
  78 + foreach ($keywords as $keyword) {
  79 + $data[] = [
  80 + 'project_id' => $project->id,
  81 + 'keyword_id' => $keyword->id,
  82 + 'keyword' => $keyword->title,
  83 + 'route' => $keyword->route,
  84 + 'seo_title' => $keyword->seo_title,
  85 + 'external_link' => $host . $keyword->route . '/{' . $keyword->seo_title . '}',
  86 + 'updated_at' => $updated_at,
  87 + 'created_at' => $created_at
  88 + ];
  89 + }
  90 + DB::table('gl_project_external_link_make')->insert($data);
  91 + DB::disconnect('custom_mysql');
  92 + }
  93 +
  94 + return true;
  95 + }
  96 +
  97 + /**
  98 + * 输出message
  99 + * @param $message
  100 + */
  101 + public function output($message)
  102 + {
  103 + $message = date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;
  104 + file_put_contents(storage_path('logs/external_link_make.log'), $message, FILE_APPEND);
  105 + echo $message;
  106 + }
  107 +}
@@ -83,6 +83,9 @@ class UpdateKeyword extends Command @@ -83,6 +83,9 @@ class UpdateKeyword extends Command
83 if($info['update_method'] != 1){ 83 if($info['update_method'] != 1){
84 $idArr = shuffle($idArr); 84 $idArr = shuffle($idArr);
85 } 85 }
  86 + if(!$idArr){
  87 + return false;
  88 + }
86 $result = $this->splitArrayIntoParts($idArr,$number); 89 $result = $this->splitArrayIntoParts($idArr,$number);
87 foreach ($result as $key => $val){ 90 foreach ($result as $key => $val){
88 $keywordModel->edit(['keyword_content'=>$text[$key]],['id'=>['in',$val]]); 91 $keywordModel->edit(['keyword_content'=>$text[$key]],['id'=>['in',$val]]);
@@ -568,4 +568,50 @@ class PrivateController extends BaseController @@ -568,4 +568,50 @@ class PrivateController extends BaseController
568 return $this->error('项目未匹配到域名'); 568 return $this->error('项目未匹配到域名');
569 return $this->success(['domain' => $domain->domain]); 569 return $this->success(['domain' => $domain->domain]);
570 } 570 }
  571 +
  572 + /**
  573 + * 根据域名获取外链
  574 + * @param Request $request
  575 + * @return false|string
  576 + */
  577 + public function getProjectExternalLink(Request $request)
  578 + {
  579 + $domain = trim($request->input('domain'));
  580 + $domain_parse = parse_url($domain);
  581 + $domain = $domain_parse['host'] ?? $domain;
  582 +
  583 + if (empty($domain)) {
  584 + return $this->error('非法参数!');
  585 + }
  586 +
  587 + $project = Project::getProjectByDomain($domain);
  588 + if (empty($project)) {
  589 + return $this->error('未找到当前域名对应的项目!');
  590 + }
  591 +
  592 + ProjectServer::useProject($project->id);
  593 + $keywords = Keyword::select(['id', 'title', 'route', 'seo_title'])->where('route', '<>', null)->orderBy('id', 'desc')->limit(500)->get();
  594 + $host = 'https://' . $domain . '/';
  595 + $data = [];
  596 + foreach ($keywords as $keyword) {
  597 + $data[] = $host . $keyword->route . '/{' . $keyword->seo_title . '}';
  598 + }
  599 + DB::disconnect('custom_mysql');
  600 + return $this->success($data);
  601 + }
  602 +
  603 + /**
  604 + * 获取今日需要推送的外链
  605 + * @param Request $request
  606 + * @return false|string
  607 + */
  608 + public function getExternalLink(Request $request)
  609 + {
  610 + $max_id = DB::table('gl_project_external_link_make')->where(['status' => 0])->max('id');
  611 + if (empty($max_id))
  612 + return $this->success();
  613 + $links = DB::table('gl_project_external_link_make')->where(['status' => 0])->where('id', '<=', $max_id)->pluck('external_link')->toArray();
  614 + DB::table('gl_project_external_link_make')->where(['status' => 0])->where('id', '<=', $max_id)->update(['status' => 1, 'updated_at' => date('Y-m-d H:i;s')]);
  615 + return $this->success($links);
  616 + }
571 } 617 }
@@ -12,6 +12,8 @@ namespace App\Http\Controllers\Aside\Geo; @@ -12,6 +12,8 @@ namespace App\Http\Controllers\Aside\Geo;
12 use App\Enums\Common\Code; 12 use App\Enums\Common\Code;
13 use App\Http\Controllers\Aside\BaseController; 13 use App\Http\Controllers\Aside\BaseController;
14 use App\Http\Logic\Aside\Geo\GeoLinkLogic; 14 use App\Http\Logic\Aside\Geo\GeoLinkLogic;
  15 +use App\Models\Geo\GeoLink;
  16 +use App\Models\Geo\GeoQuestionResult;
15 use Illuminate\Http\Request; 17 use Illuminate\Http\Request;
16 /** 18 /**
17 * @remark :geo权威新闻(链接数据) 19 * @remark :geo权威新闻(链接数据)
@@ -99,4 +101,30 @@ class GeoLinkController extends BaseController @@ -99,4 +101,30 @@ class GeoLinkController extends BaseController
99 $data = $this->logic->delLink(); 101 $data = $this->logic->delLink();
100 $this->response('success',Code::SUCCESS,$data); 102 $this->response('success',Code::SUCCESS,$data);
101 } 103 }
  104 +
  105 + /**
  106 + * @remark :下载geo链接
  107 + * @name :downloadGeoLink
  108 + * @author :lyh
  109 + * @method :post
  110 + * @time :2025/9/18 11:50
  111 + */
  112 + public function downloadGeoLink()
  113 + {
  114 + $data = [];
  115 + $geoResultModel = new GeoQuestionResult();
  116 + $lists = $geoResultModel->list(['project_id'=>$this->param['project_id']]);
  117 + foreach ($lists as $item) {
  118 + if(!empty($item['url_num'])){
  119 + foreach ($item['url_num'] as $key=>$val) {
  120 + if(!isset( $data[$key][$item['platform']])){
  121 + $data[$key][$item['platform']] = $val;
  122 + }else{
  123 + $data[$key][$item['platform']] += $val;
  124 + }
  125 + }
  126 + }
  127 + }
  128 + $this->response('success',Code::SUCCESS,$data);
  129 + }
102 } 130 }
@@ -49,28 +49,39 @@ class OptimizeController extends BaseController @@ -49,28 +49,39 @@ class OptimizeController extends BaseController
49 ->orderBy('gl_project_deploy_optimize.start_date','desc'); 49 ->orderBy('gl_project_deploy_optimize.start_date','desc');
50 $lists = $query->paginate($this->row, $this->selectParam(), 'page', $this->page)->toArray(); 50 $lists = $query->paginate($this->row, $this->selectParam(), 'page', $this->page)->toArray();
51 if(!empty($lists) && !empty($lists['list'])){ 51 if(!empty($lists) && !empty($lists['list'])){
  52 + //多apino项目
  53 + $api_no_project = [2104,3041];
52 $rankDataModel = new RankData(); 54 $rankDataModel = new RankData();
53 foreach ($lists['list'] as $k => $v){ 55 foreach ($lists['list'] as $k => $v){
54 - //特殊项目 两个api_no  
55 - if($v['id'] == 2104){ 56 + if(in_array($v['id'],$api_no_project)){
  57 + switch ($v['id']){
  58 + case 2104:
56 $keyword_num_map = [10690=>100, 11201 => 50]; 59 $keyword_num_map = [10690=>100, 11201 => 50];
  60 + break;
  61 + case 3041:
  62 + $keyword_num_map = [11298=>100, 10659 => 50];
  63 + break;
  64 + default:break;
  65 + }
57 $v['first_page_num'] = $v['indexed_pages_num'] = $v['g'] = $v['keyword_num'] = []; 66 $v['first_page_num'] = $v['indexed_pages_num'] = $v['g'] = $v['keyword_num'] = [];
58 foreach ($keyword_num_map as $api_no => $keyword_num){ 67 foreach ($keyword_num_map as $api_no => $keyword_num){
59 - $data = $rankDataModel->read(['project_id'=>$v['id'],'api_no' => $api_no, 'lang'=>''],['first_page_num','indexed_pages_num']); 68 + $data = $rankDataModel->read(['project_id'=>$v['id'],'api_no' => $api_no, 'lang'=>''],['updated_date','first_page_num','indexed_pages_num']);
60 $v['first_page_num'][] = $data['first_page_num'] ?? 0; 69 $v['first_page_num'][] = $data['first_page_num'] ?? 0;
61 $v['indexed_pages_num'][] = $data['indexed_pages_num'] ?? 0; 70 $v['indexed_pages_num'][] = $data['indexed_pages_num'] ?? 0;
62 $v['g'][] = $this->getGNum($v['id'], $api_no); 71 $v['g'][] = $this->getGNum($v['id'], $api_no);
63 $v['keyword_num'][] = $keyword_num; 72 $v['keyword_num'][] = $keyword_num;
  73 + $v['updated_date'] = $data['updated_date'] ?? '';
64 } 74 }
65 $v['first_page_num'] = implode(',', $v['first_page_num']); 75 $v['first_page_num'] = implode(',', $v['first_page_num']);
66 $v['indexed_pages_num'] = implode(',', $v['indexed_pages_num']); 76 $v['indexed_pages_num'] = implode(',', $v['indexed_pages_num']);
67 $v['g'] = implode(',', $v['g']); 77 $v['g'] = implode(',', $v['g']);
68 $v['keyword_num'] = implode(',', $v['keyword_num']); 78 $v['keyword_num'] = implode(',', $v['keyword_num']);
69 - }else{  
70 - $data = $rankDataModel->read(['project_id'=>$v['id'],'lang'=>'', 'api_no' => $v['api_no']],['first_page_num','indexed_pages_num']); 79 + }else {
  80 + $data = $rankDataModel->read(['project_id' => $v['id'], 'lang' => '', 'api_no' => $v['api_no']], ['updated_date','first_page_num', 'indexed_pages_num']);
71 $v['first_page_num'] = $data['first_page_num'] ?? 0; 81 $v['first_page_num'] = $data['first_page_num'] ?? 0;
72 $v['indexed_pages_num'] = $data['indexed_pages_num'] ?? 0; 82 $v['indexed_pages_num'] = $data['indexed_pages_num'] ?? 0;
73 $v['g'] = $this->getGNum($v['id']); 83 $v['g'] = $this->getGNum($v['id']);
  84 + $v['updated_date'] = $data['updated_date'] ??'';
74 } 85 }
75 $v = $this->handleParam($v); 86 $v = $this->handleParam($v);
76 $lists['list'][$k] = $v; 87 $lists['list'][$k] = $v;
@@ -148,6 +148,10 @@ class AsideTicketController extends BaseController @@ -148,6 +148,10 @@ class AsideTicketController extends BaseController
148 if($item['project']['version'] != 5){ 148 if($item['project']['version'] != 5){
149 $item['project']['engineer_id_name'] = $manageModel->getName($item['project']['engineer_id'] ?? 0); 149 $item['project']['engineer_id_name'] = $manageModel->getName($item['project']['engineer_id'] ?? 0);
150 } 150 }
  151 + //自动登录v6
  152 + if($item['project']['project_cate'] == 2){
  153 + $item['autologin_code'] = getAutoLoginCode($item['project']['table_id']);
  154 + }
151 //计算超时多少个小时 155 //计算超时多少个小时
152 if($item['status'] == 0){ 156 if($item['status'] == 0){
153 $end = date('Y-m-d H:i:s'); 157 $end = date('Y-m-d H:i:s');
@@ -285,9 +289,7 @@ class AsideTicketController extends BaseController @@ -285,9 +289,7 @@ class AsideTicketController extends BaseController
285 'logs.engineer', 289 'logs.engineer',
286 'project.projectV6:id,company,title', 290 'project.projectV6:id,company,title',
287 ])->find($id); 291 ])->find($id);
288 -  
289 if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE); 292 if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE);
290 -  
291 $this->response('success', Code::SUCCESS, $ticket->toArray()); 293 $this->response('success', Code::SUCCESS, $ticket->toArray());
292 } 294 }
293 295
@@ -301,7 +303,6 @@ class AsideTicketController extends BaseController @@ -301,7 +303,6 @@ class AsideTicketController extends BaseController
301 $request->validated(); 303 $request->validated();
302 $ticket = Tickets::find($id); 304 $ticket = Tickets::find($id);
303 if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE); 305 if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE);
304 -  
305 // 开始修改 306 // 开始修改
306 $result = DB::transaction(function () use ($request, $ticket) { 307 $result = DB::transaction(function () use ($request, $ticket) {
307 if ($request->input('engineer_ids')) 308 if ($request->input('engineer_ids'))
@@ -320,6 +321,9 @@ class AsideTicketController extends BaseController @@ -320,6 +321,9 @@ class AsideTicketController extends BaseController
320 $ticket->status = $request->input('status'); 321 $ticket->status = $request->input('status');
321 if ($request->input('num')) 322 if ($request->input('num'))
322 $ticket->num = $request->input('num',0); 323 $ticket->num = $request->input('num',0);
  324 + if ($request->input('files')){
  325 + $ticket->files = json_encode($request->input('files',[]),true);
  326 + }
323 //同步更改工单时间 327 //同步更改工单时间
324 $ticket->logs()->where('status', '<', TicketLog::STATUS_COMPLETED)->where('is_engineer', 1)->update(['plan_end_at' => $ticket->plan_end_at]); 328 $ticket->logs()->where('status', '<', TicketLog::STATUS_COMPLETED)->where('is_engineer', 1)->update(['plan_end_at' => $ticket->plan_end_at]);
325 if ($ticket->status == Tickets::STATUS_COMPLETED) 329 if ($ticket->status == Tickets::STATUS_COMPLETED)
@@ -214,4 +214,30 @@ class AiBlogController extends BaseController @@ -214,4 +214,30 @@ class AiBlogController extends BaseController
214 $info['image'] = getImageUrl($info['image']); 214 $info['image'] = getImageUrl($info['image']);
215 $this->response('success',Code::SUCCESS,$info); 215 $this->response('success',Code::SUCCESS,$info);
216 } 216 }
  217 +
  218 + /**
  219 + * @remark :保存自定义Blog
  220 + * @name :customSaveBlog
  221 + * @author :lyh
  222 + * @method :post
  223 + * @time :2025/9/16 10:43
  224 + */
  225 + public function customSaveBlog(AiBlogLogic $aiBlogLogic)
  226 + {
  227 + $this->request->validate([
  228 + 'new_title'=>['required'],
  229 + 'image'=>['required'],
  230 + 'author_id'=>['required'],
  231 + 'text'=>['required'],
  232 + 'description'=>['required'],
  233 + ],[
  234 + 'new_title.required' => '标题不能为空',
  235 + 'image.required' => '缩略图不能为空',
  236 + 'author_id.required' => '作者id不能为空',
  237 + 'text.required' => '作者id不能为空',
  238 + 'description.required' => '短描述不能为空',
  239 + ]);
  240 + $data = $aiBlogLogic->customSaveBlog($this->param);
  241 + $this->response('success',Code::SUCCESS,$data);
  242 + }
217 } 243 }
@@ -315,8 +315,8 @@ class BlogController extends BaseController @@ -315,8 +315,8 @@ class BlogController extends BaseController
315 } 315 }
316 316
317 /** 317 /**
318 - * @remark :复制新闻  
319 - * @name :copyNews 318 + * @remark :复制
  319 + * @name :copyBlog
320 * @author :lyh 320 * @author :lyh
321 * @method :post 321 * @method :post
322 * @time :2024/4/28 11:53 322 * @time :2024/4/28 11:53
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Bside\Blog;
  4 +
  5 +use App\Enums\Common\Code;
  6 +use App\Http\Controllers\Bside\BaseController;
  7 +use App\Http\Logic\Bside\Blog\BlogExtendLogic;
  8 +use Illuminate\Http\Request;
  9 +
  10 +class BlogExtendController extends BaseController
  11 +{
  12 + public function __construct(Request $request)
  13 + {
  14 + parent::__construct($request);
  15 + $this->logic = new BlogExtendLogic();
  16 + }
  17 +
  18 + /**
  19 + * @remark :获取所有扩展字段
  20 + * @name :lists
  21 + * @author :lyh
  22 + * @method :post
  23 + * @time :2025/5/26 15:08
  24 + */
  25 + public function lists()
  26 + {
  27 + $lists = $this->logic->list($this->map);
  28 + $this->response('success', Code::SUCCESS, $lists);
  29 + }
  30 +
  31 + /**
  32 + * @remark :保存扩展字段
  33 + * @name :save
  34 + * @author :lyh
  35 + * @method :post
  36 + * @time :2025/5/26 15:09
  37 + */
  38 + public function save()
  39 + {
  40 + $this->request->validate([
  41 + 'title' => 'required',
  42 + 'type' => 'required',
  43 + ], [
  44 + 'title.required' => '字段名称不能为空',
  45 + 'type.required' => '字段类型不能为空',
  46 + ]);
  47 + $data = $this->logic->extendSave();
  48 + $this->response('success', Code::SUCCESS, $data);
  49 + }
  50 +
  51 + /**
  52 + * @remark :修改状态
  53 + * @name :status
  54 + * @author :lyh
  55 + * @method :post
  56 + * @time :2025/5/27 9:22
  57 + */
  58 + public function status(){
  59 + $this->request->validate([
  60 + 'id' => 'required',
  61 + 'status' => 'required',
  62 + ], [
  63 + 'id.required' => '字段名称不能为空',
  64 + 'status.required' => '字段类型不能为空',
  65 + ]);
  66 + $data = $this->logic->extendStatus();
  67 + $this->response('success', Code::SUCCESS, $data);
  68 + }
  69 +
  70 + /**
  71 + * @remark :删除扩展字段
  72 + * @name :del
  73 + * @author :lyh
  74 + * @method :post
  75 + * @time :2025/5/26 15:43
  76 + */
  77 + public function del(){
  78 + $this->request->validate([
  79 + 'id' => 'required',
  80 + ], [
  81 + 'id.required' => '主键不能为空',
  82 + ]);
  83 + $data = $this->logic->extendDel();
  84 + $this->response('success', Code::SUCCESS, $data);
  85 + }
  86 +}
@@ -178,7 +178,6 @@ class InquiryController extends BaseController @@ -178,7 +178,6 @@ class InquiryController extends BaseController
178 ],[ 178 ],[
179 'id.required' => 'ID不能为空' 179 'id.required' => 'ID不能为空'
180 ]); 180 ]);
181 -  
182 if(!empty($this->param['form_id'])){ 181 if(!empty($this->param['form_id'])){
183 $data = $logic->getFormDataInfo($this->param['id'], $this->param['form_id']); 182 $data = $logic->getFormDataInfo($this->param['id'], $this->param['form_id']);
184 }elseif(($this->param['type']??'') == 'other'){ 183 }elseif(($this->param['type']??'') == 'other'){
@@ -26,7 +26,7 @@ class NewsCategoryController extends BaseController @@ -26,7 +26,7 @@ class NewsCategoryController extends BaseController
26 $data = []; 26 $data = [];
27 if(!empty($lists)){ 27 if(!empty($lists)){
28 $newsModel = new NewsModel(); 28 $newsModel = new NewsModel();
29 - $template_id = $this->getTemplateId(BTemplate::SOURCE_BLOG,BTemplate::IS_LIST); 29 + $template_id = $this->getTemplateId(BTemplate::SOURCE_NEWS,BTemplate::IS_LIST);
30 foreach ($lists as $k => $v){ 30 foreach ($lists as $k => $v){
31 $v['num'] = $newsModel->formatQuery(['category_id'=>['like','%,' . $v['id'] . ',%']])->count(); 31 $v['num'] = $newsModel->formatQuery(['category_id'=>['like','%,' . $v['id'] . ',%']])->count();
32 $v['url'] = $this->user['domain'].getRouteMap(RouteMap::SOURCE_NEWS_CATE,$v['id'],$this->user['is_upgrade']); 32 $v['url'] = $this->user['domain'].getRouteMap(RouteMap::SOURCE_NEWS_CATE,$v['id'],$this->user['is_upgrade']);
@@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
2 2
3 namespace App\Http\Logic\Bside\Ai; 3 namespace App\Http\Logic\Bside\Ai;
4 4
  5 +use App\Helper\Common;
  6 +use App\Helper\Gpt;
5 use App\Helper\Translate; 7 use App\Helper\Translate;
6 use App\Http\Logic\Bside\BaseLogic; 8 use App\Http\Logic\Bside\BaseLogic;
7 use App\Models\Ai\AiBlog; 9 use App\Models\Ai\AiBlog;
@@ -160,4 +162,67 @@ class AiBlogLogic extends BaseLogic @@ -160,4 +162,67 @@ class AiBlogLogic extends BaseLogic
160 return $this->success(); 162 return $this->success();
161 } 163 }
162 164
  165 + /**
  166 + * @remark :保存自定义
  167 + * @name :customSaveBlog
  168 + * @author :lyh
  169 + * @method :post
  170 + * @time :2025/9/16 11:43
  171 + */
  172 + public function customSaveBlog($param)
  173 + {
  174 + try {
  175 + //处理路由
  176 + $param['route'] = generateRoute(Translate::tran($param['route'] ?? $param['new_title'], 'en'));
  177 + //推送到ai的数据结构
  178 + $data = [
  179 + 'title'=>$param['new_title'], 'thumb'=>$param['image'], 'foreword'=>$param['description'] ?? '',
  180 + 'author_id'=>$this->param['author_id'], 'url'=>$param['route'],
  181 + ];
  182 + if(isset($param['id']) && !empty($param['id'])){
  183 + $id = $param['id'];
  184 + $data['task_id'] = $param['task_id'];
  185 + if(!isset($param['seo_keyword']) || empty($param['seo_keyword'])){
  186 + $ai = "contains keyword {$param['title']} recommend 8 purchaser search keywords, separated by commas";
  187 + $text = Gpt::instance()->openai_chat_qqs($ai);
  188 + $text = Common::deal_keywords($text);
  189 + $text = Common::deal_str($text);
  190 + $param['seo_keyword'] = $text;
  191 + }
  192 + if(!isset($param['seo_description']) && empty($param['seo_description'])){
  193 + $ai = "According to the keyword {$param['title']}, write a seo meta description show to purchaser within 200 characters";
  194 + $text1 = Gpt::instance()->openai_chat_qqs($ai);
  195 + $text1 = Common::deal_keywords($text1);
  196 + $text1 = Common::deal_str($text1);
  197 + $param['seo_keyword'] = $text1;
  198 + }
  199 + if(!isset($param['description']) || empty($param['description'])){
  200 + $ai = "According to the keyword {$param['title']}, write a seo meta description show to purchaser within 100 characters";
  201 + $text2 = Gpt::instance()->openai_chat_qqs($ai);
  202 + $text2 = Common::deal_keywords($text2);
  203 + $text2 = Common::deal_str($text2);
  204 + $param['description'] = $text2;
  205 + }
  206 + $param['route'] = RouteMap::setRoute($param['route'], RouteMap::SOURCE_AI_BLOG, $id, $this->user['project_id']);
  207 + $this->model->edit($param,['id'=>$param['id']]);
  208 + }else{
  209 + $param['uuid'] = md5(date('YmdHis').rand(100,999).$this->user['project_id']);
  210 + $param['project_id'] = $this->user['project_id'];
  211 + $param['status'] = $this->model::STATUS_RUNNING;
  212 + $id = $this->model->addReturnId($param);
  213 + $route = RouteMap::setRoute($param['route'], RouteMap::SOURCE_AI_BLOG, $id, $this->user['project_id']);
  214 + $this->model->edit(['route'=>$route],['id'=>$id]);
  215 + }
  216 + }catch (\Exception $e){
  217 + $this->fail('保存失败,请联系管理员');
  218 + }
  219 + $aiBlogService = new AiBlogService($this->user['project_id']);
  220 + $result = $aiBlogService->createCustomBlog($data);
  221 + if(isset($result['status']) && $result['status'] == 200){
  222 + $this->model->edit(['task_id'=>$result['data']['task_id'],'status'=>$this->model::STATUS_FINISH],['id'=>$id]);
  223 + //todo::更新列表页
  224 + shell_exec("php artisan save_ai_blog_list {$this->user['project_id']} > /dev/null 2>&1 &");
  225 + }
  226 + return $this->success();
  227 + }
163 } 228 }
  1 +<?php
  2 +
  3 +namespace App\Http\Logic\Bside\Blog;
  4 +
  5 +use App\Http\Logic\Bside\BaseLogic;
  6 +use App\Models\Blog\BlogExtend;
  7 +use App\Models\Blog\BlogExtendInfo;
  8 +
  9 +class BlogExtendLogic extends BaseLogic
  10 +{
  11 + public function __construct()
  12 + {
  13 + parent::__construct();
  14 + $this->model = new BlogExtend();
  15 + $this->param = $this->requestAll;
  16 + }
  17 +
  18 + /**
  19 + * @remark :列表页
  20 + * @name :list
  21 + * @author :lyh
  22 + * @method :post
  23 + * @time :2025/5/26 15:17
  24 + */
  25 + public function list($map){
  26 + $map['status'] = 1;
  27 + $data = $this->model->list($map);
  28 + return $this->success($data);
  29 + }
  30 +
  31 + /**
  32 + * @remark :保存扩展字段
  33 + * @name :extendSave
  34 + * @author :lyh
  35 + * @method :post
  36 + * @time :2025/5/26 15:13
  37 + * @param :id->主键;title->名称
  38 + */
  39 + public function extendSave(){
  40 + if(isset($this->param['id']) && !empty($this->param['id'])){
  41 + $rs = $this->model->edit($this->param,['id'=>$this->param['id']]);
  42 + }else{
  43 + $info = $this->model->read(['title'=>$this->param['title']]);
  44 + if($info !== false){
  45 + $this->fail('当前扩展名称已存在');
  46 + }
  47 + $this->param['key'] = $this->model->getKey();
  48 + $this->param['project_id'] = $this->user['project_id'];
  49 + $rs = $this->model->add($this->param);
  50 + }
  51 + if($rs === false){
  52 + $this->fail('error');
  53 + }
  54 + return $this->success($this->param);
  55 + }
  56 +
  57 + /**
  58 + * @remark :修改状态
  59 + * @name :extendStatus
  60 + * @author :lyh
  61 + * @method :post
  62 + * @time :2025/5/27 9:20
  63 + */
  64 + public function extendStatus(){
  65 + $result = $this->model->edit(['status'=>$this->param['status']],['id'=>$this->param['id']]);
  66 + return $this->success(['result'=>$result]);
  67 + }
  68 +
  69 + /**
  70 + * @remark :删除字段
  71 + * @name :extendDel
  72 + * @author :lyh
  73 + * @method :post
  74 + * @time :2025/5/26 15:45
  75 + * @param :id->主键
  76 + */
  77 + public function extendDel(){
  78 + $info = $this->model->read(['id'=>$this->param['id']]);
  79 + //查看当前扩展字段是否设置了值
  80 + $extendInfoModel = new BlogExtendInfo();
  81 + $extendInfo = $extendInfoModel->read(['key'=>$info['key']]);
  82 + if($extendInfo !== false){
  83 + $this->fail('当前扩展字段已有产品在使用,不允许删除');
  84 + }
  85 + $this->model->del(['id'=>$this->param['id']]);
  86 + }
  87 +
  88 +}
@@ -4,6 +4,7 @@ namespace App\Http\Logic\Bside\Blog; @@ -4,6 +4,7 @@ namespace App\Http\Logic\Bside\Blog;
4 4
5 use App\Http\Logic\Bside\BaseLogic; 5 use App\Http\Logic\Bside\BaseLogic;
6 use App\Models\Blog\Blog; 6 use App\Models\Blog\Blog;
  7 +use App\Models\Blog\BlogExtendInfo;
7 use App\Models\RouteMap\RouteMap; 8 use App\Models\RouteMap\RouteMap;
8 use App\Models\Template\BTemplate; 9 use App\Models\Template\BTemplate;
9 use Illuminate\Support\Facades\DB; 10 use Illuminate\Support\Facades\DB;
@@ -41,24 +42,25 @@ class BlogLogic extends BaseLogic @@ -41,24 +42,25 @@ class BlogLogic extends BaseLogic
41 $this->edit($this->param,['id'=>$id]); 42 $this->edit($this->param,['id'=>$id]);
42 $this->curlDelRoute(['new_route'=>$route ?? '','old_route'=>$info['url'] ?? '']); 43 $this->curlDelRoute(['new_route'=>$route ?? '','old_route'=>$info['url'] ?? '']);
43 }else{ 44 }else{
44 - $this->param['sort'] = $this->setNewsSort(); 45 + $this->param['sort'] = $this->setBlogSort();
45 $id = $this->model->addReturnId($this->param); 46 $id = $this->model->addReturnId($this->param);
46 $route = RouteMap::setRoute($this->param['url'], RouteMap::SOURCE_BLOG, $id, $this->user['project_id']); 47 $route = RouteMap::setRoute($this->param['url'], RouteMap::SOURCE_BLOG, $id, $this->user['project_id']);
47 $this->edit(['url'=>$route],['id'=>$id]); 48 $this->edit(['url'=>$route],['id'=>$id]);
48 $this->curlDelRoute(['new_route'=>$route]); 49 $this->curlDelRoute(['new_route'=>$route]);
49 } 50 }
  51 + $this->model->saveExtendInfo($id,$this->param['extend'] ?? [],$this->user['project_id']);
50 $this->addUpdateNotify(RouteMap::SOURCE_BLOG,$route); 52 $this->addUpdateNotify(RouteMap::SOURCE_BLOG,$route);
51 return $this->success(['id'=>$id]); 53 return $this->success(['id'=>$id]);
52 } 54 }
53 55
54 /** 56 /**
55 * @remark :设置最新产品的sort排序 57 * @remark :设置最新产品的sort排序
56 - * @name :setNewsSort 58 + * @name :setBlogSort
57 * @author :lyh 59 * @author :lyh
58 * @method :post 60 * @method :post
59 * @time :2023/12/25 9:27 61 * @time :2023/12/25 9:27
60 */ 62 */
61 - public function setNewsSort(){ 63 + public function setBlogSort(){
62 $info = $this->model->orderBy('sort','desc')->first(); 64 $info = $this->model->orderBy('sort','desc')->first();
63 if(empty($info)){ 65 if(empty($info)){
64 return 1; 66 return 1;
@@ -101,6 +103,7 @@ class BlogLogic extends BaseLogic @@ -101,6 +103,7 @@ class BlogLogic extends BaseLogic
101 $info['label_name'] = $blogLabelLogic->getLabelName($info['label_id']); 103 $info['label_name'] = $blogLabelLogic->getLabelName($info['label_id']);
102 $info['image_link'] = getImageUrl($info['image'],$this->user['storage_type'],$this->user['project_location']); 104 $info['image_link'] = getImageUrl($info['image'],$this->user['storage_type'],$this->user['project_location']);
103 $info['og_image'] = getImageUrl(empty($info['og_image']) ? $info['image'] : $info['og_image'],$this->user['storage_type'],$this->user['project_location']); 105 $info['og_image'] = getImageUrl(empty($info['og_image']) ? $info['image'] : $info['og_image'],$this->user['storage_type'],$this->user['project_location']);
  106 + $info['extend'] = $this->model->getExtendInfo($info['id']);
104 return $this->success($info); 107 return $this->success($info);
105 } 108 }
106 109
@@ -141,6 +144,9 @@ class BlogLogic extends BaseLogic @@ -141,6 +144,9 @@ class BlogLogic extends BaseLogic
141 $this->delRoute($id); 144 $this->delRoute($id);
142 RouteMap::delRoute(RouteMap::SOURCE_BLOG, $id, $this->user['project_id']); 145 RouteMap::delRoute(RouteMap::SOURCE_BLOG, $id, $this->user['project_id']);
143 $this->model->del(['id' => $id]); 146 $this->model->del(['id' => $id]);
  147 + //删除扩展字段
  148 + $extendInfoModel = new BlogExtendInfo();
  149 + $extendInfoModel->del(['blog_id'=>$id]);
144 } 150 }
145 } 151 }
146 DB::commit(); 152 DB::commit();
@@ -435,8 +441,8 @@ class BlogLogic extends BaseLogic @@ -435,8 +441,8 @@ class BlogLogic extends BaseLogic
435 } 441 }
436 442
437 /** 443 /**
438 - * @remark :复制新闻  
439 - * @name :copyNewsInfo 444 + * @remark :复制
  445 + * @name :copyBlogInfo
440 * @author :lyh 446 * @author :lyh
441 * @method :post 447 * @method :post
442 * @time :2024/4/28 14:51 448 * @time :2024/4/28 14:51
@@ -77,6 +77,10 @@ class GeoQuestionResLogic extends BaseLogic @@ -77,6 +77,10 @@ class GeoQuestionResLogic extends BaseLogic
77 * @time :2025/7/4 10:19 77 * @time :2025/7/4 10:19
78 */ 78 */
79 public function getResultInfo(){ 79 public function getResultInfo(){
  80 + if(isset($this->param['model'])){//查询记录表
  81 + $this->model = new GeoQuestionLog();
  82 + unset($this->param['model']);
  83 + }
80 $data = $this->model->read($this->param); 84 $data = $this->model->read($this->param);
81 return $this->success($data); 85 return $this->success($data);
82 } 86 }
@@ -11,7 +11,7 @@ namespace App\Http\Logic\Bside\News; @@ -11,7 +11,7 @@ namespace App\Http\Logic\Bside\News;
11 11
12 use App\Http\Logic\Bside\BaseLogic; 12 use App\Http\Logic\Bside\BaseLogic;
13 use App\Models\News\NewsExtend; 13 use App\Models\News\NewsExtend;
14 -use App\Models\Product\ExtendInfo; 14 +use App\Models\News\NewsExtendInfo;
15 15
16 class NewsExtendLogic extends BaseLogic 16 class NewsExtendLogic extends BaseLogic
17 { 17 {
@@ -84,7 +84,7 @@ class NewsExtendLogic extends BaseLogic @@ -84,7 +84,7 @@ class NewsExtendLogic extends BaseLogic
84 public function extendDel(){ 84 public function extendDel(){
85 $info = $this->model->read(['id'=>$this->param['id']]); 85 $info = $this->model->read(['id'=>$this->param['id']]);
86 //查看当前扩展字段是否设置了值 86 //查看当前扩展字段是否设置了值
87 - $extendInfoModel = new ExtendInfo(); 87 + $extendInfoModel = new NewsExtendInfo();
88 $extendInfo = $extendInfoModel->read(['key'=>$info['key']]); 88 $extendInfo = $extendInfoModel->read(['key'=>$info['key']]);
89 if($extendInfo !== false){ 89 if($extendInfo !== false){
90 $this->fail('当前扩展字段已有产品在使用,不允许删除'); 90 $this->fail('当前扩展字段已有产品在使用,不允许删除');
@@ -3,12 +3,9 @@ @@ -3,12 +3,9 @@
3 namespace App\Http\Logic\Bside\News; 3 namespace App\Http\Logic\Bside\News;
4 4
5 use App\Enums\Common\Code; 5 use App\Enums\Common\Code;
6 -use App\Helper\Arr;  
7 use App\Http\Logic\Bside\BaseLogic; 6 use App\Http\Logic\Bside\BaseLogic;
8 use App\Models\News\News; 7 use App\Models\News\News;
9 -use App\Models\News\NewsCategory;  
10 use App\Models\News\NewsCategory as NewsCategoryModel; 8 use App\Models\News\NewsCategory as NewsCategoryModel;
11 -use App\Models\News\NewsExtend;  
12 use App\Models\News\NewsExtendInfo; 9 use App\Models\News\NewsExtendInfo;
13 use App\Models\RouteMap\RouteMap; 10 use App\Models\RouteMap\RouteMap;
14 use App\Models\Template\BTemplate; 11 use App\Models\Template\BTemplate;
@@ -22,6 +22,124 @@ class Blog extends Base @@ -22,6 +22,124 @@ class Blog extends Base
22 } 22 }
23 return $value; 23 return $value;
24 } 24 }
  25 + /**
  26 + * @remark :扩展字段根据type返回类型
  27 + * @name :setTypValues
  28 + * @author :lyh
  29 + * @method :post
  30 + * @time :2023/12/6 14:43
  31 + */
  32 + public function getExtendInfo($blog_id){
  33 + $extendModel = new BlogExtend();
  34 + $list = $extendModel->list(['status'=>1],'id',['id','type','key','title']);
  35 + if(empty($list)){
  36 + return [];
  37 + }
  38 + $extendInfoModel = new BlogExtendInfo();
  39 + $infoList = $extendInfoModel->list(['blog_id'=>$blog_id],'created_at');
  40 + foreach ($list as $k=>$v){
  41 + if($v['type'] == 3 || $v['type'] == 4){
  42 + $v['values'] = [];
  43 + }else{
  44 + $v['values'] = '';
  45 + }
  46 + if(!empty($infoList)){
  47 + foreach ($infoList as $values){
  48 + if($v['key'] == $values['key']){
  49 + $v = $this->setTypValues($v,$values);
  50 + break;
  51 + }
  52 + }
  53 + }
  54 + $list[$k] = $v;
  55 + }
  56 + return $list;
  57 + }
  58 +
  59 + /**
  60 + * @remark :扩展字段根据type返回类型
  61 + * @name :setTypValues
  62 + * @author :lyh
  63 + * @method :post
  64 + * @time :2023/12/6 14:43
  65 + */
  66 + public function setTypValues($v,$info){
  67 + if($v['type'] == 3){
  68 + $arr = json_decode($info['values']);
  69 + foreach ($arr as $k1=>$v1){
  70 + $v1 = (array)$v1;
  71 + $v1['url'] = getImageUrl($v1['url']);
  72 + $arr[$k1] = $v1;
  73 + }
  74 + $v['values'] = $arr;
  75 + }elseif($v['type'] == 4){
  76 + $arr1 = json_decode($info['values']);
  77 + foreach ($arr1 as $k1=>$v1){
  78 + $v1 = (array)$v1;
  79 + if(isset($v1['url'])){
  80 + $v1['url'] = getFileUrl($v1['url']);
  81 + }else{
  82 + $v1 = getFileUrl($v1);
  83 + }
  84 + $arr1[$k1] = $v1;
  85 + }
  86 + $v['values'] = $arr1;
  87 + }else{
  88 + $v['values'] = $info['values'];
  89 + }
  90 + return $v;
  91 + }
  92 +
  93 + /**
  94 + * @remark :保存扩展字段
  95 + * @name :saveExtend
  96 + * @author :lyh
  97 + * @method :post
  98 + * @time :2023/11/9 15:02
  99 + */
  100 + public function saveExtendInfo($blog_id,$extend,$project_id){
  101 + //先删除以前的数据
  102 + $extendInfoModel = new BlogExtendInfo();
  103 + $extendInfoModel->del(['blog_id'=>$blog_id]);
  104 + if(empty($extend)) {
  105 + return true;
  106 + }
  107 + foreach ($extend as $k => $v){
  108 + if(empty($v['values'])){
  109 + continue;
  110 + }
  111 + $v = $this->saveHandleExtend($v,$blog_id,$project_id);
  112 + $extendInfoModel->add($v);
  113 + }
  114 + return true;
  115 + }
  116 +
  117 + /**
  118 + * @remark :保存扩展字段时处理数据
  119 + * @name :saveHandleExtend
  120 + * @author :lyh
  121 + * @method :post
  122 + * @time :2023/12/6 15:11
  123 + */
  124 + public function saveHandleExtend(&$v,$blog_id,$project_id){
  125 + unset($v['title']);
  126 + if($v['type'] == 3){
  127 + foreach ($v['values'] as $k1=>$v1){
  128 + $v1['url'] = str_replace_url($v1['url']);
  129 + $v['values'][$k1] = $v1;
  130 + }
  131 + $v['values'] = json_encode($v['values']);
  132 + }elseif ($v['type'] == 4){
  133 + foreach ($v['values'] as $k1=>$v1){
  134 + $v1['url'] = str_replace_url($v1['url']);
  135 + $v['values'][$k1] = $v1;
  136 + }
  137 + $v['values'] = json_encode($v['values']);
  138 + }
  139 + $v['project_id'] = $project_id;
  140 + $v['blog_id'] = $blog_id;
  141 + return $v;
  142 + }
25 } 143 }
26 144
27 145
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :BlogExtend.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/5/26 15:08
  8 + */
  9 +
  10 +namespace App\Models\Blog;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +class BlogExtend extends Base
  15 +{
  16 + protected $table = 'gl_blog_extend';
  17 + protected $connection = 'custom_mysql';
  18 +
  19 + const EXTEND_KEY = 'pd_extended_field_';
  20 +
  21 + /**
  22 + * @remark :添加扩展字段
  23 + * @name :getKey
  24 + * @author :lyh
  25 + * @method :post
  26 + * @time :2025/5/26 15:39
  27 + */
  28 + public function getKey($key = self::EXTEND_KEY,$i = 1){
  29 + $info = $this->read(['key'=>$key.$i]);
  30 + if($info !== false){
  31 + return $this->getKey($key,$i+1);
  32 + }else{
  33 + return $key.$i;
  34 + }
  35 + }
  36 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :BlogExtendInfo.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/5/26 15:49
  8 + */
  9 +
  10 +namespace App\Models\Blog;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +class BlogExtendInfo extends Base
  15 +{
  16 + protected $table = 'gl_blog_extend_info';
  17 + protected $connection = 'custom_mysql';
  18 +}
1 <?php 1 <?php
2 /** 2 /**
3 * @remark : 3 * @remark :
4 - * @name :NewsExtend.php 4 + * @name :BlogExtend.php
5 * @author :lyh 5 * @author :lyh
6 * @method :post 6 * @method :post
7 * @time :2025/5/26 15:08 7 * @time :2025/5/26 15:08
1 <?php 1 <?php
2 /** 2 /**
3 * @remark : 3 * @remark :
4 - * @name :NewsExtendInfo.php 4 + * @name :BlogExtendInfo.php
5 * @author :lyh 5 * @author :lyh
6 * @method :post 6 * @method :post
7 * @time :2025/5/26 15:49 7 * @time :2025/5/26 15:49
@@ -270,4 +270,21 @@ class AiBlogService @@ -270,4 +270,21 @@ class AiBlogService
270 $result = http_post($request_url,json_encode($param,true)); 270 $result = http_post($request_url,json_encode($param,true));
271 return $result; 271 return $result;
272 } 272 }
  273 +
  274 + /**
  275 + * @remark :自定义博客
  276 + * @name :createCustomBlog
  277 + * @author :lyh
  278 + * @method :post
  279 + * @time :2025/9/16 13:41
  280 + */
  281 + public function createCustomBlog($param)
  282 + {
  283 + $request_url = $this->url.'api/result/save_customer_article';
  284 + $param['mch_id'] = $this->mch_id;
  285 + $this->sign = $this->generateSign($param,$this->key);
  286 + $param['sign'] = $this->sign;
  287 + $result = http_post($request_url,json_encode($param,true));
  288 + return $result;
  289 + }
273 } 290 }
@@ -47,6 +47,10 @@ Route::any('project_new_url', [\App\Http\Controllers\Api\PrivateController::clas @@ -47,6 +47,10 @@ Route::any('project_new_url', [\App\Http\Controllers\Api\PrivateController::clas
47 Route::any('upgrade_project_domain', [\App\Http\Controllers\Api\PrivateController::class, 'upgradeProjectDomain'])->name('api.upgrade_project_domain'); 47 Route::any('upgrade_project_domain', [\App\Http\Controllers\Api\PrivateController::class, 'upgradeProjectDomain'])->name('api.upgrade_project_domain');
48 // 询盘通知微信提示hook 48 // 询盘通知微信提示hook
49 Route::any('inquiry_notice_hook', [\App\Http\Controllers\Api\NoticeController::class, 'inquiryNoticeHook'])->name('api.inquiry_notice_hook'); 49 Route::any('inquiry_notice_hook', [\App\Http\Controllers\Api\NoticeController::class, 'inquiryNoticeHook'])->name('api.inquiry_notice_hook');
  50 +// 获取当日需要推送外链列表
  51 +Route::any('get_today_push_external_link', [\App\Http\Controllers\Api\PrivateController::class, 'getExternalLink'])->name('api.today_push_external_link');
  52 +// 根据域名获取生成聚合页外链
  53 +Route::any('get_external_link_by_domain', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectExternalLink'])->name('api.external_link_by_domain');
50 54
51 // --------------------- 站群服务 ------------------------------------------ 55 // --------------------- 站群服务 ------------------------------------------
52 // 获取项目信息 56 // 获取项目信息
@@ -582,6 +582,7 @@ Route::middleware(['aloginauth'])->group(function () { @@ -582,6 +582,7 @@ Route::middleware(['aloginauth'])->group(function () {
582 Route::any('/save', [Aside\Geo\GeoLinkController::class, 'save'])->name('admin.geo_link_save'); 582 Route::any('/save', [Aside\Geo\GeoLinkController::class, 'save'])->name('admin.geo_link_save');
583 Route::any('/info', [Aside\Geo\GeoLinkController::class, 'info'])->name('admin.geo_link_info'); 583 Route::any('/info', [Aside\Geo\GeoLinkController::class, 'info'])->name('admin.geo_link_info');
584 Route::any('/del', [Aside\Geo\GeoLinkController::class, 'del'])->name('admin.geo_link_del'); 584 Route::any('/del', [Aside\Geo\GeoLinkController::class, 'del'])->name('admin.geo_link_del');
  585 + Route::any('/downloadGeoLink', [Aside\Geo\GeoLinkController::class, 'downloadGeoLink'])->name('admin.geo_link_downloadGeoLink');
585 }); 586 });
586 }); 587 });
587 // 任务相关 588 // 任务相关
@@ -141,13 +141,18 @@ Route::middleware(['bloginauth'])->group(function () { @@ -141,13 +141,18 @@ Route::middleware(['bloginauth'])->group(function () {
141 Route::any('/category/sort', [\App\Http\Controllers\Bside\Blog\BlogCategoryController::class, 'sort'])->name('blog_category_sort'); 141 Route::any('/category/sort', [\App\Http\Controllers\Bside\Blog\BlogCategoryController::class, 'sort'])->name('blog_category_sort');
142 Route::any('/category/categoryTopList', [\App\Http\Controllers\Bside\Blog\BlogCategoryController::class, 'categoryTopList'])->name('blog_category_categoryTopList'); 142 Route::any('/category/categoryTopList', [\App\Http\Controllers\Bside\Blog\BlogCategoryController::class, 'categoryTopList'])->name('blog_category_categoryTopList');
143 //博客标签 143 //博客标签
144 - Route::any('/label/', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'lists'])->name('blog_lists');  
145 - Route::any('/label/add', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'add'])->name('blog_add');  
146 - Route::any('/label/info', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'info'])->name('blog_info');  
147 - Route::any('/label/edit', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'edit'])->name('blog_edit');  
148 - Route::any('/label/del', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'del'])->name('blog_del');  
149 - Route::any('/label/batchAdd', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'batchAdd'])->name('blog_batchAdd');  
150 - Route::any('/label/status', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'status'])->name('blog_status'); 144 + Route::any('/label/', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'lists'])->name('blog_label_lists');
  145 + Route::any('/label/add', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'add'])->name('blog_label_add');
  146 + Route::any('/label/info', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'info'])->name('blog_label_info');
  147 + Route::any('/label/edit', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'edit'])->name('blog_label_edit');
  148 + Route::any('/label/del', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'del'])->name('blog_label_del');
  149 + Route::any('/label/batchAdd', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'batchAdd'])->name('blog_label_batchAdd');
  150 + Route::any('/label/status', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'status'])->name('blog_label_status');
  151 + //扩展字段
  152 + Route::any('/extend/', [\App\Http\Controllers\Bside\Blog\BlogExtendController::class, 'lists'])->name('blog_extend_lists');
  153 + Route::any('/extend/save', [\App\Http\Controllers\Bside\Blog\BlogExtendController::class, 'save'])->name('blog_extend_save');
  154 + Route::any('/extend/status', [\App\Http\Controllers\Bside\Blog\BlogExtendController::class, 'status'])->name('blog_extend_status');
  155 + Route::any('/extend/del', [\App\Http\Controllers\Bside\Blog\BlogExtendController::class, 'del'])->name('blog_extend_del');
151 }); 156 });
152 //ai指令 157 //ai指令
153 Route::prefix('command')->group(function () { 158 Route::prefix('command')->group(function () {
@@ -180,6 +185,7 @@ Route::middleware(['bloginauth'])->group(function () { @@ -180,6 +185,7 @@ Route::middleware(['bloginauth'])->group(function () {
180 Route::any('/blog/getAuthorInfo', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getAuthorInfo'])->name('ai_blog_getAuthorInfo'); 185 Route::any('/blog/getAuthorInfo', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getAuthorInfo'])->name('ai_blog_getAuthorInfo');
181 Route::any('/blog/saveBlogAuthor', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'saveBlogAuthor'])->name('ai_blog_saveBlogAuthor'); 186 Route::any('/blog/saveBlogAuthor', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'saveBlogAuthor'])->name('ai_blog_saveBlogAuthor');
182 Route::any('/blog/getInfo', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getInfo'])->name('ai_blog_getInfo'); 187 Route::any('/blog/getInfo', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getInfo'])->name('ai_blog_getInfo');
  188 + Route::any('/blog/customSaveBlog', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'customSaveBlog'])->name('ai_blog_customSaveBlog');
183 Route::any('/blog/getAiBlogList', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getAiBlogList'])->name('ai_blog_getAiBlogList'); 189 Route::any('/blog/getAiBlogList', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getAiBlogList'])->name('ai_blog_getAiBlogList');
184 Route::any('/blog/getAiBlogListInfo', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getAiBlogListInfo'])->name('ai_blog_getAiBlogListInfo'); 190 Route::any('/blog/getAiBlogListInfo', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getAiBlogListInfo'])->name('ai_blog_getAiBlogListInfo');
185 Route::any('/product/', [\App\Http\Controllers\Bside\Ai\AiProductController::class, 'save'])->name('ai_product_save'); 191 Route::any('/product/', [\App\Http\Controllers\Bside\Ai\AiProductController::class, 'save'])->name('ai_product_save');