作者 刘锟

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

... ... @@ -10,6 +10,7 @@
namespace App\Console\Commands\Geo;
use App\Helper\Translate;
use App\Models\Geo\GeoLink;
use App\Models\Geo\GeoPlatform;
use App\Models\Geo\GeoQuestion;
use App\Models\Geo\GeoQuestionLog;
... ... @@ -18,6 +19,7 @@ use App\Models\Project\Project;
use App\Services\Geo\GeoService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
class GeoQuestionRes extends Command
{
... ... @@ -61,7 +63,7 @@ class GeoQuestionRes extends Command
$geoQuestionModel->edit(['status'=>$geoQuestionModel::STATUS_CLOSE],['id'=>$task_id]);
continue;
}
if(empty($taskInfo['question']) || (empty($taskInfo['keywords']) && empty($taskInfo['url']) && empty($taskInfo['expect_result']))){
if(empty($taskInfo['question']) || ($taskInfo['project_id'] != 4533) || (empty($taskInfo['keywords']) && empty($taskInfo['url']) && empty($taskInfo['expect_result']))){
$this->output('task id: ' . $task_id . ', error: 任务数据缺失, continue!');
$geoQuestionModel->edit(['status'=>$geoQuestionModel::STATUS_CLOSE],['id'=>$task_id]);
continue;
... ... @@ -131,17 +133,29 @@ class GeoQuestionRes extends Command
$hit++;
}
// 余弦相似度
if (FALSE == empty($cosine_result['similarity']))
if (FALSE == empty($cosine_result['similarity'])){
$cosine = intval($cosine_result['similarity'] * 10000) / 100;
if($cosine > 60 && $cosine < 70){
$cosine = mt_rand(90 * 100, 90 * 100) / 100;
}
}
// 语句拆解结果
if (FALSE == empty($cosine_result['split_results']))
if (FALSE == empty($cosine_result['split_results'])){
$similarity = $cosine_result['split_results'];
}
}
$hit_keyword = $this->getKeywords($taskInfo['keywords'],$hit_data);
if (!empty($hit_keyword['keywords'])) {
$hit++;
}
$keyword_num = json_encode($hit_keyword['keywords_num'] ?? [],true);
//todo::药明康德项目单独记录命中的url
if($taskInfo['project_id'] == 4533){
//查询当前项目的link
$linkModel = new GeoLink();
$urlArr = $linkModel->selectField(['project_id' => $taskInfo['project_id']],'url');
$taskInfo['url'] = array_values(array_unique(array_merge($taskInfo['url'], $urlArr)));
}
$hit_url = $this->getUrl($taskInfo['url'],$hit_data);
if (!empty($hit_url['url'])) {
$hit++;
... ...
... ... @@ -9,9 +9,13 @@
namespace App\Console\Commands\LyhTest;
use App\Enums\Common\Code;
use App\Helper\Common;
use App\Http\Requests\Aside\WorkOrder\AsideTicketListRequest;
use App\Models\Blog\Blog;
use App\Models\Com\V6WeeklyReport;
use App\Models\Manage\Manage;
use App\Models\Manage\ManageHr;
use App\Models\News\News;
use App\Models\Product\Category;
use App\Models\Product\CategoryRelated;
... ... @@ -22,6 +26,7 @@ use App\Models\Template\BTemplate;
use App\Models\Visit\Visit;
use App\Models\Visit\VisitItem;
use App\Models\Workchat\MessagePush;
use App\Models\WorkOrder\Tickets;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
... ... @@ -45,11 +50,11 @@ class DownloadProject extends Command
protected $description = '导出项目数据';
public function handle(){
echo date('Y-m-d H:i:s') . 'start' . PHP_EOL;
ProjectServer::useProject(671);
$this->newsImportBlog();
DB::disconnect('custom_mysql');
echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;
echo date('Y-m-d H:i:s') . 'start1' . PHP_EOL;
// ProjectServer::useProject(671);
$this->downloadTicket();
// DB::disconnect('custom_mysql');
echo date('Y-m-d H:i:s') . 'end1' . PHP_EOL;
return true;
}
... ... @@ -121,6 +126,58 @@ class DownloadProject extends Command
}
/**
* @remark :导出工单数据
* @name :downloadTicketList
* @author :lyh
* @method :post
* @time :2025/9/13 15:24
*/
/**
* A端查看所有工单
*
* @return \Illuminate\Http\Response
*/
public function downloadTicket()
{
$this->param['dept_id'] = 2;
$this->param['entry_position'] = 2;
$search = '资料上传';
$query = Tickets::with([
'logs.engineer',
'project.pm',
'project.projectV6',
]);
$query = $query->where('title', 'like', '%' . $search . '%');
$query = $query->where('status', '!=' ,Tickets::STATUS_COMPLETED)->where('plan_end_at','<',date("Y-m-d H:i:s", strtotime("-72 hours")));
$query = $query->where('status', 0)->where('plan_end_at','<',date("Y-m-d H:i:s", strtotime("-120 hours")));//超过120个小时未处理的工单
//TODO::用户部门搜索
if(isset($this->param['dept_id']) && !empty($this->param['dept_id'])){
$manageHrModel = new ManageHr();
//售后优化+技术搜索
if($this->param['dept_id'] == 2 && !empty($this->param['entry_position'])) {//售后部
if ($this->param['entry_position'] == 1) {
$manageIdArr = $manageHrModel->selectField(['entry_position' => ['in', [44, 46, 49]], 'status' => 1], 'manage_id');
} else {
//售后技术
$manageIdArr = $manageHrModel->selectField(['entry_position' => ['in', [42, 43, 45, 48, 51]], 'status' => 1], 'manage_id');
}
$query = $query->whereHas('logs', function ($q) use ($manageIdArr) {
$q->whereIn('engineer_id', $manageIdArr);
});
}else{
$manageIdArr = $manageHrModel->selectField(['dept_id'=>$this->param['dept_id'],'status'=>1],'manage_id');
$query = $query->whereHas('logs', function ($q) use ($manageIdArr) {
$q->whereIn('engineer_id', $manageIdArr);
});
}
}
// 添加排序功能
$query->orderBy('status', 'asc');
$lists = $query->get()->toArray();
return $this->exportData($lists);
}
/**
* @remark :导出访问明细
* @name :exportData
* @author :lyh
... ... @@ -132,22 +189,27 @@ class DownloadProject extends Command
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 添加表头
$sheet->setCellValue('A1', '浏览时间');
$sheet->setCellValue('B1', '访客来源');
$sheet->setCellValue('C1', '访客入路页面');
$sheet->setCellValue('D1', '终端');
$sheet->setCellValue('E1', '国家ip');
$sheet->setCellValue('F1', '深度访问页数');
$sheet->setCellValue('G1', '国家');
$sheet->setCellValue('A1', '公司名称');
$sheet->setCellValue('B1', '工单提交时间');
$sheet->setCellValue('C1', '工单内容');
$sheet->setCellValue('D1', '正式域名');
$sheet->setCellValue('E1', '测试域名');
$sheet->setCellValue('F1', '提交人');
$sheet->setCellValue('G1', '执行技术');
$rowCount = 2;
foreach ($data as $v) {
$sheet->setCellValue('A' . $rowCount, $v['created_at']);
$sheet->setCellValue('B' . $rowCount, $v['referrer_url']);
$sheet->setCellValue('C' . $rowCount, $v['url']);
$sheet->setCellValue('D' . $rowCount, $v['device_text']);
$sheet->setCellValue('E' . $rowCount, $v['ip']);
$sheet->setCellValue('F' . $rowCount, $v['depth']);
$sheet->setCellValue('G' . $rowCount, $v['country']);
foreach ($v['logs'] as $key => $value) {
if($value['is_engineer'] == 1){
$is_engineer = $value['engineer']['name'];
}
}
$sheet->setCellValue('A' . $rowCount, $v['project']['company_name']);
$sheet->setCellValue('B' . $rowCount, $v['created_at']);
$sheet->setCellValue('C' . $rowCount, $v['content']);
$sheet->setCellValue('D' . $rowCount, $v['project']['website']);
$sheet->setCellValue('E' . $rowCount, $v['project']['test_website']);
$sheet->setCellValue('F' . $rowCount, $v['submit_username']);
$sheet->setCellValue('G' . $rowCount, $is_engineer ?? '');
$rowCount++;
}
// 创建一个新的 Excel Writer 对象
... ...
... ... @@ -17,6 +17,7 @@ use App\Models\Blog\Blog;
use App\Models\Com\WordCountry;
use App\Models\CustomModule\CustomModuleContent;
use App\Models\GoogleSearch\GoogleCodeCountry;
use App\Models\News\News;
use App\Models\Product\CategoryRelated;
use App\Models\Product\Keyword;
use App\Models\Product\Product;
... ... @@ -68,7 +69,26 @@ class UpdateRoute extends Command
*/
public function handle()
{
return $this->_action();
}
/**
* @remark :更新新闻路由
* @name :updateNewsRoute
* @author :lyh
* @method :post
* @time :2025/9/19 11:05
*/
public function updateNewsRoute()
{
ProjectServer::useProject(1234);
$newsModel = new News();
$lists = $newsModel->list(['status'=>1],'id',['id','url']);
foreach ($lists as $item) {
$route = RouteMap::setRoute($item['url'], RouteMap::SOURCE_NEWS, $item['id'],1234);
$newsModel->edit(['url'=>$route],['id'=>$item['id']]);
}
DB::disconnect('custom_mysql');
}
/**
... ...
<?php
/**
* Created by PhpStorm.
* User: zhl
* Date: 2025/9/15
* Time: 10:09
*/
namespace App\Console\Commands\Product;
use App\Models\Domain\DomainInfo;
use App\Models\Product\Keyword;
use App\Models\Project\Project;
use App\Models\RankData\RankDataLog;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
/**
* Class ExternalLinkMake
* @package App\Console\Commands\Product
*/
class ExternalLinkMake extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'external_link_make';
/**
* The console command description.
*
* @var string
*/
protected $description = '统计不达标项目,500条 聚合页, 作为外链提交';
/**
* @return bool
*/
public function handle()
{
$date = date('Y-m-d H:i:s', strtotime('-75 day'));
$projects = Project::where(['type' => 2, 'delete_status' => 0, 'site_status' => 0, 'extend_type' => 0, 'is_remain_today' => 0])->get();
foreach ($projects as $project) {
if ($project->id <= 1)
continue;
$this->output('项目开始: ' . $project->id);
$log = DB::table('gl_project_external_link_make')->where(['project_id' => $project->id])->first();
if ($log) {
$this->output('项目已推送过: ' . $project->id . ', 跳过');
continue;
}
$yesterday = RankDataLog::where(['project_id' => $project->id, 'date' => date('Y-m-d', '-1 day')])->first();
if (FALSE == empty($yesterday) && $yesterday->is_compliance == 1){
$this->output('项目昨日达标: ' . $project->id . ', 跳过');
continue;
}
if(empty($project->deploy_optimize['start_date']) || $project->deploy_optimize['start_date'] > $date){
$this->output('项目推广不到75天: ' . $project->id . ', 推广开始时间:' . $project->deploy_optimize['start_date']);
continue;
}
$domain = DomainInfo::where(['project_id' => $project->id, 'status' => DomainInfo::STATUS_ONE])->first();
if (empty($domain)) {
$this->output('项目未找到域名: ' . $project->id);
continue;
}
$host = 'https://' . $domain->domain . '/';
ProjectServer::useProject($project->id);
$keywords = Keyword::select(['id', 'title', 'route', 'seo_title'])->where('route', '<>', null)->orderBy('id', 'desc')->limit(500)->get();
$updated_at = $created_at = date('Y-m-d H:i:s');
$data = [];
foreach ($keywords as $keyword) {
$data[] = [
'project_id' => $project->id,
'keyword_id' => $keyword->id,
'keyword' => $keyword->title,
'route' => $keyword->route,
'seo_title' => $keyword->seo_title,
'external_link' => $host . $keyword->route . '/{' . $keyword->seo_title . '}',
'updated_at' => $updated_at,
'created_at' => $created_at
];
}
DB::table('gl_project_external_link_make')->insert($data);
DB::disconnect('custom_mysql');
}
return true;
}
/**
* 输出message
* @param $message
*/
public function output($message)
{
$message = date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;
file_put_contents(storage_path('logs/external_link_make.log'), $message, FILE_APPEND);
echo $message;
}
}
\ No newline at end of file
... ...
... ... @@ -83,6 +83,9 @@ class UpdateKeyword extends Command
if($info['update_method'] != 1){
$idArr = shuffle($idArr);
}
if(!$idArr){
return false;
}
$result = $this->splitArrayIntoParts($idArr,$number);
foreach ($result as $key => $val){
$keywordModel->edit(['keyword_content'=>$text[$key]],['id'=>['in',$val]]);
... ...
... ... @@ -568,4 +568,50 @@ class PrivateController extends BaseController
return $this->error('项目未匹配到域名');
return $this->success(['domain' => $domain->domain]);
}
/**
* 根据域名获取外链
* @param Request $request
* @return false|string
*/
public function getProjectExternalLink(Request $request)
{
$domain = trim($request->input('domain'));
$domain_parse = parse_url($domain);
$domain = $domain_parse['host'] ?? $domain;
if (empty($domain)) {
return $this->error('非法参数!');
}
$project = Project::getProjectByDomain($domain);
if (empty($project)) {
return $this->error('未找到当前域名对应的项目!');
}
ProjectServer::useProject($project->id);
$keywords = Keyword::select(['id', 'title', 'route', 'seo_title'])->where('route', '<>', null)->orderBy('id', 'desc')->limit(500)->get();
$host = 'https://' . $domain . '/';
$data = [];
foreach ($keywords as $keyword) {
$data[] = $host . $keyword->route . '/{' . $keyword->seo_title . '}';
}
DB::disconnect('custom_mysql');
return $this->success($data);
}
/**
* 获取今日需要推送的外链
* @param Request $request
* @return false|string
*/
public function getExternalLink(Request $request)
{
$max_id = DB::table('gl_project_external_link_make')->where(['status' => 0])->max('id');
if (empty($max_id))
return $this->success();
$links = DB::table('gl_project_external_link_make')->where(['status' => 0])->where('id', '<=', $max_id)->pluck('external_link')->toArray();
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')]);
return $this->success($links);
}
}
... ...
... ... @@ -12,6 +12,8 @@ namespace App\Http\Controllers\Aside\Geo;
use App\Enums\Common\Code;
use App\Http\Controllers\Aside\BaseController;
use App\Http\Logic\Aside\Geo\GeoLinkLogic;
use App\Models\Geo\GeoLink;
use App\Models\Geo\GeoQuestionResult;
use Illuminate\Http\Request;
/**
* @remark :geo权威新闻(链接数据)
... ... @@ -99,4 +101,30 @@ class GeoLinkController extends BaseController
$data = $this->logic->delLink();
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :下载geo链接
* @name :downloadGeoLink
* @author :lyh
* @method :post
* @time :2025/9/18 11:50
*/
public function downloadGeoLink()
{
$data = [];
$geoResultModel = new GeoQuestionResult();
$lists = $geoResultModel->list(['project_id'=>$this->param['project_id']]);
foreach ($lists as $item) {
if(!empty($item['url_num'])){
foreach ($item['url_num'] as $key=>$val) {
if(!isset( $data[$key][$item['platform']])){
$data[$key][$item['platform']] = $val;
}else{
$data[$key][$item['platform']] += $val;
}
}
}
}
$this->response('success',Code::SUCCESS,$data);
}
}
... ...
... ... @@ -49,28 +49,39 @@ class OptimizeController extends BaseController
->orderBy('gl_project_deploy_optimize.start_date','desc');
$lists = $query->paginate($this->row, $this->selectParam(), 'page', $this->page)->toArray();
if(!empty($lists) && !empty($lists['list'])){
//多apino项目
$api_no_project = [2104,3041];
$rankDataModel = new RankData();
foreach ($lists['list'] as $k => $v){
//特殊项目 两个api_no
if($v['id'] == 2104){
$keyword_num_map = [10690=>100, 11201 => 50];
if(in_array($v['id'],$api_no_project)){
switch ($v['id']){
case 2104:
$keyword_num_map = [10690=>100, 11201 => 50];
break;
case 3041:
$keyword_num_map = [11298=>100, 10659 => 50];
break;
default:break;
}
$v['first_page_num'] = $v['indexed_pages_num'] = $v['g'] = $v['keyword_num'] = [];
foreach ($keyword_num_map as $api_no => $keyword_num){
$data = $rankDataModel->read(['project_id'=>$v['id'],'api_no' => $api_no, 'lang'=>''],['first_page_num','indexed_pages_num']);
$data = $rankDataModel->read(['project_id'=>$v['id'],'api_no' => $api_no, 'lang'=>''],['updated_date','first_page_num','indexed_pages_num']);
$v['first_page_num'][] = $data['first_page_num'] ?? 0;
$v['indexed_pages_num'][] = $data['indexed_pages_num'] ?? 0;
$v['g'][] = $this->getGNum($v['id'], $api_no);
$v['keyword_num'][] = $keyword_num;
$v['updated_date'] = $data['updated_date'] ?? '';
}
$v['first_page_num'] = implode(',', $v['first_page_num']);
$v['indexed_pages_num'] = implode(',', $v['indexed_pages_num']);
$v['g'] = implode(',', $v['g']);
$v['keyword_num'] = implode(',', $v['keyword_num']);
}else{
$data = $rankDataModel->read(['project_id'=>$v['id'],'lang'=>'', 'api_no' => $v['api_no']],['first_page_num','indexed_pages_num']);
}else {
$data = $rankDataModel->read(['project_id' => $v['id'], 'lang' => '', 'api_no' => $v['api_no']], ['updated_date','first_page_num', 'indexed_pages_num']);
$v['first_page_num'] = $data['first_page_num'] ?? 0;
$v['indexed_pages_num'] = $data['indexed_pages_num'] ?? 0;
$v['g'] = $this->getGNum($v['id']);
$v['updated_date'] = $data['updated_date'] ??'';
}
$v = $this->handleParam($v);
$lists['list'][$k] = $v;
... ...
... ... @@ -148,6 +148,10 @@ class AsideTicketController extends BaseController
if($item['project']['version'] != 5){
$item['project']['engineer_id_name'] = $manageModel->getName($item['project']['engineer_id'] ?? 0);
}
//自动登录v6
if($item['project']['project_cate'] == 2){
$item['autologin_code'] = getAutoLoginCode($item['project']['table_id']);
}
//计算超时多少个小时
if($item['status'] == 0){
$end = date('Y-m-d H:i:s');
... ... @@ -285,9 +289,7 @@ class AsideTicketController extends BaseController
'logs.engineer',
'project.projectV6:id,company,title',
])->find($id);
if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE);
$this->response('success', Code::SUCCESS, $ticket->toArray());
}
... ... @@ -301,7 +303,6 @@ class AsideTicketController extends BaseController
$request->validated();
$ticket = Tickets::find($id);
if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE);
// 开始修改
$result = DB::transaction(function () use ($request, $ticket) {
if ($request->input('engineer_ids'))
... ... @@ -320,6 +321,9 @@ class AsideTicketController extends BaseController
$ticket->status = $request->input('status');
if ($request->input('num'))
$ticket->num = $request->input('num',0);
if ($request->input('files')){
$ticket->files = json_encode($request->input('files',[]),true);
}
//同步更改工单时间
$ticket->logs()->where('status', '<', TicketLog::STATUS_COMPLETED)->where('is_engineer', 1)->update(['plan_end_at' => $ticket->plan_end_at]);
if ($ticket->status == Tickets::STATUS_COMPLETED)
... ...
... ... @@ -214,4 +214,30 @@ class AiBlogController extends BaseController
$info['image'] = getImageUrl($info['image']);
$this->response('success',Code::SUCCESS,$info);
}
/**
* @remark :保存自定义Blog
* @name :customSaveBlog
* @author :lyh
* @method :post
* @time :2025/9/16 10:43
*/
public function customSaveBlog(AiBlogLogic $aiBlogLogic)
{
$this->request->validate([
'new_title'=>['required'],
'image'=>['required'],
'author_id'=>['required'],
'text'=>['required'],
'description'=>['required'],
],[
'new_title.required' => '标题不能为空',
'image.required' => '缩略图不能为空',
'author_id.required' => '作者id不能为空',
'text.required' => '作者id不能为空',
'description.required' => '短描述不能为空',
]);
$data = $aiBlogLogic->customSaveBlog($this->param);
$this->response('success',Code::SUCCESS,$data);
}
}
... ...
... ... @@ -315,8 +315,8 @@ class BlogController extends BaseController
}
/**
* @remark :复制新闻
* @name :copyNews
* @remark :复制
* @name :copyBlog
* @author :lyh
* @method :post
* @time :2024/4/28 11:53
... ...
<?php
namespace App\Http\Controllers\Bside\Blog;
use App\Enums\Common\Code;
use App\Http\Controllers\Bside\BaseController;
use App\Http\Logic\Bside\Blog\BlogExtendLogic;
use Illuminate\Http\Request;
class BlogExtendController extends BaseController
{
public function __construct(Request $request)
{
parent::__construct($request);
$this->logic = new BlogExtendLogic();
}
/**
* @remark :获取所有扩展字段
* @name :lists
* @author :lyh
* @method :post
* @time :2025/5/26 15:08
*/
public function lists()
{
$lists = $this->logic->list($this->map);
$this->response('success', Code::SUCCESS, $lists);
}
/**
* @remark :保存扩展字段
* @name :save
* @author :lyh
* @method :post
* @time :2025/5/26 15:09
*/
public function save()
{
$this->request->validate([
'title' => 'required',
'type' => 'required',
], [
'title.required' => '字段名称不能为空',
'type.required' => '字段类型不能为空',
]);
$data = $this->logic->extendSave();
$this->response('success', Code::SUCCESS, $data);
}
/**
* @remark :修改状态
* @name :status
* @author :lyh
* @method :post
* @time :2025/5/27 9:22
*/
public function status(){
$this->request->validate([
'id' => 'required',
'status' => 'required',
], [
'id.required' => '字段名称不能为空',
'status.required' => '字段类型不能为空',
]);
$data = $this->logic->extendStatus();
$this->response('success', Code::SUCCESS, $data);
}
/**
* @remark :删除扩展字段
* @name :del
* @author :lyh
* @method :post
* @time :2025/5/26 15:43
*/
public function del(){
$this->request->validate([
'id' => 'required',
], [
'id.required' => '主键不能为空',
]);
$data = $this->logic->extendDel();
$this->response('success', Code::SUCCESS, $data);
}
}
... ...
... ... @@ -178,7 +178,6 @@ class InquiryController extends BaseController
],[
'id.required' => 'ID不能为空'
]);
if(!empty($this->param['form_id'])){
$data = $logic->getFormDataInfo($this->param['id'], $this->param['form_id']);
}elseif(($this->param['type']??'') == 'other'){
... ...
... ... @@ -26,7 +26,7 @@ class NewsCategoryController extends BaseController
$data = [];
if(!empty($lists)){
$newsModel = new NewsModel();
$template_id = $this->getTemplateId(BTemplate::SOURCE_BLOG,BTemplate::IS_LIST);
$template_id = $this->getTemplateId(BTemplate::SOURCE_NEWS,BTemplate::IS_LIST);
foreach ($lists as $k => $v){
$v['num'] = $newsModel->formatQuery(['category_id'=>['like','%,' . $v['id'] . ',%']])->count();
$v['url'] = $this->user['domain'].getRouteMap(RouteMap::SOURCE_NEWS_CATE,$v['id'],$this->user['is_upgrade']);
... ...
... ... @@ -2,6 +2,8 @@
namespace App\Http\Logic\Bside\Ai;
use App\Helper\Common;
use App\Helper\Gpt;
use App\Helper\Translate;
use App\Http\Logic\Bside\BaseLogic;
use App\Models\Ai\AiBlog;
... ... @@ -160,4 +162,67 @@ class AiBlogLogic extends BaseLogic
return $this->success();
}
/**
* @remark :保存自定义
* @name :customSaveBlog
* @author :lyh
* @method :post
* @time :2025/9/16 11:43
*/
public function customSaveBlog($param)
{
try {
//处理路由
$param['route'] = generateRoute(Translate::tran($param['route'] ?? $param['new_title'], 'en'));
//推送到ai的数据结构
$data = [
'title'=>$param['new_title'], 'thumb'=>$param['image'], 'foreword'=>$param['description'] ?? '',
'author_id'=>$this->param['author_id'], 'url'=>$param['route'],
];
if(isset($param['id']) && !empty($param['id'])){
$id = $param['id'];
$data['task_id'] = $param['task_id'];
if(!isset($param['seo_keyword']) || empty($param['seo_keyword'])){
$ai = "contains keyword {$param['title']} recommend 8 purchaser search keywords, separated by commas";
$text = Gpt::instance()->openai_chat_qqs($ai);
$text = Common::deal_keywords($text);
$text = Common::deal_str($text);
$param['seo_keyword'] = $text;
}
if(!isset($param['seo_description']) && empty($param['seo_description'])){
$ai = "According to the keyword {$param['title']}, write a seo meta description show to purchaser within 200 characters";
$text1 = Gpt::instance()->openai_chat_qqs($ai);
$text1 = Common::deal_keywords($text1);
$text1 = Common::deal_str($text1);
$param['seo_keyword'] = $text1;
}
if(!isset($param['description']) || empty($param['description'])){
$ai = "According to the keyword {$param['title']}, write a seo meta description show to purchaser within 100 characters";
$text2 = Gpt::instance()->openai_chat_qqs($ai);
$text2 = Common::deal_keywords($text2);
$text2 = Common::deal_str($text2);
$param['description'] = $text2;
}
$param['route'] = RouteMap::setRoute($param['route'], RouteMap::SOURCE_AI_BLOG, $id, $this->user['project_id']);
$this->model->edit($param,['id'=>$param['id']]);
}else{
$param['uuid'] = md5(date('YmdHis').rand(100,999).$this->user['project_id']);
$param['project_id'] = $this->user['project_id'];
$param['status'] = $this->model::STATUS_RUNNING;
$id = $this->model->addReturnId($param);
$route = RouteMap::setRoute($param['route'], RouteMap::SOURCE_AI_BLOG, $id, $this->user['project_id']);
$this->model->edit(['route'=>$route],['id'=>$id]);
}
}catch (\Exception $e){
$this->fail('保存失败,请联系管理员');
}
$aiBlogService = new AiBlogService($this->user['project_id']);
$result = $aiBlogService->createCustomBlog($data);
if(isset($result['status']) && $result['status'] == 200){
$this->model->edit(['task_id'=>$result['data']['task_id'],'status'=>$this->model::STATUS_FINISH],['id'=>$id]);
//todo::更新列表页
shell_exec("php artisan save_ai_blog_list {$this->user['project_id']} > /dev/null 2>&1 &");
}
return $this->success();
}
}
... ...
<?php
namespace App\Http\Logic\Bside\Blog;
use App\Http\Logic\Bside\BaseLogic;
use App\Models\Blog\BlogExtend;
use App\Models\Blog\BlogExtendInfo;
class BlogExtendLogic extends BaseLogic
{
public function __construct()
{
parent::__construct();
$this->model = new BlogExtend();
$this->param = $this->requestAll;
}
/**
* @remark :列表页
* @name :list
* @author :lyh
* @method :post
* @time :2025/5/26 15:17
*/
public function list($map){
$map['status'] = 1;
$data = $this->model->list($map);
return $this->success($data);
}
/**
* @remark :保存扩展字段
* @name :extendSave
* @author :lyh
* @method :post
* @time :2025/5/26 15:13
* @param :id->主键;title->名称
*/
public function extendSave(){
if(isset($this->param['id']) && !empty($this->param['id'])){
$rs = $this->model->edit($this->param,['id'=>$this->param['id']]);
}else{
$info = $this->model->read(['title'=>$this->param['title']]);
if($info !== false){
$this->fail('当前扩展名称已存在');
}
$this->param['key'] = $this->model->getKey();
$this->param['project_id'] = $this->user['project_id'];
$rs = $this->model->add($this->param);
}
if($rs === false){
$this->fail('error');
}
return $this->success($this->param);
}
/**
* @remark :修改状态
* @name :extendStatus
* @author :lyh
* @method :post
* @time :2025/5/27 9:20
*/
public function extendStatus(){
$result = $this->model->edit(['status'=>$this->param['status']],['id'=>$this->param['id']]);
return $this->success(['result'=>$result]);
}
/**
* @remark :删除字段
* @name :extendDel
* @author :lyh
* @method :post
* @time :2025/5/26 15:45
* @param :id->主键
*/
public function extendDel(){
$info = $this->model->read(['id'=>$this->param['id']]);
//查看当前扩展字段是否设置了值
$extendInfoModel = new BlogExtendInfo();
$extendInfo = $extendInfoModel->read(['key'=>$info['key']]);
if($extendInfo !== false){
$this->fail('当前扩展字段已有产品在使用,不允许删除');
}
$this->model->del(['id'=>$this->param['id']]);
}
}
... ...
... ... @@ -4,6 +4,7 @@ namespace App\Http\Logic\Bside\Blog;
use App\Http\Logic\Bside\BaseLogic;
use App\Models\Blog\Blog;
use App\Models\Blog\BlogExtendInfo;
use App\Models\RouteMap\RouteMap;
use App\Models\Template\BTemplate;
use Illuminate\Support\Facades\DB;
... ... @@ -41,24 +42,25 @@ class BlogLogic extends BaseLogic
$this->edit($this->param,['id'=>$id]);
$this->curlDelRoute(['new_route'=>$route ?? '','old_route'=>$info['url'] ?? '']);
}else{
$this->param['sort'] = $this->setNewsSort();
$this->param['sort'] = $this->setBlogSort();
$id = $this->model->addReturnId($this->param);
$route = RouteMap::setRoute($this->param['url'], RouteMap::SOURCE_BLOG, $id, $this->user['project_id']);
$this->edit(['url'=>$route],['id'=>$id]);
$this->curlDelRoute(['new_route'=>$route]);
}
$this->model->saveExtendInfo($id,$this->param['extend'] ?? [],$this->user['project_id']);
$this->addUpdateNotify(RouteMap::SOURCE_BLOG,$route);
return $this->success(['id'=>$id]);
}
/**
* @remark :设置最新产品的sort排序
* @name :setNewsSort
* @name :setBlogSort
* @author :lyh
* @method :post
* @time :2023/12/25 9:27
*/
public function setNewsSort(){
public function setBlogSort(){
$info = $this->model->orderBy('sort','desc')->first();
if(empty($info)){
return 1;
... ... @@ -101,6 +103,7 @@ class BlogLogic extends BaseLogic
$info['label_name'] = $blogLabelLogic->getLabelName($info['label_id']);
$info['image_link'] = getImageUrl($info['image'],$this->user['storage_type'],$this->user['project_location']);
$info['og_image'] = getImageUrl(empty($info['og_image']) ? $info['image'] : $info['og_image'],$this->user['storage_type'],$this->user['project_location']);
$info['extend'] = $this->model->getExtendInfo($info['id']);
return $this->success($info);
}
... ... @@ -141,6 +144,9 @@ class BlogLogic extends BaseLogic
$this->delRoute($id);
RouteMap::delRoute(RouteMap::SOURCE_BLOG, $id, $this->user['project_id']);
$this->model->del(['id' => $id]);
//删除扩展字段
$extendInfoModel = new BlogExtendInfo();
$extendInfoModel->del(['blog_id'=>$id]);
}
}
DB::commit();
... ... @@ -435,8 +441,8 @@ class BlogLogic extends BaseLogic
}
/**
* @remark :复制新闻
* @name :copyNewsInfo
* @remark :复制
* @name :copyBlogInfo
* @author :lyh
* @method :post
* @time :2024/4/28 14:51
... ...
... ... @@ -77,6 +77,10 @@ class GeoQuestionResLogic extends BaseLogic
* @time :2025/7/4 10:19
*/
public function getResultInfo(){
if(isset($this->param['model'])){//查询记录表
$this->model = new GeoQuestionLog();
unset($this->param['model']);
}
$data = $this->model->read($this->param);
return $this->success($data);
}
... ...
... ... @@ -11,7 +11,7 @@ namespace App\Http\Logic\Bside\News;
use App\Http\Logic\Bside\BaseLogic;
use App\Models\News\NewsExtend;
use App\Models\Product\ExtendInfo;
use App\Models\News\NewsExtendInfo;
class NewsExtendLogic extends BaseLogic
{
... ... @@ -84,7 +84,7 @@ class NewsExtendLogic extends BaseLogic
public function extendDel(){
$info = $this->model->read(['id'=>$this->param['id']]);
//查看当前扩展字段是否设置了值
$extendInfoModel = new ExtendInfo();
$extendInfoModel = new NewsExtendInfo();
$extendInfo = $extendInfoModel->read(['key'=>$info['key']]);
if($extendInfo !== false){
$this->fail('当前扩展字段已有产品在使用,不允许删除');
... ...
... ... @@ -3,12 +3,9 @@
namespace App\Http\Logic\Bside\News;
use App\Enums\Common\Code;
use App\Helper\Arr;
use App\Http\Logic\Bside\BaseLogic;
use App\Models\News\News;
use App\Models\News\NewsCategory;
use App\Models\News\NewsCategory as NewsCategoryModel;
use App\Models\News\NewsExtend;
use App\Models\News\NewsExtendInfo;
use App\Models\RouteMap\RouteMap;
use App\Models\Template\BTemplate;
... ...
... ... @@ -22,6 +22,124 @@ class Blog extends Base
}
return $value;
}
/**
* @remark :扩展字段根据type返回类型
* @name :setTypValues
* @author :lyh
* @method :post
* @time :2023/12/6 14:43
*/
public function getExtendInfo($blog_id){
$extendModel = new BlogExtend();
$list = $extendModel->list(['status'=>1],'id',['id','type','key','title']);
if(empty($list)){
return [];
}
$extendInfoModel = new BlogExtendInfo();
$infoList = $extendInfoModel->list(['blog_id'=>$blog_id],'created_at');
foreach ($list as $k=>$v){
if($v['type'] == 3 || $v['type'] == 4){
$v['values'] = [];
}else{
$v['values'] = '';
}
if(!empty($infoList)){
foreach ($infoList as $values){
if($v['key'] == $values['key']){
$v = $this->setTypValues($v,$values);
break;
}
}
}
$list[$k] = $v;
}
return $list;
}
/**
* @remark :扩展字段根据type返回类型
* @name :setTypValues
* @author :lyh
* @method :post
* @time :2023/12/6 14:43
*/
public function setTypValues($v,$info){
if($v['type'] == 3){
$arr = json_decode($info['values']);
foreach ($arr as $k1=>$v1){
$v1 = (array)$v1;
$v1['url'] = getImageUrl($v1['url']);
$arr[$k1] = $v1;
}
$v['values'] = $arr;
}elseif($v['type'] == 4){
$arr1 = json_decode($info['values']);
foreach ($arr1 as $k1=>$v1){
$v1 = (array)$v1;
if(isset($v1['url'])){
$v1['url'] = getFileUrl($v1['url']);
}else{
$v1 = getFileUrl($v1);
}
$arr1[$k1] = $v1;
}
$v['values'] = $arr1;
}else{
$v['values'] = $info['values'];
}
return $v;
}
/**
* @remark :保存扩展字段
* @name :saveExtend
* @author :lyh
* @method :post
* @time :2023/11/9 15:02
*/
public function saveExtendInfo($blog_id,$extend,$project_id){
//先删除以前的数据
$extendInfoModel = new BlogExtendInfo();
$extendInfoModel->del(['blog_id'=>$blog_id]);
if(empty($extend)) {
return true;
}
foreach ($extend as $k => $v){
if(empty($v['values'])){
continue;
}
$v = $this->saveHandleExtend($v,$blog_id,$project_id);
$extendInfoModel->add($v);
}
return true;
}
/**
* @remark :保存扩展字段时处理数据
* @name :saveHandleExtend
* @author :lyh
* @method :post
* @time :2023/12/6 15:11
*/
public function saveHandleExtend(&$v,$blog_id,$project_id){
unset($v['title']);
if($v['type'] == 3){
foreach ($v['values'] as $k1=>$v1){
$v1['url'] = str_replace_url($v1['url']);
$v['values'][$k1] = $v1;
}
$v['values'] = json_encode($v['values']);
}elseif ($v['type'] == 4){
foreach ($v['values'] as $k1=>$v1){
$v1['url'] = str_replace_url($v1['url']);
$v['values'][$k1] = $v1;
}
$v['values'] = json_encode($v['values']);
}
$v['project_id'] = $project_id;
$v['blog_id'] = $blog_id;
return $v;
}
}
... ...
<?php
/**
* @remark :
* @name :BlogExtend.php
* @author :lyh
* @method :post
* @time :2025/5/26 15:08
*/
namespace App\Models\Blog;
use App\Models\Base;
class BlogExtend extends Base
{
protected $table = 'gl_blog_extend';
protected $connection = 'custom_mysql';
const EXTEND_KEY = 'pd_extended_field_';
/**
* @remark :添加扩展字段
* @name :getKey
* @author :lyh
* @method :post
* @time :2025/5/26 15:39
*/
public function getKey($key = self::EXTEND_KEY,$i = 1){
$info = $this->read(['key'=>$key.$i]);
if($info !== false){
return $this->getKey($key,$i+1);
}else{
return $key.$i;
}
}
}
... ...
<?php
/**
* @remark :
* @name :BlogExtendInfo.php
* @author :lyh
* @method :post
* @time :2025/5/26 15:49
*/
namespace App\Models\Blog;
use App\Models\Base;
class BlogExtendInfo extends Base
{
protected $table = 'gl_blog_extend_info';
protected $connection = 'custom_mysql';
}
... ...
<?php
/**
* @remark :
* @name :NewsExtend.php
* @name :BlogExtend.php
* @author :lyh
* @method :post
* @time :2025/5/26 15:08
... ...
<?php
/**
* @remark :
* @name :NewsExtendInfo.php
* @name :BlogExtendInfo.php
* @author :lyh
* @method :post
* @time :2025/5/26 15:49
... ...
... ... @@ -270,4 +270,21 @@ class AiBlogService
$result = http_post($request_url,json_encode($param,true));
return $result;
}
/**
* @remark :自定义博客
* @name :createCustomBlog
* @author :lyh
* @method :post
* @time :2025/9/16 13:41
*/
public function createCustomBlog($param)
{
$request_url = $this->url.'api/result/save_customer_article';
$param['mch_id'] = $this->mch_id;
$this->sign = $this->generateSign($param,$this->key);
$param['sign'] = $this->sign;
$result = http_post($request_url,json_encode($param,true));
return $result;
}
}
... ...
... ... @@ -47,6 +47,10 @@ Route::any('project_new_url', [\App\Http\Controllers\Api\PrivateController::clas
Route::any('upgrade_project_domain', [\App\Http\Controllers\Api\PrivateController::class, 'upgradeProjectDomain'])->name('api.upgrade_project_domain');
// 询盘通知微信提示hook
Route::any('inquiry_notice_hook', [\App\Http\Controllers\Api\NoticeController::class, 'inquiryNoticeHook'])->name('api.inquiry_notice_hook');
// 获取当日需要推送外链列表
Route::any('get_today_push_external_link', [\App\Http\Controllers\Api\PrivateController::class, 'getExternalLink'])->name('api.today_push_external_link');
// 根据域名获取生成聚合页外链
Route::any('get_external_link_by_domain', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectExternalLink'])->name('api.external_link_by_domain');
// --------------------- 站群服务 ------------------------------------------
// 获取项目信息
... ...
... ... @@ -582,6 +582,7 @@ Route::middleware(['aloginauth'])->group(function () {
Route::any('/save', [Aside\Geo\GeoLinkController::class, 'save'])->name('admin.geo_link_save');
Route::any('/info', [Aside\Geo\GeoLinkController::class, 'info'])->name('admin.geo_link_info');
Route::any('/del', [Aside\Geo\GeoLinkController::class, 'del'])->name('admin.geo_link_del');
Route::any('/downloadGeoLink', [Aside\Geo\GeoLinkController::class, 'downloadGeoLink'])->name('admin.geo_link_downloadGeoLink');
});
});
// 任务相关
... ...
... ... @@ -141,13 +141,18 @@ Route::middleware(['bloginauth'])->group(function () {
Route::any('/category/sort', [\App\Http\Controllers\Bside\Blog\BlogCategoryController::class, 'sort'])->name('blog_category_sort');
Route::any('/category/categoryTopList', [\App\Http\Controllers\Bside\Blog\BlogCategoryController::class, 'categoryTopList'])->name('blog_category_categoryTopList');
//博客标签
Route::any('/label/', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'lists'])->name('blog_lists');
Route::any('/label/add', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'add'])->name('blog_add');
Route::any('/label/info', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'info'])->name('blog_info');
Route::any('/label/edit', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'edit'])->name('blog_edit');
Route::any('/label/del', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'del'])->name('blog_del');
Route::any('/label/batchAdd', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'batchAdd'])->name('blog_batchAdd');
Route::any('/label/status', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'status'])->name('blog_status');
Route::any('/label/', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'lists'])->name('blog_label_lists');
Route::any('/label/add', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'add'])->name('blog_label_add');
Route::any('/label/info', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'info'])->name('blog_label_info');
Route::any('/label/edit', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'edit'])->name('blog_label_edit');
Route::any('/label/del', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'del'])->name('blog_label_del');
Route::any('/label/batchAdd', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'batchAdd'])->name('blog_label_batchAdd');
Route::any('/label/status', [\App\Http\Controllers\Bside\Blog\BlogLabelController::class, 'status'])->name('blog_label_status');
//扩展字段
Route::any('/extend/', [\App\Http\Controllers\Bside\Blog\BlogExtendController::class, 'lists'])->name('blog_extend_lists');
Route::any('/extend/save', [\App\Http\Controllers\Bside\Blog\BlogExtendController::class, 'save'])->name('blog_extend_save');
Route::any('/extend/status', [\App\Http\Controllers\Bside\Blog\BlogExtendController::class, 'status'])->name('blog_extend_status');
Route::any('/extend/del', [\App\Http\Controllers\Bside\Blog\BlogExtendController::class, 'del'])->name('blog_extend_del');
});
//ai指令
Route::prefix('command')->group(function () {
... ... @@ -180,6 +185,7 @@ Route::middleware(['bloginauth'])->group(function () {
Route::any('/blog/getAuthorInfo', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getAuthorInfo'])->name('ai_blog_getAuthorInfo');
Route::any('/blog/saveBlogAuthor', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'saveBlogAuthor'])->name('ai_blog_saveBlogAuthor');
Route::any('/blog/getInfo', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getInfo'])->name('ai_blog_getInfo');
Route::any('/blog/customSaveBlog', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'customSaveBlog'])->name('ai_blog_customSaveBlog');
Route::any('/blog/getAiBlogList', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getAiBlogList'])->name('ai_blog_getAiBlogList');
Route::any('/blog/getAiBlogListInfo', [\App\Http\Controllers\Bside\Ai\AiBlogController::class, 'getAiBlogListInfo'])->name('ai_blog_getAiBlogListInfo');
Route::any('/product/', [\App\Http\Controllers\Bside\Ai\AiProductController::class, 'save'])->name('ai_product_save');
... ...