作者 刘锟

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

... ... @@ -40,8 +40,8 @@ class AiBlogTask extends Command
protected $signature = 'save_ai_blog';
public $updateProject = [];//需更新的列表
public $projectSetting = [];
public $routes = [];//需要更新的路由
/**
* The console command description.
... ... @@ -50,10 +50,14 @@ class AiBlogTask extends Command
*/
protected $description = '查询ai_blog是否已经生成';
/**
* @return bool
* @throws \Exception
*/
public function handle(){
while (true){
//获取任务id
$task_id = $this->getTaskId(2);
$task_id = $this->getTaskId();
if(empty($task_id)){
sleep(300);
continue;
... ... @@ -64,16 +68,15 @@ class AiBlogTask extends Command
}
/**
* @remark :请求方法
* @name :sendRequest
* @author :lyh
* @method :post
* @time :2025/3/19 16:48
* 请求方法
* @param $task_id
* @return bool
* @throws \Exception
*/
public function sendRequest($task_id){
$aiBlogTaskModel = new AiBlogTaskModel();
$item = $aiBlogTaskModel->read(['id'=>$task_id]);
echo date('Y-m-d H:i:s') . '开始->任务id:' . $item['task_id'] . PHP_EOL;
$this->output('start:project ID: ' . $item['project_id'] . ',task ID: ' . $task_id);
//获取配置
$aiSettingInfo = $this->getSetting($item['project_id']);
$aiBlogService = new AiBlogService();
... ... @@ -82,7 +85,7 @@ class AiBlogTask extends Command
$aiBlogService->task_id = $item['task_id'];
//拉取文章数据
$result = $aiBlogService->getDetail();
if(!isset($result['status']) || ($result['status'] != 200)){
if(empty($result['status']) || ($result['status'] != 200)){
if($item['sort'] < 5){
$aiBlogTaskModel->edit(['sort'=>$item['sort'] + 1],['id'=>$item['id']]);
}else{
... ... @@ -90,36 +93,40 @@ class AiBlogTask extends Command
// 钉钉通知
$dingService = new DingService();
$body = [
'keyword' => 'AI_BLOG生成错误',
'msg' => '任务id:'.$item['task_id'].'拉取数据失败'.PHP_EOL.'返回信息:'.json_encode($result,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
'keyword' => 'AI_BLOG获取失败',
'msg' => '任务ID:' . $item['task_id'] . PHP_EOL . '返回信息:' . json_encode($result,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
'isAtAll' => false, // 是否@所有人
];
$dingService->handle($body);
}
echo date('Y-m-d H:i:s'). '错误信息:'.json_encode($result,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES).PHP_EOL;
$this->output('error: 数据获取失败,status:' . $result['status'] . ',message: ' . ($result['message'] ?? 'null'));
return false;
}
//保存当前项目ai_blog数据
ProjectServer::useProject($item['project_id']);
$aiBlogModel = new AiBlog();
$aiBlogInfo = $aiBlogModel->read(['task_id'=>$item['task_id']],['id']);
$aiBlogInfo = $aiBlogModel->read(['task_id'=>$item['task_id']],['id','route']);
if($aiBlogInfo === false){
// 钉钉通知
$dingService = new DingService();
$body = [
'keyword' => 'AI_BLOG生成错误',
'msg' => '子任务不存在:'.$item['task_id'],
'msg' => '任务ID:' . $item['task_id'] . ', 子库获取数据失败, 检查子库数据是否被删除!',
'isAtAll' => false, // 是否@所有人
];
$dingService->handle($body);
echo '任务id不存在:'.$item['task_id'].PHP_EOL;
$this->output('error: 子库获取数据失败, task id: ' . $task_id);
$aiBlogTaskModel->edit(['status'=>9],['id'=>$item['id']]);
DB::disconnect('custom_mysql');
return false;
}
//需要更新的路由
if (!in_array($result['data']['author_id'], $this->updateProject[$item['project_id']] ?? [])) {
$this->updateProject[$item['project_id']][] = $result['data']['author_id'];
}
if (!in_array($aiBlogInfo['route'], $this->routes[$item['project_id']] ?? [])) {
$this->routes[$item['project_id']][] = $aiBlogInfo['route'];
}
//拿到返回的路由查看是否重复
$route = RouteMap::setRoute($result['data']['url'], RouteMap::SOURCE_AI_BLOG, $aiBlogInfo['id'], $item['project_id']);
if($route != $result['data']['url']){
... ... @@ -128,19 +135,16 @@ class AiBlogTask extends Command
$aiBlogModel->edit(['new_title'=>$result['data']['title'], 'image'=>$result['data']['thumb'], 'text'=>$result['data']['section'], 'author_id'=>$result['data']['author_id'],'seo_title'=>$result['data']['title'],'seo_keyword'=>$result['data']['keyword'],'seo_description'=>$result['data']['description'], 'route'=>$route ,'status'=>$aiBlogModel::STATUS_FINISH], ['task_id'=>$item['task_id']]);
DB::disconnect('custom_mysql');
$aiBlogTaskModel->edit(['status'=>$aiBlogModel::STATUS_FINISH],['id'=>$item['id']]);
echo date('Y-m-d H:i:s').'结束->任务id:' . $item['task_id'] . PHP_EOL;
$this->output('success: task id: ' . $task_id);
return true;
}
/**
* @remark :获取任务id
* @name :getTaskId
* @author :lyh
* @method :post
* @time :2025/3/19 16:16
* @param :
* 获取任务id
* @param int $finish_at
* @return mixed
*/
public function getTaskId($finish_at = 1)
public function getTaskId($finish_at = 2)
{
$task_id = Redis::rpop('ai_blog_task');
if (empty($task_id)) {
... ... @@ -148,9 +152,13 @@ class AiBlogTask extends Command
$this->updateProject($this->updateProject);
$this->updateProject = [];
}
if(!empty($this->routes)){
$this->updateRoutes($this->routes);
$this->routes = [];
}
$aiBlogTaskModel = new AiBlogTaskModel();
$finish_at = date('Y-m-d H:i:s', strtotime('-' . $finish_at . ' hour'));
$ids = $aiBlogTaskModel->formatQuery(['status'=>$aiBlogTaskModel::STATUS_RUNNING,'type'=>$aiBlogTaskModel::TYPE_BLOG,'updated_at'=>['<=',$finish_at]])->pluck('id');
$ids = $aiBlogTaskModel->formatQuery(['status'=>$aiBlogTaskModel::STATUS_RUNNING, 'type'=>$aiBlogTaskModel::TYPE_BLOG, 'updated_at'=>['<=',$finish_at]])->pluck('id');
if(!empty($ids)){
foreach ($ids as $id) {
Redis::lpush('ai_blog_task', $id);
... ... @@ -162,11 +170,9 @@ class AiBlogTask extends Command
}
/**
* @remark :更新项目作者页面及列表页
* @name :updateProject
* @author :lyh
* @method :post
* @time :2025/3/4 10:25
* 更新项目作者页面及列表页
* @param $updateProject
* @return bool
*/
public function updateProject($updateProject){
if(empty($updateProject)){
... ... @@ -175,38 +181,45 @@ class AiBlogTask extends Command
foreach ($updateProject as $project_id => $author){
ProjectServer::useProject($project_id);
$aiSettingInfo = $this->getSetting($project_id);
$this->output('sync: list start, project_id: ' . $project_id);
$this->updateBlogList($aiSettingInfo);
$this->output('sync: list end');
//更新作者
$this->output('sync: author start, project_id: ' . $project_id);
foreach ($author as $val){
$this->updateAiBlogAuthor($aiSettingInfo,$val);
$this->updateAiBlogAuthor($aiSettingInfo,$val,$project_id);
}
$this->output('sync: author end');
DB::disconnect('custom_mysql');
$this->curlDelRoute($project_id);
}
return true;
}
/**
* @remark :获取项目配置
* @name :getSetting
* @author :lyh
* @method :post
* @time :2025/2/14 11:27
* 获取项目配置
* @param $project_id
* @return bool
*/
public function getSetting($project_id){
public function getSetting($project_id)
{
$project_setting = $this->projectSetting;
if (FALSE == empty($project_setting[$project_id])){
return $project_setting[$project_id];
}
$projectAiSettingModel = new ProjectAiSetting();
$aiSettingInfo = $projectAiSettingModel->read(['project_id'=>$project_id]);
$this->projectSetting[$project_id] = $aiSettingInfo;
return $aiSettingInfo;
}
/**
* @remark :更新作者的页面
* @name :updateAiBlogAuthor
* @author :lyh
* @method :post
* @time :2025/2/21 11:53
* 更新作者的页面
* @param $aiSettingInfo
* @param $author_id
* @return bool
*/
public function updateAiBlogAuthor($aiSettingInfo,$author_id){
public function updateAiBlogAuthor($aiSettingInfo,$author_id,$project_id){
if(empty($author_id)){
return true;
}
... ... @@ -218,7 +231,12 @@ class AiBlogTask extends Command
if(isset($result['status']) && $result['status'] == 200){
//当前作者的页面
$aiBlogAuthorModel = new AiBlogAuthor();
if(!empty($result['data']['section'])){
$authorInfo = $aiBlogAuthorModel->read(['author_id'=>$author_id],['id','route']);
if($authorInfo !== false && !empty($result['data']['section'])){
//需要更新的路由
if (!in_array($authorInfo['route'], $this->routes[$project_id] ?? [])) {
$this->routes[$project_id][] = $authorInfo['route'];
}
$aiBlogAuthorModel->edit(['text'=>$result['data']['section']],['author_id'=>$author_id]);
}
}
... ... @@ -226,11 +244,9 @@ class AiBlogTask extends Command
}
/**
* @remark :更新列表页
* @name :updateBlogList
* @author :lyh
* @method :post
* @time :2025/2/26 15:42
* 更新列表页
* @param $aiSettingInfo
* @return bool
*/
public function updateBlogList($aiSettingInfo){
$aiBlogService = new AiBlogService();
... ... @@ -268,22 +284,24 @@ class AiBlogTask extends Command
}
/**
* @remark :通知C端生成界面
* @name :sendNotice
* @author :lyh
* @method :post
* @time :2025/3/6 11:51
* 通知C端生成界面
* @param $project_id
* @return bool
*/
public function curlDelRoute($project_id){
public function updateRoutes($routes){
$domainModel = new DomainInfo();
//获取项目域名
$project_model = new Project();
foreach ($routes as $project_id => $route){
$route[] = 'top-blog';
$domain = $domainModel->getProjectIdDomain($project_id);
if(!empty($domain)){
if (empty($domain)) {
$this->output('send: 域名不存在, project id: ' . $project_id);
return true;
}
//判断是否是自建站服务器,如果是,不请求C端接口,数据直接入库
$project_model = new Project();
$project_info = $project_model->read(['id'=>$project_id],['serve_id']);
if(!$project_info){
echo '项目不存在:' . $project_id . PHP_EOL . date('Y-m-d H:i:s');
$this->output('send: 项目不存在, project id: ' . $project_id);
return true;
}
$serve_ip_model = new ServersIp();
... ... @@ -300,23 +318,41 @@ class AiBlogTask extends Command
'status' => ['!=',Notify::STATUS_FINISH_SITEMAP]
];
$notify = $notify_model->read($data,['id']);
if(!$notify){
$domain_array = parse_url($domain);
$data['data'] = Arr::a2s(['domain'=>$domain_array['host'],'url'=>[],'language'=>[]]);
$data['data'] = Arr::a2s(['domain'=>$domain_array['host'],'url'=>$route,'language'=>[]]);
$data['status'] = Notify::STATUS_INIT;
$data['sort'] = 2;
$notify_model->add($data);
}
echo '自建站项目:'.$project_id.'更新';
$this->output('send: 自建站项目, project id: ' . $project_id);
}else{
$url = $domain.'api/update_page/?project_id='.$project_id.'&route=7';
$res = http_get($url);
echo '通知C端:'.json_encode($res,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES).PHP_EOL;
$c_url = $domain.'api/update_page/';
$param = [
'project_id' => $project_id,
'type' => 1,
'route' => 3,
'url' => $route,
'language'=> [],
'is_sitemap' => 0
];
$res = http_post($c_url, json_encode($param,true));
$this->output('notify: project id: ' . $project_id . ', result: ' . json_encode($res,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
}
}else{
echo '域名不存在:' . $project_id . PHP_EOL . date('Y-m-d H:i:s');
}
return true;
}
/**
* 输入日志
* @param $message
* @return bool
*/
public function output($message)
{
$message = date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;
echo $message;
file_put_contents(storage_path('logs/AiBlog/') . date('Ymd') . '.log', $message, FILE_APPEND);
return true;
}
}
... ...
... ... @@ -11,6 +11,7 @@ namespace App\Console\Commands\DayCount;
use App\Models\Manage\ManageHr;
use App\Models\Project\Project;
use App\Models\RankData\RankDataLog;
use Carbon\Carbon;
use App\Models\HomeCount\AfterCount as AfterCountModel;
use Illuminate\Console\Command;
... ... @@ -58,26 +59,59 @@ class AfterCount extends Command
public function _action(){
$this->managerHrModel = new ManageHr();
$projectModel = new Project();
$rankDataLogModel = new RankDataLog();
$todayMidnight = date('Y-m-d 00:00:00', strtotime('today'));
$saveData = [];
$projectIdArr = $rankDataLogModel->selectField(['is_compliance'=>1,'lang'=>null,'date'=>date('Y-m-d', strtotime('-3 months'))],'project_id');//3个月前达标的项目id
foreach ($this->after_manager as $key => $valM){
$idArr = $this->managerHrModel->selectField(['name'=>['in',$valM]],'id');
$project_count = $projectModel->where('gl_project.extend_type',0)->where('gl_project.delete_status',0)->where('gl_project.created_at','<=',$todayMidnight)->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)->whereIn('gl_project.type',[2,4])->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')->count();
$qualified_count = $projectModel->where('gl_project.extend_type',0)->where('gl_project.delete_status',0)->where('gl_project.created_at','<=',$todayMidnight)->where('gl_project.is_remain_today',1)->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)->whereIn('gl_project.type',[2,4])->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')->count();
$project_count = $projectModel->where('gl_project.extend_type',0)
->where('gl_project.delete_status',0)
->where('gl_project.created_at','<=',$todayMidnight)
->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)
->whereIn('gl_project.type',[2,4])
->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')->count();
$qualified_count = $projectModel->where('gl_project.extend_type',0)
->where('gl_project.delete_status',0)
->where('gl_project.created_at','<=',$todayMidnight)
->where('gl_project.is_remain_today',1)
->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)
->whereIn('gl_project.type',[2,4])
->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')->count();
$rate = number_format($qualified_count / $project_count, 2);
$threeMonthsAgo = date('Y-m-d 00:00:00', strtotime('-3 months'));
$three_project_count = $projectModel->where('gl_project.extend_type',0)->where('gl_project.delete_status',0)->where('gl_project.created_at','<=',$threeMonthsAgo)->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)->whereIn('gl_project.type',[2,4])->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')->count();
$three_qualified_count = $projectModel->where('gl_project.extend_type',0)->where('gl_project.delete_status',0)->where('gl_project.created_at','<=',$threeMonthsAgo)->where('gl_project.is_remain_today',1)->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)->whereIn('gl_project.type',[2,4])->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')->count();
$three_project_count = $projectModel->where('gl_project.extend_type',0)
->where('gl_project.delete_status',0)
->where('gl_project.created_at','<=',$threeMonthsAgo)
->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)
->whereIn('gl_project.type',[2,4])
->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')->count();
$three_qualified_count = $projectModel->where('gl_project.extend_type',0)
->whereIn('gl_project.id',$projectIdArr)
->where('gl_project.delete_status',0)
->where('gl_project.created_at','<=',$threeMonthsAgo)
->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)
->whereIn('gl_project.type',[2,4])
->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')->count();
$three_rate = number_format($three_qualified_count / $three_project_count, 2);
$data = $projectModel->where('gl_project.extend_type',0)
->where('gl_project.delete_status',0)
->where('gl_project.created_at','<=',$todayMidnight)
->where('gl_project.is_remain_today',1)
->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)
->whereIn('gl_project.type',[2,4])
->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')
->pluck('gl_project.title')->toArray();
$saveData[] = [
'date'=>date('Y-m-d', strtotime('yesterday')),
'type'=> $key,
'project_count'=>$project_count,
'qualified_count'=>$qualified_count,
'rate'=>$rate,
'three_project_count'=>$three_project_count,
'three_qualified_count'=>$three_qualified_count,
'three_rate'=>$three_rate,
'three_project_count'=>$project_count - $three_project_count,
'three_qualified_count'=>$qualified_count - $three_qualified_count,
'three_rate'=>$rate - $three_rate,
'data' => json_encode($data,true)
];
}
return $saveData;
... ...
... ... @@ -125,7 +125,9 @@ class RemainDay extends Command
continue;
}
$diff = time() - strtotime($opInfo['start_date'] ?? $item['uptime']);
$remain_day = $deploy_build['service_duration'] - floor($diff / (60 * 60 * 24));
$compliance_day = floor($diff / (60 * 60 * 24));
$remain_day = $deploy_build['service_duration'] - $compliance_day;
}else{
$compliance_day = ($item['finish_remain_day'] ?? 0);
$remain_day = $deploy_build['service_duration'] - $compliance_day;
... ... @@ -134,7 +136,8 @@ class RemainDay extends Command
//普通建站项目
if($item['uptime']){
$diff = time() - strtotime($item['uptime']);
$remain_day = $deploy_build['service_duration'] - floor($diff / (60 * 60 * 24));
$compliance_day = floor($diff / (60 * 60 * 24));
$remain_day = $deploy_build['service_duration'] - $compliance_day;
}else{
$remain_day = $deploy_build['service_duration'];
}
... ... @@ -144,7 +147,7 @@ class RemainDay extends Command
$remain_day = 0;
$extend_type = Project::TYPE_FIVE;
}
$this->project->edit(['remain_day'=>$remain_day,'extend_type'=>$extend_type],['id'=>$item['id']]);
$this->project->edit(['remain_day'=>$remain_day,'extend_type'=>$extend_type,'finish_remain_day'=>$compliance_day ?? 0],['id'=>$item['id']]);
echo 'end->项目id:' . $item['id'] . '执行时间:'. date('Y-m-d H:i:s') . PHP_EOL;
}
return true;
... ...
... ... @@ -16,6 +16,8 @@ use App\Models\Product\CategoryRelated;
use App\Models\Product\Product;
use App\Models\ProjectAssociation\ProjectAssociation;
use App\Models\RouteMap\RouteMap;
use App\Models\Visit\Visit;
use App\Models\Visit\VisitItem;
use App\Models\Workchat\MessagePush;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
... ... @@ -40,96 +42,115 @@ class DownloadProject extends Command
protected $description = '导出项目数据';
public function handle(){
$v6WeekModel = new V6WeeklyReport();
$lists = $v6WeekModel->list([],'id',['*'],'desc',100);
echo date('Y-m-d H:i:s') . 'start' . PHP_EOL;
foreach ($lists as $data){
$this->workChatMessage($data,$data['project_id']);
}
ProjectServer::useProject(535);
$this->model = new Visit();
$data = $this->importVisit();
dd($data);
DB::disconnect('custom_mysql');
echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;
return true;
}
public function downloadProduct()
/**
* @remark :导出明细
* @name :importVisit
* @author :lyh
* @method :post
* @time :2025/4/8 11:34
*/
public function importVisit()
{
$product = new Product();
// $filed = ['id', 'project_id', 'title' ,'thumb' , 'route' ,'intro','content',
// 'category_id', 'status','seo_mate'];
$filed = ['id','title'];
$this->order = 'sort';
$lists = $product->list(['status'=>1],'id',$filed);
if(!empty($lists)){
// $cate_data = $this->getCategoryList();//分类
foreach ($lists as $k => $v){
echo date('Y-m-d H:i:s') . '产品id:'.$v['id'] . PHP_EOL;
// $v['url'] = 'https://www.autsikinta.com/' . getRouteMap(RouteMap::SOURCE_PRODUCT,$v['id']);
// $v['category_id_text'] = $this->categoryName($v['id'],$cate_data);
// //ToDo::处理图片及文件
// if(!empty($v['thumb']) && !empty($v['thumb']['url'])){
// $v['images'] = getImageUrl($v['thumb']['url']);
// }else{
// $v['images'] = '';
// }
$lists[$k] = $v;
}
$lists = $this->model->list();
if(!empty($lists) && !empty($lists['list'])){
foreach ($lists as $v){
$customer_visit_id[] = $v['id'];
}
return $lists;
$itemModel = new VisitItem();
$itemList = $itemModel->list(['customer_visit_id'=>['in',$customer_visit_id]],['customer_visit_id','url']);
foreach ($lists as $key => $value){
$sub = [];
foreach ($itemList as $sonValue){
if($value['id'] == $sonValue['customer_visit_id']){
$sub[] = $sonValue;
}
public function categoryName($product_id,$data){
$cateRelatedModel = new CategoryRelated();
$category_id = $cateRelatedModel->where('product_id',$product_id)->pluck('cate_id')->toArray();
$category_name = '';
if(!empty($category_id) && !empty($data)){
foreach ($category_id as $v){
if(isset($data[$v])){
$category_name .= $data[$v].',';
}
$value['sub'] = $sub;
$lists[$key] = $value;
}
$category_name = trim($category_name,',');
}
return $category_name;
return $lists;
}
/**
* @remark :获取所有分类
* @name :getCategoryList
* @remark :导出访问明细
* @name :exportData
* @author :lyh
* @method :post
* @time :2023/9/14 13:56
* @time :2025/4/8 11:32
*/
public function getCategoryList(){
$data = Common::get_user_cache('product_category',1225);
if(empty($data)){
$categoryModel = new Category();
$data = [];
$cateList = $categoryModel->list(['project_id'=>1225],['id','title']);
if(!empty($cateList)){
foreach ($cateList as $value){
$data[$value['id']] = $value['title'];
}
}
Common::set_user_cache($data,'product_category',1225);
public function exportData($data){
// 创建一个新的 Excel 电子表格实例
$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', '国家');
$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']);
$rowCount++;
}
return $data;
// 创建一个新的 Excel Writer 对象
$writer = new Xlsx($spreadsheet);
$filename = time().'.xlsx';
// 设置导出文件的保存路径和文件名
$filePath = public_path('upload/excel/'.$filename);
// 导出 Excel 文件
$writer->save($filePath);
echo date('Y-m-d H:i:s') . 'file_link:'.url('upload/excel/'.$filename) . PHP_EOL;
// 返回导出文件的响应
return ['file_link'=>url('upload/excel/'.$filename)];
}
// public function exportData($data){
// // 创建一个新的 Excel 电子表格实例
// $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('A1', '产品名称');
//// $sheet->setCellValue('B1', '产品短描述');
//// $sheet->setCellValue('C1', '产品内容');
//// $sheet->setCellValue('D1', '产品路由');
//// $sheet->setCellValue('E1', '产品分类');
//// $sheet->setCellValue('F1', '产品状态');
//// $sheet->setCellValue('G1', '产品主图');
//// $sheet->setCellValue('H1', '产品seo_title');
//// $sheet->setCellValue('I1', '产品seo_keyword');
//// $sheet->setCellValue('J1', '产品seo_title');
// $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('A' . $rowCount, $v['title']);
//// $sheet->setCellValue('B' . $rowCount, $v['intro']);
//// $sheet->setCellValue('C' . $rowCount, $v['content']);
//// $sheet->setCellValue('D' . $rowCount, $v['url']);
//// $sheet->setCellValue('E' . $rowCount, $v['category_id_text']);
//// $sheet->setCellValue('F' . $rowCount, '发布中');
//// $sheet->setCellValue('G' . $rowCount, $v['images']);
//// $sheet->setCellValue('H' . $rowCount, $v['seo_mate']['title']);
//// $sheet->setCellValue('I' . $rowCount, $v['seo_mate']['keyword']);
//// $sheet->setCellValue('J' . $rowCount, $v['seo_mate']['description']);
// $rowCount++;
// }
// // 创建一个新的 Excel Writer 对象
... ... @@ -143,69 +164,28 @@ class DownloadProject extends Command
// // 返回导出文件的响应
// return ['file_link'=>url('upload/excel/'.$filename)];
// }
public function exportData($data){
// 创建一个新的 Excel 电子表格实例
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 添加表头
$sheet->setCellValue('A1', '产品名称');
// $sheet->setCellValue('B1', '产品短描述');
// $sheet->setCellValue('C1', '产品内容');
// $sheet->setCellValue('D1', '产品路由');
// $sheet->setCellValue('E1', '产品分类');
// $sheet->setCellValue('F1', '产品状态');
// $sheet->setCellValue('G1', '产品主图');
// $sheet->setCellValue('H1', '产品seo_title');
// $sheet->setCellValue('I1', '产品seo_keyword');
// $sheet->setCellValue('J1', '产品seo_title');
$rowCount = 2;
foreach ($data as $v) {
$sheet->setCellValue('A' . $rowCount, $v['title']);
// $sheet->setCellValue('B' . $rowCount, $v['intro']);
// $sheet->setCellValue('C' . $rowCount, $v['content']);
// $sheet->setCellValue('D' . $rowCount, $v['url']);
// $sheet->setCellValue('E' . $rowCount, $v['category_id_text']);
// $sheet->setCellValue('F' . $rowCount, '发布中');
// $sheet->setCellValue('G' . $rowCount, $v['images']);
// $sheet->setCellValue('H' . $rowCount, $v['seo_mate']['title']);
// $sheet->setCellValue('I' . $rowCount, $v['seo_mate']['keyword']);
// $sheet->setCellValue('J' . $rowCount, $v['seo_mate']['description']);
$rowCount++;
}
// 创建一个新的 Excel Writer 对象
$writer = new Xlsx($spreadsheet);
$filename = time().'.xlsx';
// 设置导出文件的保存路径和文件名
$filePath = public_path('upload/excel/'.$filename);
// 导出 Excel 文件
$writer->save($filePath);
echo date('Y-m-d H:i:s') . 'file_link:'.url('upload/excel/'.$filename) . PHP_EOL;
// 返回导出文件的响应
return ['file_link'=>url('upload/excel/'.$filename)];
}
public function downloadItem($filed = ['id','depth','created_at','referrer_url','url','device_port','country','ip']){
$visitModel = new Visit();
$page = 1;
$pageSize = 3000;
$lists = $visitModel->lists(['updated_date'=>['between',['2025-02-01','2025-02-31']]],$page,$pageSize,'id',$filed);
foreach ($lists as $v){
$customer_visit_id[] = $v['id'];
}
$itemModel = new VisitItem();
$itemList = $itemModel->list(['customer_visit_id'=>['in',$customer_visit_id]],['customer_visit_id','url']);
foreach ($lists as $key => $value){
$sub = [];
foreach ($itemList as $sonValue){
if($value['id'] == $sonValue['customer_visit_id']){
$sub[] = $sonValue;
}
}
$value['sub'] = $sub;
$lists[$key] = $value;
}
return $lists;
}
//
// public function downloadItem($filed = ['id','depth','created_at','referrer_url','url','device_port','country','ip']){
// $visitModel = new Visit();
// $page = 1;
// $pageSize = 3000;
// $lists = $visitModel->lists(['updated_date'=>['between',['2025-02-01','2025-02-31']]],$page,$pageSize,'id',$filed);
// foreach ($lists as $v){
// $customer_visit_id[] = $v['id'];
// }
// $itemModel = new VisitItem();
// $itemList = $itemModel->list(['customer_visit_id'=>['in',$customer_visit_id]],['customer_visit_id','url']);
// foreach ($lists as $key => $value){
// $sub = [];
// foreach ($itemList as $sonValue){
// if($value['id'] == $sonValue['customer_visit_id']){
// $sub[] = $sonValue;
// }
// }
// $value['sub'] = $sub;
// $lists[$key] = $value;
// }
// return $lists;
// }
}
... ...
... ... @@ -52,9 +52,9 @@ class LyhImportTest extends Command
* @time :2023/11/20 15:13
*/
public function handle(){
ProjectServer::useProject(2878);
ProjectServer::useProject(3283);
echo date('Y-m-d H:i:s') . 'start' . PHP_EOL;
$this->importProductCategory('https://ecdn6.globalso.com/upload/p/2878/file/2025-03/products.csv',2878);
$this->importProductCategory('https://ecdn6.globalso.com/upload/p/3283/file/2025-04/zhouyongpaxu.csv',3283);
DB::disconnect('custom_mysql');
echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;
}
... ... @@ -93,18 +93,19 @@ class LyhImportTest extends Command
continue;
}
try {
$id = $categoryModel->addReturnId(['project_id'=>$project_id,'title'=>$val[1],'seo_title'=>$val[0],'seo_des'=>$val[2]]);
$pid = 0;
if($val[2] != 0){
//查询上级id
$pidCate = $categoryModel->read(['seo_title'=>$val[2]]);
if($pidCate !== false){
$pid = $pidCate['id'];
}
}
$route = RouteMap::setRoute($val[1],RouteMap::SOURCE_PRODUCT_CATE,$id,$project_id);
$categoryModel->edit(['route'=>$route,'pid'=>$pid],['id'=>$id]);
echo date('Y-m-d H:i:s') . '产品分类id:'. $id.PHP_EOL;
$categoryModel->edit(['sort'=>$val[1]],['title'=>$val[0]]);
// $id = $categoryModel->addReturnId(['project_id'=>$project_id,'title'=>$val[1],'seo_title'=>$val[0],'seo_des'=>$val[2]]);
// $pid = 0;
// if($val[2] != 0){
// //查询上级id
// $pidCate = $categoryModel->read(['seo_title'=>$val[2]]);
// if($pidCate !== false){
// $pid = $pidCate['id'];
// }
// }
// $route = RouteMap::setRoute($val[1],RouteMap::SOURCE_PRODUCT_CATE,$id,$project_id);
// $categoryModel->edit(['route'=>$route,'pid'=>$pid],['id'=>$id]);
echo date('Y-m-d H:i:s') . '产品分类id:'.PHP_EOL;
}catch (\Exception $e){
echo date('Y-m-d H:i:s') . '跳过的名称:'. $val[1];
continue;
... ...
... ... @@ -7,6 +7,8 @@
*/
namespace App\Console\Commands\Product;
use App\Helper\Common;
use App\Models\Com\NoticeLog;
use App\Models\Product\Keyword;
use App\Models\Project\AggregateKeyword;
use App\Services\ProjectServer;
... ... @@ -56,6 +58,8 @@ class OptimizeSetKeywordSync extends Command
$item->status = AggregateKeyword::STATUS_FINISH;
$item->save();
}
Common::del_user_cache('product_keyword',$this->user['project_id']);
NoticeLog::createLog(NoticeLog::TYPE_INIT_KEYWORD, ['project_id' => $this->user['project_id']]);
return true;
}
... ...
... ... @@ -281,13 +281,12 @@ class WeekProject extends Command
foreach ($arr as $key => $val){
$content .= ($key+1).','.$val.PHP_EOL.PHP_EOL;
}
$timestamp = strtotime('tomorrow 9:00 AM');
$tomorrowNineAM = date('Y-m-d H:i:s', $timestamp);
$tomorrowNineAM = date('Y-m-d 09:00:00', time());
if(empty($content)){
return true;
}
$tips = 'Tips:'.PHP_EOL.'1、全球搜V6.0系统提供网页TDK、H标签、Img标签等用户自定义编辑接口且辅以AI创作工具,用户可进一步对相关优化设置进行精细化优化与调整;'.PHP_EOL.'2、全球搜V6.0系统提供小语种页面精准校对翻译功能,用户可进一步对已翻译小语种页面进行人工翻译校对;'.PHP_EOL.'3、全球搜V6.0系统支持绑定Facebook、LinkedIn、X(原Twitter)等社媒账号,可一键同步转发网站上发布的产品和新闻至社媒账号动态,建议用户用起来哦;'.PHP_EOL.'4、如用户有较丰富的企业、产品、服务相关视频素材,全球搜建议用户及时创建YouTube主页,并在YouTube和网站相关网页上同步发布视频;';
$message = "【全球搜V6.0周报】- 项目ID:" . PHP_EOL . $content . PHP_EOL . $tips;
$message = "【全球搜V6.0周报】" . PHP_EOL . $content . PHP_EOL . $tips;
$param = [
'project_id'=>$project_id,
'friend_id'=>$friend_id,
... ...
... ... @@ -1174,3 +1174,41 @@ function getDeployOptimize($project_id){
return $info;
}
/**
* @remark :返回分页数据
* @name :paginateArray
* @author :lyh
* @method :post
* @time :2025/4/1 9:41
*/
function paginateArray($array, $page = 1, $pageSize = 20) {
$totalItems = count($array);
$totalPages = ceil($totalItems / $pageSize);
// 确保页码有效
$page = max(1, min($page, $totalPages));
$offset = ($page - 1) * $pageSize;
$data = array_slice($array, $offset, $pageSize);
return [
'list' => $data,
'page' => $page,
'size' => $pageSize,
'total_page' => $totalPages,
'total' => $totalItems,
];
}
/**
* @remark :获取域名
* @name :getDomain
* @author :lyh
* @method :post
* @time :2025/4/3 16:19
*/
function getDomain($url) {
$parsedUrl = parse_url($url);
return $parsedUrl['host'] ?? $url; // 如果解析失败,返回原始 URL
}
... ...
<?php
/**
* @remark :
* @name :AfterCountController.php
* @author :lyh
* @method :post
* @time :2025/4/8 9:56
*/
namespace App\Http\Controllers\Aside\Optimize;
use App\Enums\Common\Code;
use App\Http\Controllers\Aside\BaseController;
use App\Models\HomeCount\AfterCount;
class AfterCountController extends BaseController
{
/**
* @remark :售后数据统计
* @name :getAfterCount
* @author :lyh
* @method :post
* @time :2025/3/27 17:21
*/
public function getAfterCount(AfterCount $afterCount){
$list = $afterCount->lists($this->map,$this->page,$this->row);
$this->response('success',Code::SUCCESS,$list);
}
/**
* @remark :获取当前售后数据详情
* @name :getAfterCountInfo
* @author :lyh
* @method :post
* @time :2025/4/8 9:56
*/
public function getAfterCountInfo(AfterCount $afterCount){
$this->request->validate([
'id' => 'required',
], [
'id.required' => 'id不能为空',
]);
$info = $afterCount->read($this->map,['id','data']);
$info['data'] = json_decode($info['data'],true);
$this->response('success',Code::SUCCESS,$info);
}
}
... ...
... ... @@ -67,6 +67,7 @@ class OnlineController extends BaseController
'gl_project.is_upgrade AS is_upgrade',
'gl_project_online_check.id AS online_check_id',
'gl_project_online_check.question AS question',
'gl_project_online_check.go_question AS go_question',
'gl_project_online_check.optimist_status AS optimist_status',
'gl_project_online_check.qa_status AS qa_status',
'gl_project_payment.amount AS amount',
... ... @@ -110,7 +111,8 @@ class OnlineController extends BaseController
$item['optimize_assist'] = $manageModel->getName($item['optimize_assist_mid']);
$item['optimize_tech'] = $manageModel->getName($item['optimize_tech_mid']);
$item['quality_mid_name'] = $manageModel->getName($item['quality_mid']);
$item['plan'] = Project::planMap()[$item['plan']];
$plan = Project::planMap();
$item['plan'] = $plan[$item['plan']] ?? 0;
$item['created_at'] = date('Y年m月d日', strtotime($item['created_at']));
$item['autologin_code'] = getAutoLoginCode($item['id']);
$item['product_num'] = $data['product'] ?? 0;
... ...
... ... @@ -147,6 +147,8 @@ class OptimizeController extends BaseController
$data = APublicModel::getNumByProjectId($item['id']);
}
$manageModel = new ManageHr();
$plan = Project::planMap();
$seo_plan = Project::seoMap();
$item['channel'] = Channel::getChannelText($item['channel']['user_id'] ?? 0);
$item['build_leader'] = $manageModel->getName($item['leader_mid']);
$item['build_manager'] = $manageModel->getName($item['manager_mid']);
... ... @@ -157,7 +159,8 @@ class OptimizeController extends BaseController
$item['optimize_assist'] = $manageModel->getName($item['optimize_assist_mid']);
$item['optimize_tech'] = $manageModel->getName($item['optimize_tech_mid']);
$item['quality_mid_name'] = $manageModel->getName($item['quality_mid']);
$item['plan'] = Project::planMap()[$item['plan']];
$item['plan'] = $plan[$item['plan']] ?? 0;
$item['seo_plan'] = $seo_plan[$item['plan']] ?? 0;
$item['created_at'] = date('Y年m月d日', strtotime($item['cooperate_date']));
$item['autologin_code'] = getAutoLoginCode($item['id']);
$item['domain'] = 'https://'.$item['domain'].'/';
... ... @@ -213,6 +216,7 @@ class OptimizeController extends BaseController
'gl_project_deploy_build.tech_mid AS tech_mid',
'gl_project_deploy_build.test_domain AS test_domain',
'gl_project_deploy_build.plan AS plan',
'gl_project_deploy_build.seo_plan AS seo_plan',
'gl_project_deploy_optimize.dept_id AS optimize_dept_id',
'gl_project_deploy_optimize.manager_mid AS optimize_manager_mid',
'gl_project_deploy_optimize.optimist_mid AS optimize_optimist_mid',
... ... @@ -246,7 +250,10 @@ class OptimizeController extends BaseController
$query = $query->where('gl_project.title','like','%'.$this->map['title'].'%');
}
if(isset($this->map['site_status'])){
$query = $query->where('gl_project.site_status',$this->map['site_status']);
$query = $query->where('gl_project_deploy_build.site_status',$this->map['site_status']);
}
if(isset($this->map['seo_plan'])){
$query = $query->where('gl_project_deploy_build.seo_plan',$this->map['seo_plan']);
}
if(isset($this->map['main_lang_id'])){
$query = $query->where('gl_project.main_lang_id',$this->map['main_lang_id']);
... ... @@ -484,7 +491,12 @@ class OptimizeController extends BaseController
$this->fail('请先设置域名');
}
$domain = 'https://' . $domainInfo['domain'] . '/';
$data = [];
$data = [
'ai_blog' => [],
'product' => [],
'product_category'=>[],
'product_keyword' => [],
];
ProjectServer::useProject($this->param['project_id']);
$productModel = new Product();
$this->processChunkedList($productModel, ['status' => $productModel::STATUS_ON], ['id', 'title', 'route'], $domain, $data, 'product');
... ... @@ -581,15 +593,5 @@ class OptimizeController extends BaseController
$this->response('success',Code::SUCCESS,$resultData);
}
/**
* @remark :售后数据统计
* @name :getAfterCount
* @author :lyh
* @method :post
* @time :2025/3/27 17:21
*/
public function getAfterCount(AfterCount $afterCount){
$list = $afterCount->lists($this->map,$this->page,$this->row);
$this->response('success',Code::SUCCESS,$list);
}
}
... ...
... ... @@ -292,6 +292,9 @@ class ProjectController extends BaseController
if(isset($this->map['plan'])){
$query = $query->where('gl_project_deploy_build.plan',$this->map['plan']);
}
if(isset($this->map['seo_plan'])){
$query = $query->where('gl_project_deploy_build.seo_plan',$this->map['seo_plan']);
}
if(isset($this->map['site_status'])){
$query = $query->where('gl_project.site_status',$this->map['site_status']);
}
... ... @@ -415,7 +418,10 @@ class ProjectController extends BaseController
$item['optimize_assist'] = $manageModel->getName($item['optimize_assist_mid']);
$item['optimize_tech'] = $manageModel->getName($item['optimize_tech_mid']);
$item['quality_mid_name'] = $manageModel->getName($item['quality_mid']);
$item['plan'] = Project::planMap()[$item['plan']];
$planMap = Project::planMap();
$seoPlanMap = Project::seoMap();
$item['plan'] = $planMap[$item['plan']] ?? '';
$item['seo_plan'] = $seoPlanMap[$item['seo_plan']] ?? '';
$item['created_at'] = date('Y年m月d日', strtotime($item['cooperate_date']));
$item['autologin_code'] = getAutoLoginCode($item['id']);
$domainModel = new DomainInfo();
... ...
... ... @@ -67,6 +67,7 @@ class RenewProjectController extends BaseController
}else{
$map['type'] = $param['type'];
}
$map['extend_type'] = 0;
$map['remain_day'] = ['<=',15];
return $map;
}
... ...
... ... @@ -215,7 +215,7 @@ class CNoticeController extends BaseController
$project_id = $this->user['project_id'];
$type = intval($request->input('type', 1));
$route = intval($request->input('page', 1));
if($type == 2 && in_array($route,[4,6])){
if(($this->user['is_upgrade'] == 0) && ($type == 2) && in_array($route,[4,6])){
$this->fail('聚合页翻译请联系管理员');
}
$url = $request->input('url', []);
... ...
... ... @@ -65,11 +65,11 @@ class GoogleKeywordInsightController extends BaseController
$detailModel = new GoogleKeywordInsightDetail();
$resultData = [];
if(!empty($array)){
$resultData = $this->paginateArray($array,$this->page,$this->row);
$resultData = paginateArray($array,$this->page,$this->row);
$detailList = $detailModel->list(['search'=>['in',$resultData['list']]]);
foreach ($resultData['list'] as $key => $item){
$result['keyword'] = $item;
$searchKeyword = $this->getSearchDetail($item,$detailList);
$searchKeyword = $detailModel->getSearchDetail($item,$detailList);
if($searchKeyword === false){
$result['data'] = [];
}else{
... ... @@ -101,44 +101,4 @@ class GoogleKeywordInsightController extends BaseController
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :查看当前数据是否存在数组中
* @name :getSearchDetail
* @author :lyh
* @method :post
* @time :2025/4/1 9:56
*/
public function getSearchDetail($keyword,$detailList){
if(!empty($detailList)){
foreach ($detailList as $value){
if($keyword == $value['search']){
return $value;
}
}
}
return [];
}
/**
* @remark :返回分页数据
* @name :paginateArray
* @author :lyh
* @method :post
* @time :2025/4/1 9:41
*/
public function paginateArray($array, $page = 1, $pageSize = 20) {
$totalItems = count($array);
$totalPages = ceil($totalItems / $pageSize);
// 确保页码有效
$page = max(1, min($page, $totalPages));
$offset = ($page - 1) * $pageSize;
$data = array_slice($array, $offset, $pageSize);
return [
'list' => $data,
'page' => $page,
'size' => $pageSize,
'total_page' => $totalPages,
'total' => $totalItems,
];
}
}
... ...
<?php
/**
* @remark :
* @name :GoogleLinkController.php
* @author :lyh
* @method :post
* @time :2025/4/3 15:05
*/
namespace App\Http\Controllers\Bside\GoogleKeyword;
use App\Enums\Common\Code;
use App\Http\Controllers\Bside\BaseController;
use App\Models\GoogleSearch\GoogleLink;
use App\Services\GoogleLinkService;
class GoogleLinkController extends BaseController
{
/**
* @remark :外链数据
* @name :getLink
* @author :lyh
* @method :post
* @time :2025/4/3 16:09
*/
public function getLink(){
$linkModel = new GoogleLink();
$lists = $linkModel->lists($this->map,$this->page,$this->row,'id',['url','moz_da','status','google_search','date','project_id','domain']);
if(empty($lists['list'])){
$linkService = new GoogleLinkService();
$data = $linkService->linkPageData($this->user['domain'],$this->user['project_id']);
$lists = paginateArray($data,$this->page,$this->row);
}
$lists['y_total'] = $linkModel->counts(['status'=>1]);
$lists['n_total'] = $linkModel->counts(['status'=>0]);
$this->response('success',Code::SUCCESS,$lists);
}
}
... ...
... ... @@ -37,7 +37,7 @@ class GoogleSearchController extends BaseController
//查询详情数据
$searchDetailModel = new GoogleSearchDetail();
$this->map['project_id']= 711;
$data = $searchDetailModel->lists($this->map,$this->page,$this->row,'impressions');
$data = $searchDetailModel->lists($this->map,$this->page,$this->row,'clicks',['keys','click_rate','impressions_rate']);
if(!empty($data)){
if($this->param['type'] == 'country'){
$codeCountryModel = new GoogleCodeCountry();
... ...
... ... @@ -26,6 +26,10 @@ class ChatController extends BaseController
*/
public function list(Chat $chat){
$list = $chat->lists(['user_id'=>$this->user['id'],'status'=>1],$this->page,$this->row);
$chatItem = new ChatItem();
foreach ($list as $k => $v){
$chatItem->orderBy('id', 'desc')->first();
}
$this->response('success',Code::SUCCESS,$list);
}
... ... @@ -78,4 +82,23 @@ class ChatController extends BaseController
$data = $chat->edit(['status'=>0],['id'=>$this->param['id']]);
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :修改标题
* @name :saveChat
* @author :lyh
* @method :post
* @time :2025/4/7 11:15
*/
public function saveChat(Chat $chat){
$this->request->validate([
'id'=>['required'],
'input_content'=>['required'],
],[
'id.required' => 'id不能为空',
'input_content.required' => '标题不能为空',
]);
$data = $chat->edit(['input_content'=>$this->param['input_content']],['id'=>$this->param['id']]);
$this->response('success',Code::SUCCESS,$data);
}
}
... ...
... ... @@ -152,7 +152,7 @@ class LoginController extends BaseController
],[
'str.required' => '翻译字符串不能为空',
]);
$str = Translate::tran($this->param['str'], 'en') ?? '';
$str = Translate::tran($this->param['str'], $this->param['language'] ?? 'en') ?? '';
if(is_array($str)){
$str = $str[0];
}
... ...
... ... @@ -201,6 +201,40 @@ class ProjectLogic extends BaseLogic
}
/**
* @remark :保存上线审核问题
* @name :saveOnlineCheck
* @author :lyh
* @method :post
* @time :2025/4/3 16:41
*/
public function saveOnlineCheck($project_id,$optimist_mid,$quality_mid,$question,$go_question){
if(($optimist_mid == 0) || ($quality_mid == 0)){
$this->fail('请先选择优化师和品控,在提交审核');
}
$onlineCheckModel = new OnlineCheck();
$onlineInfo = $onlineCheckModel->read(['project_id'=>$project_id]);
if($onlineInfo === false){
$data = [
'project_id' => $project_id,
'created_manage_id' => $this->manager['id'],
'optimist_mid' => $optimist_mid,
'qa_mid' => $quality_mid,
'created_at'=>date('Y-m-d H:i:s'),
'question'=>$question,
'go_question'=>$go_question
];
$onlineCheckModel->addReturnId($data);
}else{
$data = [
'question'=>$question,
'go_question'=>$go_question
];
$onlineCheckModel->edit($data,['project_id'=>$project_id]);
}
return true;
}
/**
* @remark :开启白帽验证产数
* @name :checkAiBlog
* @author :lyh
... ... @@ -451,7 +485,7 @@ class ProjectLogic extends BaseLogic
}
/**
* @remark :保存seo白帽类型
* @remark :保存seo白帽类型,上线保存一条审核记录,
* @name :saveSeoPlan
* @author :lyh
* @method :post
... ... @@ -461,10 +495,6 @@ class ProjectLogic extends BaseLogic
$onlineCheckModel = new OnlineCheck();
if(($plan == Project::TYPE_ZERO) && ($seo_plan == Project::TYPE_ONE) && ($type == Project::TYPE_TWO || $type == Project::TYPE_THREE)){
$onlineInfo = $onlineCheckModel->read(['project_id'=>$project_id]);
if($onlineInfo === false){
if(empty($optimist_mid) || empty($quality_mid)){
$this->fail('请选择优化师及品控');
}
$data = [
'project_id' => $project_id,
'created_manage_id' => $this->manager['id'],
... ... @@ -476,7 +506,17 @@ class ProjectLogic extends BaseLogic
'qa_status'=>1,
'created_at'=>date('Y-m-d H:i:s'),
];
if($onlineInfo === false){
if(empty($optimist_mid) || empty($quality_mid)){
$this->fail('自动提交审核,请选择优化师及品控');
}
$onlineCheckModel->addReturnId($data);
}else{
$onlineCheckModel->edit($data,['project_id'=>$project_id]);
}
$this->param['status'] = Project::STATUS_ONE;
if(empty($this->param['uptime'])){
$this->param['uptime'] = date('Y-m-d H:i:s');
}
}
return true;
... ...
... ... @@ -70,6 +70,11 @@ class ChatLogic extends BaseLogic
}
$data = ['message' => $message];
$stream = $gptService->get_ai_chat($data); // 获取流
// 允许跨域访问
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
... ... @@ -89,7 +94,7 @@ class ChatLogic extends BaseLogic
if (json_last_error() === JSON_ERROR_NONE) {
if (isset($jsonData['text'])) {
$aiResponse .= $jsonData['text'];
echo $gptService->en_sse_data(trim($jsonData['text']));
echo $gptService->en_sse_data($jsonData['text']);
ob_flush();
flush();
}
... ... @@ -116,7 +121,7 @@ class ChatLogic extends BaseLogic
//创建一个会话
$saveData = [
'user_id'=>$this->user['id'],
'input_content'=>$message,
'input_content'=>mb_substr($message, 0, 50, "UTF-8").'...',
];
return $this->model->addReturnId($saveData);
}
... ... @@ -136,6 +141,9 @@ class ChatLogic extends BaseLogic
'chat_id'=>$id,
'content'=>$message,
];
return $this->itemModel->addReturnId($saveData);
//同时更改主任务
$this->itemModel->addReturnId($saveData);
$data = ['last_created_at'=>date('Y-m-d H:i:s'),'last_input_content'=>mb_substr($message, 0, 50, "UTF-8").'...'];
return $this->model->edit($data,['id'=>$id]);
}
}
... ...
... ... @@ -81,13 +81,16 @@ class RankDataLogic extends BaseLogic
}
$g_top_plan['day'] = $g_top_plan['service_day'] - $g_top_plan['is_compliance'];
}
$plan = Project::planMap();
$seo_plan = Project::seoMap();
//项目信息
$data['project'] = [
'company' => $project['company'],
'domain' => $domain_info['domain'] ?? '',
'domain_info' => $domain_info['domain_info'] ?? '',
'cert_info' => $domain_info['cert_info'] ?? '',
'plan' => Project::planMap()[$project['deploy_build']['plan']],
'plan' => $plan[$project['deploy_build']['plan']] ?? 0,
'seo_plan' => $seo_plan[$project['deploy_build']['seo_plan']] ?? 0,
'keyword_num' => $project['deploy_build']['keyword_num'],
'compliance_day' => $project['finish_remain_day'] ?? 0,
'remain_day' => $project['remain_day'],
... ... @@ -490,7 +493,8 @@ class RankDataLogic extends BaseLogic
$without_extension_project_ids = [658]; //是否达标只统计主词的
$extension_project_ids = [354]; //扩展词也到达标的
$compliance_project_ids = [2163,257,823]; //直接达标处理的
$ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066,2974];//暂停项目id
$ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066];//暂停的项目
$uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目
//一个项目多个api_no
$multiple_api_no_project_ids = [
2104 => [
... ... @@ -565,10 +569,13 @@ class RankDataLogic extends BaseLogic
//项目表更新
if (($model->updated_date != date('Y-m-d') || empty($model_is_compliance)) && !$lang) {
$compliance_day = Project::where(['id' => $project_id])->value('finish_remain_day') ?: 0;
if(!in_array($project_id,$ceaseProjectId)){
if(!in_array($project_id,$ceaseProjectId)){//不是暂停的项目
if($compliance_day == 0){//达标天数为0并当天达标 记录当前达标时间
DeployOptimize::where(['project_id'=>$project_id])->update(['first_compliance_time'=>date('Y-m-d')]);
}
if(in_array($project_id,$uptimeProjectId)){//直接按上线时间统计的项目
Project::where('id', $project_id)->update(['is_remain_today' => 1, 'finish_remain_day' => $compliance_day + 1]);
}else{
//多api_no项目 要api_no都分别达标才算
if(in_array($project_id, array_keys($multiple_api_no_project_ids))){
$api_nos = array_keys($multiple_api_no_project_ids[$project_id]);
... ... @@ -582,6 +589,7 @@ class RankDataLogic extends BaseLogic
Project::where('id', $project_id)->update(['is_remain_today' => 1, 'finish_remain_day' => $compliance_day + 1]);
}
Log::channel('rank_data')->info('项目' . $project_id . '达标天数+1:' . ($compliance_day + 1));
}
}else{
Project::where('id', $project_id)->update(['is_remain_today' => 1, 'finish_remain_day' => $compliance_day]);
Log::channel('rank_data')->info('项目' . $project_id . '暂停项目达标天数不加:'. ($compliance_day));
... ...
... ... @@ -261,7 +261,10 @@ class UserLoginLogic
$info['from_order_id'] = $project['from_order_id'] ?? '';
$info['aicc'] = $project['aicc'] ?? '';
$info['hagro'] = $project['hagro'] ?? '';
$info['plan'] = Project::planMap()[$project['deploy_build']['plan']];
$plan = Project::planMap();
$seo_plan = Project::seoMap();
$info['plan'] = $plan[$project['deploy_build']['plan']] ?? 0;
$info['seo_plan'] = $seo_plan[$project['deploy_build']['seo_plan']] ?? 0;
$info['is_domain'] = empty($project['deploy_optimize']['domain']) ? 0 : 1;
$info['test_domain'] = $project['deploy_build']['test_domain'] ?? '';
$info['domain'] = (!empty($project['deploy_optimize']['domain']) ? ((new DomainInfo())->getDomain($project['deploy_optimize']['domain'])) : ($project['deploy_build']['test_domain'] ?? ''));
... ...
... ... @@ -67,4 +67,22 @@ class GoogleKeywordInsightDetail extends Base
];
return $this->addReturnId($saveData);
}
/**
* @remark :查看当前数据是否存在数组中
* @name :getSearchDetail
* @author :lyh
* @method :post
* @time :2025/4/1 9:56
*/
public function getSearchDetail($keyword,$detailList){
if(!empty($detailList)){
foreach ($detailList as $value){
if($keyword == $value['search']){
return $value;
}
}
}
return [];
}
}
... ...
<?php
/**
* @remark :
* @name :GoogleLink.php
* @author :lyh
* @method :post
* @time :2025/4/3 15:52
*/
namespace App\Models\GoogleSearch;
use App\Models\Base;
/**
* @remark :外链数据
* @name :GoogleLink
* @author :lyh
* @method :post
* @time :2025/4/3 15:53
*/
class GoogleLink extends Base
{
protected $table = 'gl_google_link';
}
... ...
... ... @@ -115,7 +115,6 @@ class Project extends Base
12 => '俄语商务版',
14 => '俄语旗舰版',
13 => '体验版',
15 => '白帽SEO方案',
];
}
... ...
<?php
/**
* @remark :
* @name :GoogleLinkService.php
* @author :lyh
* @method :post
* @time :2025/4/3 15:06
*/
namespace App\Services;
use App\Models\GoogleSearch\GoogleLink;
class GoogleLinkService
{
public $url = 'https://www.cmer.site/api/outlinks';
/**
* @remark :只拉取1页数据
* @name :linkPageData
* @author :lyh
* @method :post
* @time :2025/4/3 15:54
*/
public function linkPageData($domain,$project_id)
{
$domain = getDomain($domain);
// 第一次请求,获取总数
$param = [
'domain' => $domain,
'page' => 1,
'pagesize' => 1, // 只拉取一条数据,获取 total
];
$queryString = http_build_query($param);
$url = $this->url . '?' . $queryString;
$response = http_get($url);
if (!empty($response) && !empty($response['data']['total'])) {
// 计算总数并一次性获取所有数据
$param['pagesize'] = $response['data']['total'];
$queryString = http_build_query($param);
$url = $this->url . '?' . $queryString;
$response = http_get($url);
if (!empty($response['data']['data'])) {
return $this->saveLink($response['data']['data'],$project_id,$domain);// 批量插入
}
}
return false;
}
/**
* @remark :拉取所有数据
* @name :linkData
* @author :lyh
* @method :post
* @time :2025/4/3 15:55
*/
public function linkData($domain,$project_id, $page = 1, $pagesize = 200)
{
$domain = getDomain($domain);
$param = [
'domain' => $domain,
'page' => $page,
'pagesize' => $pagesize,
];
do {
$queryString = http_build_query($param);
$url = $this->url . '?' . $queryString;
$response = http_get($url);
if (!empty($response) && !empty($response['data']['data'])) {
if (!empty($response['data']['data'])) {
$this->saveLink($response['data']['data'],$project_id,$domain);// 批量插入
}
$page++;
$param['page'] = $page; // 更新页码
} else {
break; // 遇到错误或空数据时跳出循环
}
} while ($page <= $response['data']['last_page']); // 循环直到拉取完所有页数据
return true;
}
/**
* @remark :保存数据库
* @name :saveLink
* @author :lyh
* @method :post
* @time :2025/4/3 15:26
*/
public function saveLink($data,$project_id,$domain){
$saveData = [];
foreach ($data as $val){
$timestamp = strtotime($val['created_at']);
$date = date('Y-m-d H:i:s', $timestamp ?? time());
$saveData[] = [
'url'=>$val['url'],
'moz_da'=>$val['mozDA'],
'status'=>$val['status'],
'google_search'=>$val['googlesearch'],
'date'=>$date,
'project_id'=>$project_id,
'domain'=>$domain
];
}
$linkModel = new GoogleLink();
$linkModel->insertAll($saveData);
return $saveData;
}
}
... ...
... ... @@ -59,10 +59,6 @@ class GptService
* @time :2025/4/2 16:56
*/
public function en_sse_data($body, string $type='text'){
return 'data:'.json_encode([
'id' => md5(is_array($body) ? json_encode($body) : $body),
'data' => $body,
'type' => $type
],JSON_UNESCAPED_UNICODE)."\n\n";
return 'data:'.json_encode(['id' => md5(is_array($body) ? json_encode($body) : $body), 'data' => $body, 'type' => $type],JSON_UNESCAPED_UNICODE)."\n\n";
}
}
... ...
... ... @@ -304,7 +304,8 @@ Route::middleware(['aloginauth'])->group(function () {
Route::any('/saveMinorLanguages', [Aside\Optimize\OptimizeController::class, 'saveMinorLanguages'])->name('admin.optimize_saveMinorLanguages');//设置小语种监控开关
Route::any('/editTranslateStatus', [Aside\Optimize\OptimizeController::class, 'editTranslateStatus'])->name('admin.optimize_editTranslateStatus');//设置robots开关
Route::any('/getAnchorLink', [Aside\Optimize\OptimizeController::class, 'getAnchorLink'])->name('admin.optimize_getAnchorLink');//设置robots开关
Route::any('/getAfterCount', [Aside\Optimize\OptimizeController::class, 'getAfterCount'])->name('admin.optimize_getAfterCount');//设置robots开关
Route::any('/getAfterCount', [Aside\Optimize\AfterCountController::class, 'getAfterCount'])->name('admin.optimize_getAfterCount');//售后统计数据
Route::any('/getAfterCountInfo', [Aside\Optimize\AfterCountController::class, 'getAfterCountInfo'])->name('admin.optimize_getAfterCountInfo');//售后统计数据详情
});
//生成关键字
Route::prefix('create_keyword')->group(function () {
... ...
... ... @@ -717,8 +717,13 @@ Route::middleware(['bloginauth'])->group(function () {
Route::any('/', [\App\Http\Controllers\Bside\Gpt\ChatController::class, 'list'])->name('gpt_list');
Route::any('/itemList', [\App\Http\Controllers\Bside\Gpt\ChatController::class, 'itemList'])->name('gpt_itemList');
Route::any('/del', [\App\Http\Controllers\Bside\Gpt\ChatController::class, 'del'])->name('gpt_del');
Route::any('/save', [\App\Http\Controllers\Bside\Gpt\ChatController::class, 'saveChat'])->name('gpt_save');
Route::any('/sendMessage', [\App\Http\Controllers\Bside\Gpt\ChatController::class, 'sendMessage'])->name('gpt_sendMessage');
});
Route::prefix('google_link')->group(function () {
Route::any('/', [\App\Http\Controllers\Bside\GoogleKeyword\GoogleLinkController::class,'getLink'])->name('google_link_getLink');
});
});
//无需登录验证的路由组
Route::group([], function () {
... ...