作者 刘锟

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

... ... @@ -114,7 +114,7 @@ class AiBlogAuthorTask extends Command
return true;
}
$aiBlogAuthorModel = new AiBlogAuthor();
$info = $aiBlogAuthorModel->count(['project_id'=>$project_id]);
$info = $aiBlogAuthorModel->counts(['project_id'=>$project_id]);
if($info === false){
foreach ($data as $v){
$param = [
... ...
<?php
namespace App\Console\Commands\Ai;
use App\Http\Logic\Aside\Project\ProjectLogic;
use App\Models\Ai\AiBlog;
use App\Models\Ai\AiBlogOpenLog;
use App\Models\Project\AiBlogTask as AiBlogTaskModel;
use App\Models\Project\Project;
use App\Models\Project\ProjectKeyword;
use App\Models\WebSetting\WebSetting;
use App\Services\AiBlogService;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/**
* 自动发布AI博客任务
* Class AiBlogAutoPublish
* @package App\Console\Commands\Ai
* @author zbj
* @date 2025/3/6
*/
class AiBlogAutoPublish extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'ai_blog_auto_publish {action}';
/**
* The console command description.
*
* @var string
*/
protected $description = '自动发布AI Blog';
/**
* @return bool
* @author zbj
* @date 2025/3/6
*/
public function handle()
{
$action = $this->argument('action');
if($action == 'auto_publish'){
$this->auto_publish();
}
if($action == 'auto_open'){
$this->auto_open();
}
}
public function auto_publish()
{
$this->output('开始自动发布博客文章');
$projects = Project::where('is_ai_blog', 1)->get();
foreach ($projects as $project) {
$this->output("项目{$project->id}开始自动发布");
$next_auto_date = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->whereNotNull('next_auto_date')->orderBy('id', 'desc')->value('next_auto_date');
if($next_auto_date && $next_auto_date > date('Y-m-d')){
$this->output("项目{$project->id}未到执行时间" . $next_auto_date);
continue;
}
//核心关键词+网站关键词
$main_keywords = ProjectKeyword::where('project_id', $project->id)->value('main_keyword');
$main_keywords = explode("\r\n", $main_keywords);
ProjectServer::useProject($project->id);
$site_keywords = WebSetting::where('project_id', $project->id)->value('keyword');
DB::disconnect('custom_mysql');
$site_keywords = explode(",", $site_keywords);
$keywords = array_filter(array_merge($main_keywords, $site_keywords));
$keywords = array_map('trim', $keywords);
if (empty($keywords)) {
$this->output("项目{$project->id}未获取到关键词");
}
$last_task = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->orderBy('id', 'desc')->first();
//如果没有发布过AI blog任务, 第一次提交3个任务
if (!$last_task) {
for ($i = 0; $i < 3; $i++) {
$this->createTask($keywords, $project->id);
}
} else {
$this->createTask($keywords, $project->id);
}
}
}
public function createTask($keywords, $project_id){
$keyword = $keywords[array_rand($keywords)];
$aiBlogService = new AiBlogService($project_id);
$result = $aiBlogService->setRoute($keyword)->createTask($keyword);
if ($result['status'] == 200) {
$aiBlogTaskModel = new AiBlogTaskModel();
$next_auto_date = date('Y-m-d', strtotime('+' . mt_rand(3,6) . 'days')); //每3-6天自动发布
$aiBlogTaskModel->addReturnId(['project_id' => $project_id, 'type' => 2, 'task_id' => $result['data']['task_id'], 'status' => 1, 'next_auto_date' => $next_auto_date]);
ProjectServer::useProject($project_id);
$aiBlogModel = new AiBlog();
$start = strtotime('10:00:00');
$end = strtotime('16:00:00');
$randomTimestamp = mt_rand($start, $end);
$created_at = date("Y-m-d H:i:s", $randomTimestamp);
$aiBlogModel->addReturnId(['keyword' => $keyword, 'status' => 1, 'task_id' => $result['data']['task_id'], 'project_id' => $project_id, 'created_at' => $created_at]);
DB::disconnect('custom_mysql');
$this->output("任务创建成功");
} else {
$this->output('任务创建失败:' . json_encode($result));
}
}
/**
* 上线的推广项目自动开启
* @author zbj
* @date 2025/3/7
*/
public function auto_open()
{
$this->output('上线的推广项目自动开启');
$projects = Project::whereIn('type', [Project::TYPE_TWO, Project::TYPE_FOUR])
->whereNotNull('uptime')->where('is_ai_blog', 0)
->get();
foreach ($projects as $project) {
//未开启过 自动开启
if (!AiBlogOpenLog::isOpened($project->id)) {
//开启
$project->is_ai_blog = 1;
$project->save();
//创建AI博客项目
(new ProjectLogic())->setAiBlog($project->id, $project->main_lang_id, 1, $project->title);
//开启日志
AiBlogOpenLog::addLog($project->id);
$this->output('自动开启项目:' . $project->id);
}
}
}
/**
* 输出message
* @param $message
*/
public function output($message)
{
Log::channel('ai_blog')->info($message);
echo date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;
}
}
... ...
... ... @@ -42,7 +42,7 @@ class AiBlogTask extends Command
public function handle(){
$aiBlogTaskModel = new AiBlogTaskModel();
while (true){
$list = $aiBlogTaskModel->list(['status'=>1,'type'=>2],'id',['*'],'asc',1000);
$list = $aiBlogTaskModel->list(['status'=>1,'type'=>2, 'created_at' => ['<', date('Y-m-d H:i:s')]],'id',['*'],'asc',1000);
if(empty($list)){
sleep(300);
continue;
... ...
... ... @@ -67,7 +67,7 @@ class GeneratePage extends Command
$this->output($c_url . ' | 请求成功');
} else {
$noticeModel->edit(['status'=>2],['id'=>$noticeInfo['id']]);
$this->output($c_url . ' | ' . ($re['message'] ?? '未返回失败原因'));
$this->output($c_url . ' | ' . (json_encode($re,true) ?? '未返回失败原因'));
}
$this->output(' taskID: ' . $noticeInfo['id'] . ' end');
} catch (\Exception $e) {
... ...
... ... @@ -41,6 +41,9 @@ class Kernel extends ConsoleKernel
$schedule->command('sync_inquiry_text')->dailyAt('09:00')->withoutOverlapping(1);
//FB询盘费用同步
$schedule->command('sync_ad_cost')->everyThirtyMinutes()->withoutOverlapping(1);
// $schedule->command('ai_blog_auto_publish auto_open')->everyMinute()->withoutOverlapping(1);
// $schedule->command('ai_blog_auto_publish auto_publish')->dailyAt('07:00')->withoutOverlapping(1);
}
/**
... ...
... ... @@ -300,9 +300,9 @@ class InquiryController extends BaseController
*/
public function tranCountry(InquiryLogic $logic){
$this->request->validate([
'phone_region' => 'required',
'country_code' => 'required',
],[
'phone_region.required' => '国家译文不能为空'
'country_code.required' => '国家译文不能为空'
]);
$data = $logic->tranCountry();
$this->response('success',Code::SUCCESS,$data);
... ...
... ... @@ -76,7 +76,7 @@ class ProductController extends BaseController
}
/**
* @remark :列表
* @remark :下载列表
* @name :index
* @author :lyh
* @method :post
... ... @@ -108,29 +108,6 @@ class ProductController extends BaseController
}
$this->response('success',Code::SUCCESS,$lists);
}
/**
* @remark :获取当前页的所有关键字名称
* @name :keywordNameLists
* @author :lyh
* @method :post
* @time :2024/6/3 14:24
*/
public function keywordNameLists($lists){
$keywordId = [];
foreach ($lists as $v){
$keywordId = array_merge($keywordId,$v['keyword_id']);
}
$keywordId = array_values(array_unique($keywordId));
$keywordModel = new Keyword();
$data = [];
$cateList = $keywordModel->list(['id' => ['in',$keywordId]], ['id', 'title']);
if (!empty($cateList)) {
foreach ($cateList as $value) {
$data[$value['id']] = $value['title'];
}
}
return $data;
}
/**
* @remark :不分页产品列表
... ... @@ -146,424 +123,119 @@ class ProductController extends BaseController
}
/**
* @remark :获取时处理图片和文件
* @name :getHandleFileImage
* @remark :详情
* @name :info
* @author :lyh
* @method :post
* @time :2024/1/23 17:43
* @time :2023/8/21 18:12
*/
public function getHandleFileImage($v){
//ToDo::处理图片及文件
if(!empty($v['thumb']) && !empty($v['thumb']['url'])){
$v['thumb']['url'] = getImageUrl($v['thumb']['url'],$this->user['storage_type'] ?? 0,$this->user['project_location']);
}
if(!empty($v['gallery'])){
foreach ($v['gallery'] as $gallery_k => $gallery_v){
$gallery_v['url'] = getImageUrl($gallery_v['url'],$this->user['storage_type'] ?? 0,$this->user['project_location']);
$v['gallery'][$gallery_k] = $gallery_v;
}
}
if(!empty($v['icon'])){
foreach ($v['icon'] as $icon_k => $icon_v){
$icon_v = getImageUrl($icon_v,$this->user['storage_type'] ?? 0,$this->user['project_location']);
$v['icon'][$icon_k] = $icon_v;
}
}
if(!empty($v['video'])){
$v['video']['url'] = getFileUrl($v['video']['url'],$this->user['storage_type'] ?? 0,$this->user['project_location'],$this->user['file_cdn'] ?? 0);
$v['video']['video_image'] = getImageUrl($v['video']['video_image'] ?? '',$this->user['storage_type'] ?? 0,$this->user['project_location']);
}
if(!empty($v['files']) && !empty($v['files']['url'])){
$v['files']['url'] = getFileUrl($v['files']['url'],$this->user['storage_type'] ?? 0,$this->user['project_location'],$this->user['file_cdn'] ?? 0);
}
return $this->success($v);
public function info(Product $product){
$this->request->validate([
'id'=>'required'
],[
'id.required' => 'ID不能为空'
]);
$info = $product->read(['id'=>$this->param['id']]);
$info = $this->handleParam($info);
return $this->response('success',Code::SUCCESS,$info);
}
/**
* @remark :搜索参数处理
* @name :handleReturnParam
* @remark :保存产品数据
* @name :save
* @author :lyh
* @method :post
* @time :2023/9/14 10:01
* @time :2023/8/17 15:01
*/
public function searchParam(&$query){
$query = $query->where('project_id',$this->user['project_id']);
if (isset($this->map['category_id']) && !empty($this->map['category_id'])) {
$str[] = $this->map['category_id'];
$this->getAllSub($this->map['category_id'],$str);
$categoryRelatedModel = new CategoryRelated();
$product_id_arr = $categoryRelatedModel->whereIn('cate_id',$str)->pluck('product_id')->toArray();
$query = $query->whereIn('id',$product_id_arr);
}
if(isset($this->map['title']) && !empty($this->map['title'])){
$this->map['title'] = str_replace('+',' ',$this->map['title']);
$query = $query->where('title','like','%'.$this->map['title'].'%');
}
if(isset($this->map['keyword_title']) && !empty($this->map['keyword_title'])){
$keywordModel = new Keyword();
$keywordInfo = $keywordModel->read(['title'=>$this->map['keyword_title']],['id']);
if(!empty($keywordInfo)){
$query = $query->where('keyword_id','like','%,'.$keywordInfo['id'].',%');
}
}
if(isset($this->map['status'])){
if($this->map['status'] == 0){
$query = $query->whereIn('status',[0,3]);
}else{
$query = $query->where('status',$this->map['status']);
}
}
if(isset($this->map['created_uid'])){
$query = $query->where('created_uid',$this->map['created_uid']);
}
if(!empty($this->param['start_at']) && !empty($this->param['end_at'])){
if($this->user['project_id'] == 2059){
$query->where('send_time', '>=' ,$this->param['start_at'].' 00:00:00')->where('send_time', '<=' ,$this->param['end_at'].' 59:59:59');
}else{
$query->where('created_at', '>=' ,$this->param['start_at'].' 00:00:00')->where('created_at', '<=' ,$this->param['end_at'].' 59:59:59');
}
}
$this->param['featured_status'] = $this->param['featured_status'] ?? 0;
if($this->param['featured_status'] != Category::STATUS_ACTIVE) {
$cateModel = new Category();
$featured_ids = $cateModel->formatQuery(['title'=>['in',['Featured','featured']]])->pluck('id')->toArray();
if(!empty($featured_ids)){
$status = [];
if(isset($this->map['status'])){
$status = ['status'=>$this->map['status']];
}
$cateList = $cateModel->list($status,'id',['id','pid']);
//获取当前的子集
$featured_arr = [];
foreach ($featured_ids as $id){
$featured_arr = array_merge($featured_arr,array_unique(_get_all_sub($id,$cateList)));
}
if(!empty($featured_arr)){
$cateRelated = new CategoryRelated();
$product_ids = $cateRelated->whereIn('cate_id',$featured_arr)->pluck('product_id')->unique()->toArray();
$query = $query->whereNotIn('id',$product_ids);
}
}
}
return $query;
public function save(ProductRequest $request, ProductLogic $logic)
{
$request->validated();
$data = $logic->productSave();
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :获取当前id下所有子集
* @name :getAllSub
* @remark :直接编辑列表数据
* @name :editList
* @author :lyh
* @method :post
* @time :2023/10/18 15:10
* @time :2023/10/26 9:48
*/
public function getAllSub($id,&$str = []){
$cateModel = new Category();
$list = $cateModel->list(['pid'=>$id,'status'=>1],['id','pid']);
if(!empty($list)){
foreach ($list as $v){
$str[] = $v['id'];
$this->getAllSub($v['id'],$str);
}
}
return $str;
public function editList(ProductLogic $logic){
$logic->editList();
$this->response('success');
}
/**
* @remark :获取所有分类
* @name :getCategoryList
* @remark :删除
* @name :delete
* @author :lyh
* @method :post
* @time :2023/9/14 13:56
* @time :2023/8/22 13:45
*/
public function getCategoryList(){
$data = Common::get_user_cache('product_category',$this->user['project_id']);
if(empty($data)){
$categoryModel = new Category();
$data = [];
$cateList = $categoryModel->list(['project_id'=>$this->user['project_id']],['id','title']);
if(!empty($cateList)){
foreach ($cateList as $value){
$data[$value['id']] = $value['title'];
}
}
Common::set_user_cache($data,'product_category',$this->user['project_id']);
}
return $data;
public function delete(ProductLogic $logic)
{
$this->request->validate([
'ids'=>['required', new Ids()]
],[
'ids.required' => 'ID不能为空'
]);
$logic->productDelete();
$this->response('success');
}
/**
* @remark :获取分类名称
* @name :categoryName
* @remark :根据状态获取数量
* @name :getStatusNumber
* @author :lyh
* @method :post
* @time :2023/9/14 13:58
* @time :2023/8/21 18:33
*/
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].',';
}
}
$category_name = trim($category_name,',');
}
return $category_name;
public function getStatusNumber(ProductLogic $logic){
$this->request->validate([
'featured_status'=>'numeric',
],[
'featured_status.numeric' => 'numeric为数字',
]);
$data = $logic->getStatusNumber();
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :获取关键词名称
* @name :categoryName
* @remark :复制产品
* @name :copyProduct
* @author :lyh
* @method :post
* @time :2023/9/14 13:58
* @time :2023/7/29 14:59
*/
public function keywordName($keyword_id,$data){
$keyword_name = '';
if(!empty($keyword_id) && !empty($data)){
foreach ($keyword_id as $v){
if(isset($data[$v])){
$keyword_name .= $data[$v].',';
}
}
$keyword_name = trim($keyword_name,',');
}
return $keyword_name;
public function copyProduct(ProductLogic $logic){
$this->request->validate([
'id'=>'required',
],[
'id.required' => 'id不能为空',
]);
$data = $logic->setCopyProduct();
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :详情
* @name :info
* @remark :批量设置产品分类
* @name :batchSetCategory
* @author :lyh
* @method :post
* @time :2023/8/21 18:12
* @time :2023/8/15 17:51
*/
public function info(Product $product){
public function batchSetCategory(ProductLogic $logic){
$this->request->validate([
'id'=>'required'
'id'=>'required',
'category_id'=>'required',
],[
'id.required' => 'ID不能为空'
'id.required' => '产品ID不能为空',
'category_id.required' => '分类ID不能为空',
]);
$info = $product->read(['id'=>$this->param['id']]);
$info = $this->handleParam($info);
return $this->response('success',Code::SUCCESS,$info);
}
/**
* @remark :处理列表参数
* @name :handleParam
* @author :lyh
* @method :post
* @time :2023/8/17 9:15
*/
public function handleParam($v){
$v['keyword_id_text'] = '';
if(!empty($v['keyword_id'])){
$keywordModel = new Keyword();
$keyword_data = $keywordModel->list(['id'=>['in',$v['keyword_id']]]);
foreach ($keyword_data as $v1){
$v['keyword_id_text'] .= $v1['title'].',';
}
$v['keyword_id_text'] = trim($v['keyword_id_text'],',');
}
if(!empty($v['status'])){
$v['status_text'] = Product::statusMap()[$v['status']] ?? '';
}else{
$v['status_text'] = '';
}
//ToDo::处理图片及文件
$v = $this->getHandleFileImage($v);
$template_id = $this->getTemplateId(BTemplate::SOURCE_PRODUCT,BTemplate::IS_DETAIL);
$v['is_renovation'] = $this->getIsRenovation(BTemplate::SOURCE_PRODUCT,BTemplate::IS_DETAIL,$template_id,$v['id'] ?? 0);
$v['url'] = $this->user['domain'].($v['route'] ?? '');
//获取当前数据扩展字段及值
$v['extend'] = $this->getExtendInfo($v['id']);
return $v;
}
/**
* @remark :获取扩展字段详情
* @name :getExtendInfo
* @author :lyh
* @method :post
* @time :2023/11/14 9:45
*/
public function getExtendInfo($product_id){
$extendModel = new Extend();
$list = $extendModel->list([],'id',['id','type','key','title']);
if(empty($list)){
return [];
}
$extendInfoModel = new ExtendInfo();
$infoList = $extendInfoModel->list(['product_id'=>$product_id],'created_at');
foreach ($list as $k=>$v){
foreach ($infoList as $values){
if($v['key'] == $values['key']){
$v = $this->setTypValues($v,$values);
break;
}
}
$list[$k] = $v;
}
$list = $this->handleExtentList($list);
return $list;
}
/**
* @remark :处理详情数据(初始化)
* @name :handleList
* @author :lyh
* @method :post
* @time :2024/8/14 18:26
*/
public function handleExtentList($list){
foreach ($list as $k => $v){
if($v['type'] == 3 || $v['type'] == 4){
if(!isset($v['values'])){
$v['values'] = [];
}
}else{
if(!isset($v['values'])){
$v['values'] = '';
}
}
$list[$k] = $v;
}
return $this->success($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'],$this->user['storage_type'],$this->user['project_location']);
$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'],$this->user['storage_type'],$this->user['project_location'],$this->user['file_cdn'] ?? 0);
}else{
$v1 = getFileUrl($v1,$this->user['storage_type'],$this->user['project_location'],$this->user['file_cdn'] ?? 0);
}
$arr1[$k1] = $v1;
}
$v['values'] = $arr1;
}else{
$v['values'] = $info['values'];
}
return $v;
}
/**
* @remark :保存产品数据
* @name :save
* @author :lyh
* @method :post
* @time :2023/8/17 15:01
*/
public function save(ProductRequest $request, ProductLogic $logic)
{
$request->validated();
$data = $logic->productSave();
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :直接编辑列表数据
* @name :editList
* @author :lyh
* @method :post
* @time :2023/10/26 9:48
*/
public function editList(ProductLogic $logic){
$logic->editList();
$this->response('success');
}
/**
* @remark :删除
* @name :delete
* @author :lyh
* @method :post
* @time :2023/8/22 13:45
*/
public function delete(ProductLogic $logic)
{
$this->request->validate([
'ids'=>['required', new Ids()]
],[
'ids.required' => 'ID不能为空'
]);
$logic->productDelete();
$this->response('success');
}
/**
* @remark :根据状态获取数量
* @name :getStatusNumber
* @author :lyh
* @method :post
* @time :2023/8/21 18:33
*/
public function getStatusNumber(ProductLogic $logic){
$this->request->validate([
'featured_status'=>'numeric',
],[
'featured_status.numeric' => 'numeric为数字',
]);
$data = $logic->getStatusNumber();
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :复制产品
* @name :copyProduct
* @author :lyh
* @method :post
* @time :2023/7/29 14:59
*/
public function copyProduct(ProductLogic $logic){
$this->request->validate([
'id'=>'required',
],[
'id.required' => 'id不能为空',
]);
$data = $logic->setCopyProduct();
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :批量设置产品分类
* @name :batchSetCategory
* @author :lyh
* @method :post
* @time :2023/8/15 17:51
*/
public function batchSetCategory(ProductLogic $logic){
$this->request->validate([
'id'=>'required',
'category_id'=>'required',
],[
'id.required' => '产品ID不能为空',
'category_id.required' => '分类ID不能为空',
]);
$logic->batchSetCategory();
$this->response('success');
$logic->batchSetCategory();
$this->response('success');
}
/**
... ... @@ -812,4 +484,335 @@ class ProductController extends BaseController
$logic->batchSetKeyword();
$this->response('success');
}
/**
* @remark :获取所有分类
* @name :getCategoryList
* @author :lyh
* @method :post
* @time :2023/9/14 13:56
*/
public function getCategoryList(){
$data = Common::get_user_cache('product_category',$this->user['project_id']);
if(empty($data)){
$categoryModel = new Category();
$data = [];
$cateList = $categoryModel->list(['project_id'=>$this->user['project_id']],['id','title']);
if(!empty($cateList)){
foreach ($cateList as $value){
$data[$value['id']] = $value['title'];
}
}
Common::set_user_cache($data,'product_category',$this->user['project_id']);
}
return $data;
}
/**
* @remark :获取当前页的所有关键字名称
* @name :keywordNameLists
* @author :lyh
* @method :post
* @time :2024/6/3 14:24
*/
public function keywordNameLists($lists){
$keywordId = [];
foreach ($lists as $v){
$keywordId = array_merge($keywordId,$v['keyword_id']);
}
$keywordId = array_values(array_unique($keywordId));
$keywordModel = new Keyword();
$data = [];
$cateList = $keywordModel->list(['id' => ['in',$keywordId]], ['id', 'title']);
if (!empty($cateList)) {
foreach ($cateList as $value) {
$data[$value['id']] = $value['title'];
}
}
return $data;
}
/**
* @remark :获取时处理图片和文件
* @name :getHandleFileImage
* @author :lyh
* @method :post
* @time :2024/1/23 17:43
*/
public function getHandleFileImage($v){
//ToDo::处理图片及文件
if(!empty($v['thumb']) && !empty($v['thumb']['url'])){
$v['thumb']['url'] = getImageUrl($v['thumb']['url'],$this->user['storage_type'] ?? 0,$this->user['project_location']);
}
if(!empty($v['gallery'])){
foreach ($v['gallery'] as $gallery_k => $gallery_v){
$gallery_v['url'] = getImageUrl($gallery_v['url'],$this->user['storage_type'] ?? 0,$this->user['project_location']);
$v['gallery'][$gallery_k] = $gallery_v;
}
}
if(!empty($v['icon'])){
foreach ($v['icon'] as $icon_k => $icon_v){
$icon_v = getImageUrl($icon_v,$this->user['storage_type'] ?? 0,$this->user['project_location']);
$v['icon'][$icon_k] = $icon_v;
}
}
if(!empty($v['video'])){
$v['video']['url'] = getFileUrl($v['video']['url'],$this->user['storage_type'] ?? 0,$this->user['project_location'],$this->user['file_cdn'] ?? 0);
$v['video']['video_image'] = getImageUrl($v['video']['video_image'] ?? '',$this->user['storage_type'] ?? 0,$this->user['project_location']);
}
if(!empty($v['files']) && !empty($v['files']['url'])){
$v['files']['url'] = getFileUrl($v['files']['url'],$this->user['storage_type'] ?? 0,$this->user['project_location'],$this->user['file_cdn'] ?? 0);
}
return $this->success($v);
}
/**
* @remark :处理详情数据(初始化)
* @name :handleList
* @author :lyh
* @method :post
* @time :2024/8/14 18:26
*/
public function handleExtentList($list){
foreach ($list as $k => $v){
if($v['type'] == 3 || $v['type'] == 4){
if(!isset($v['values'])){
$v['values'] = [];
}
}else{
if(!isset($v['values'])){
$v['values'] = '';
}
}
$list[$k] = $v;
}
return $this->success($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'],$this->user['storage_type'],$this->user['project_location']);
$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'],$this->user['storage_type'],$this->user['project_location'],$this->user['file_cdn'] ?? 0);
}else{
$v1 = getFileUrl($v1,$this->user['storage_type'],$this->user['project_location'],$this->user['file_cdn'] ?? 0);
}
$arr1[$k1] = $v1;
}
$v['values'] = $arr1;
}else{
$v['values'] = $info['values'];
}
return $this->success($v);
}
/**
* @remark :搜索参数处理
* @name :handleReturnParam
* @author :lyh
* @method :post
* @time :2023/9/14 10:01
*/
public function searchParam(&$query){
$query = $query->where('project_id',$this->user['project_id']);
if (isset($this->map['category_id']) && !empty($this->map['category_id'])) {
$str[] = $this->map['category_id'];
$this->getAllSub($this->map['category_id'],$str);
$categoryRelatedModel = new CategoryRelated();
$product_id_arr = $categoryRelatedModel->whereIn('cate_id',$str)->pluck('product_id')->toArray();
$query = $query->whereIn('id',$product_id_arr);
}
if(isset($this->map['title']) && !empty($this->map['title'])){
$this->map['title'] = str_replace('+',' ',$this->map['title']);
$query = $query->where('title','like','%'.$this->map['title'].'%');
}
if(isset($this->map['keyword_title']) && !empty($this->map['keyword_title'])){
$keywordModel = new Keyword();
$keywordInfo = $keywordModel->read(['title'=>$this->map['keyword_title']],['id']);
if(!empty($keywordInfo)){
$query = $query->where('keyword_id','like','%,'.$keywordInfo['id'].',%');
}
}
if(isset($this->map['status'])){
if($this->map['status'] == 0){
$query = $query->whereIn('status',[0,3]);
}else{
$query = $query->where('status',$this->map['status']);
}
}
if(isset($this->map['created_uid'])){
$query = $query->where('created_uid',$this->map['created_uid']);
}
if(!empty($this->param['start_at']) && !empty($this->param['end_at'])){
if($this->user['project_id'] == 2059){
$query->where('send_time', '>=' ,$this->param['start_at'].' 00:00:00')->where('send_time', '<=' ,$this->param['end_at'].' 59:59:59');
}else{
$query->where('created_at', '>=' ,$this->param['start_at'].' 00:00:00')->where('created_at', '<=' ,$this->param['end_at'].' 59:59:59');
}
}
$this->param['featured_status'] = $this->param['featured_status'] ?? 0;
if($this->param['featured_status'] != Category::STATUS_ACTIVE) {
$cateModel = new Category();
$featured_ids = $cateModel->formatQuery(['title'=>['in',['Featured','featured']]])->pluck('id')->toArray();
if(!empty($featured_ids)){
$status = [];
if(isset($this->map['status'])){
$status = ['status'=>$this->map['status']];
}
$cateList = $cateModel->list($status,'id',['id','pid']);
//获取当前的子集
$featured_arr = [];
foreach ($featured_ids as $id){
$featured_arr = array_merge($featured_arr,array_unique(_get_all_sub($id,$cateList)));
}
if(!empty($featured_arr)){
$cateRelated = new CategoryRelated();
$product_ids = $cateRelated->whereIn('cate_id',$featured_arr)->pluck('product_id')->unique()->toArray();
$query = $query->whereNotIn('id',$product_ids);
}
}
}
return $query;
}
/**
* @remark :处理列表参数
* @name :handleParam
* @author :lyh
* @method :post
* @time :2023/8/17 9:15
*/
public function handleParam($v){
$v['keyword_id_text'] = '';
if(!empty($v['keyword_id'])){
$keywordModel = new Keyword();
$keyword_data = $keywordModel->list(['id'=>['in',$v['keyword_id']]]);
foreach ($keyword_data as $v1){
$v['keyword_id_text'] .= $v1['title'].',';
}
$v['keyword_id_text'] = trim($v['keyword_id_text'],',');
}
if(!empty($v['status'])){
$v['status_text'] = Product::statusMap()[$v['status']] ?? '';
}else{
$v['status_text'] = '';
}
//ToDo::处理图片及文件
$v = $this->getHandleFileImage($v);
$template_id = $this->getTemplateId(BTemplate::SOURCE_PRODUCT,BTemplate::IS_DETAIL);
$v['is_renovation'] = $this->getIsRenovation(BTemplate::SOURCE_PRODUCT,BTemplate::IS_DETAIL,$template_id,$v['id'] ?? 0);
$v['url'] = $this->user['domain'].($v['route'] ?? '');
//获取当前数据扩展字段及值
$v['extend'] = $this->getExtendInfo($v['id']);
return $v;
}
/**
* @remark :获取扩展字段详情
* @name :getExtendInfo
* @author :lyh
* @method :post
* @time :2023/11/14 9:45
*/
public function getExtendInfo($product_id){
$extendModel = new Extend();
$list = $extendModel->list([],'id',['id','type','key','title']);
if(empty($list)){
return [];
}
$extendInfoModel = new ExtendInfo();
$infoList = $extendInfoModel->list(['product_id'=>$product_id],'created_at');
foreach ($list as $k=>$v){
foreach ($infoList as $values){
if($v['key'] == $values['key']){
$v = $this->setTypValues($v,$values);
break;
}
}
$list[$k] = $v;
}
$list = $this->handleExtentList($list);
return $list;
}
/**
* @remark :获取当前id下所有子集
* @name :getAllSub
* @author :lyh
* @method :post
* @time :2023/10/18 15:10
*/
public function getAllSub($id,&$str = []){
$cateModel = new Category();
$list = $cateModel->list(['pid'=>$id,'status'=>1],['id','pid']);
if(!empty($list)){
foreach ($list as $v){
$str[] = $v['id'];
$this->getAllSub($v['id'],$str);
}
}
return $str;
}
/**
* @remark :获取分类名称
* @name :categoryName
* @author :lyh
* @method :post
* @time :2023/9/14 13:58
*/
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].',';
}
}
$category_name = trim($category_name,',');
}
return $category_name;
}
/**
* @remark :获取关键词名称
* @name :categoryName
* @author :lyh
* @method :post
* @time :2023/9/14 13:58
*/
public function keywordName($keyword_id,$data){
$keyword_name = '';
if(!empty($keyword_id) && !empty($data)){
foreach ($keyword_id as $v){
if(isset($data[$v])){
$keyword_name .= $data[$v].',';
}
}
$keyword_name = trim($keyword_name,',');
}
return $keyword_name;
}
}
... ...
... ... @@ -23,8 +23,8 @@ class WebSettingSeoController extends BaseController
* @time :2023/9/11 16:31
*/
public function info(WebSettingSeoLogic $logic){
$info = $logic->seoInfo();
$this->response('success',Code::SUCCESS,$info);
$result = $logic->seoInfo();
$this->response('success',Code::SUCCESS,$result);
}
/**
... ... @@ -35,7 +35,7 @@ class WebSettingSeoController extends BaseController
* @time :2023/9/11 16:32
*/
public function save(WebSettingSeoLogic $logic){
$logic->seoSave();
$this->response('success');
$result = $logic->seoSave();
$this->response('success',Code::SUCCESS,$result);
}
}
... ...
... ... @@ -7,6 +7,7 @@ use App\Helper\FormGlobalsoApi;
use App\Helper\Translate;
use App\Http\Logic\Aside\Project\ProjectLogic;
use App\Http\Logic\Bside\BaseLogic;
use App\Models\Com\WordCountry;
use App\Models\Domain\DomainInfo;
use App\Models\Inquiry\InquiryForm;
use App\Models\Inquiry\InquiryFormData;
... ... @@ -195,7 +196,7 @@ class InquiryLogic extends BaseLogic
public function sendMobileVerifyData($phone){
$phoneDataModel = new PhoneData();
$num_phone = preg_replace('/\D/', '',$phone) ?? ''; // \D 匹配所有非数字字符
$data = $phoneDataModel->read(['num_phone'=>$num_phone]);
$data = $phoneDataModel->read(['phone'=>$phone]);
if($data === false){
$url = 'https://fob.ai.cc/api/mobile_verify_data/'.$num_phone;
$data = http_get($url);
... ... @@ -212,8 +213,12 @@ class InquiryLogic extends BaseLogic
'country_code'=>$data['country_code'] ?? '',
'phone_region'=>$data['phone_region'] ?? '',
];
if(!empty($param['phone_region'])){
$param['country'] = Translate::tran($param['phone_region'], 'zh') ?? '';
if(!empty($param['country_code'])){
$wordCountryModel = new WordCountry();
$info = $wordCountryModel->read(['pid'=>0,'iso2'=>$this->param['country_code']],['chinese_name']);
if($info !== false){
$param['country'] = $info['chinese_name'];
}
}
(new PhoneData())->addReturnId($param);
return $this->success($param);
... ... @@ -228,13 +233,18 @@ class InquiryLogic extends BaseLogic
* @author :lyh
* @method :post
* @time :2025/3/11 14:11
* @param :pid:0->国家
*/
public function tranCountry(){
$country = Translate::tran($this->param['phone_region'], 'zh') ?? '';
if(!empty($country)){
$phoneDataModel = new PhoneData();
$phoneDataModel->edit(['country'=>$country],['phone_region'=>$this->param['phone_region']]);
$wordCountryModel = new WordCountry();
$info = $wordCountryModel->read(['pid'=>0,'iso2'=>$this->param['country_code']],['chinese_name']);
if($info !== false){
$chinese_name = $info['chinese_name'];
}else{
$chinese_name = $this->param['country_code'];
}
return $this->success(['country'=>$country]);
$phoneDataModel = new PhoneData();
$phoneDataModel->edit(['country'=>$info['chinese_name']],['country_code'=>$this->param['country_code']]);
return $this->success(['country'=>$chinese_name]);
}
}
... ...
... ... @@ -1154,4 +1154,5 @@ class ProductLogic extends BaseLogic
}
return $this->success();
}
}
... ...
... ... @@ -9,6 +9,7 @@
namespace App\Http\Logic\Bside\Setting;
use App\Helper\Arr;
use App\Http\Logic\Bside\BaseLogic;
use App\Models\WebSetting\WebSettingSeo;
... ... @@ -42,8 +43,11 @@ class WebSettingSeoLogic extends BaseLogic
* @author :lyh
* @method :post
* @time :2023/9/11 16:34
* @param :product_category_prefix->分类页前缀;product_category_suffix->分类页后缀
*/
public function seoSave(){
$this->param['product_category_prefix'] = Arr::a2s($this->param['product_category_prefix'] ?? []);
$this->param['product_category_suffix'] = Arr::a2s($this->param['product_category_suffix'] ?? []);
try {
$info = $this->model->read(['project_id'=>$this->user['project_id']]);
if($info === false){
... ...
<?php
namespace App\Models\Ai;
use App\Models\Base;
/**
* AI Blog开启日志
* Class AiBlogOpenLog
* @package App\Models\Ai
* @author zbj
* @date 2025/3/7
*/
class AiBlogOpenLog extends Base
{
protected $table = 'gl_ai_blog_open_log';
public static function addLog($project_id, $manage_id = 0, $status = 1){
$log = new self();
$log->project_id = $project_id;
$log->manage_id = $manage_id;
$log->status = $status;
$log->save();
}
/**
* 是否有开启记录
* @author zbj
* @date 2025/3/7
*/
public static function isOpened($project_id){
$model = self::where('project_id', $project_id)->where('status', 1)->first();
return (bool)$model;
}
}
... ...
... ... @@ -110,7 +110,7 @@ class Base extends Model
*/
public function addReturnId($data){
$data = $this->filterRequestData($data);
$data['created_at'] = date('Y-m-d H:i:s');
$data['created_at'] = $data['created_at'] ?? date('Y-m-d H:i:s');
$data['updated_at'] = $data['created_at'];
return $this->insertGetId($data);
}
... ...
<?php
/**
* @remark :
* @name :WordCountry.php
* @author :lyh
* @method :post
* @time :2025/3/11 17:24
*/
namespace App\Models\Com;
use App\Models\Base;
/**
* @remark :国家信息
* @name :WordCountry
* @author :lyh
* @method :post
* @time :2025/3/11 17:24
*/
class WordCountry extends Base
{
protected $table = 'gl_world_country_city';
}
... ...
... ... @@ -7,72 +7,6 @@ use App\Models\Base;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* App\Models\Product\Product
*
* @method static get()
* @property int $id
* @property int $project_id
* @property string $title
* @property string $thumb 封面
* @property mixed|null $gallery 图集
* @property mixed|null $attrs 属性参数
* @property string|null $attr_id 通用参数
* @property string|null $category_id 分类 多个,号隔开
* @property string|null $keyword_id 关键词标签 多个,号隔开
* @property string|null $intro 简介
* @property string|null $content 详情
* @property mixed|null $describe 描述
* @property string $describe_id 通用描述
* @property mixed|null $seo_mate seo tdk
* @property string $related_product_id 相关产品 多个,号隔开
* @property int $sort 排序
* @property int $status 状态 0草稿 1已上架 2已下架
* @property int $created_uid 创建者
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property string|null $route 路由
* @property mixed|null $icon 图标
* @property string|null $product_type 产品类型:1,一般产品;2:推荐产品(recommend);3:热销产品(hot)
* @property int $is_upgrade 0:6.0 1:4.0,5.0升级
* @property string|null $send_time 发布时间
* @property int|null $six_read 1:导入数据可按6.0显示
* @method \Illuminate\Database\Eloquent\Builder|Product newModelQuery()
* @method \Illuminate\Database\Eloquent\Builder|Product newQuery()
* @method \Illuminate\Database\Eloquent\Builder|Product onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|Product query()
* @method \Illuminate\Database\Eloquent\Builder|Product whereAttrId($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereAttrs($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereCategoryId($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereContent($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereCreatedAt($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereCreatedUid($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereDeletedAt($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereDescribe($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereDescribeId($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereGallery($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereIcon($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereId($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereIntro($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereIsUpgrade($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereKeywordId($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereProductType($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereProjectId($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereRelatedProductId($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereRoute($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereSendTime($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereSeoMate($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereSixRead($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereSort($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereStatus($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereThumb($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereTitle($value)
* @method \Illuminate\Database\Eloquent\Builder|Product whereUpdatedAt($value)
* @method \Illuminate\Database\Eloquent\Builder|Product withTrashed()
* @method \Illuminate\Database\Eloquent\Builder|Product withoutTrashed()
* @mixin \Eloquent
*/
class Product extends Base
{
use SoftDeletes;
... ...
... ... @@ -9,6 +9,7 @@
namespace App\Models\WebSetting;
use App\Helper\Arr;
use App\Models\Base;
class WebSettingSeo extends Base
... ... @@ -18,4 +19,32 @@ class WebSettingSeo extends Base
//连接数据库
protected $connection = 'custom_mysql';
/**
* @remark :(获取器)分类页前缀
* @name :getProductCategoryPrefixAttribute
* @author :lyh
* @method :post
* @time :2025/3/12 10:37
*/
public function getProductCategoryPrefixAttribute($value){
if(!empty($value)){
$value = Arr::s2a($value);
}
return $value;
}
/**
* @remark :(获取器)分类页后缀
* @name :getProductCategorySuffixAttribute
* @author :lyh
* @method :post
* @time :2025/3/12 10:38
*/
public function getProductCategorySuffixAttribute($value){
if(!empty($value)){
$value = Arr::s2a($value);
}
return $value;
}
}
... ...
... ... @@ -9,6 +9,10 @@
namespace App\Services;
use App\Helper\Translate;
use App\Models\Project\ProjectAiSetting;
use Illuminate\Database\Eloquent\Model;
class AiBlogService
{
public $url = 'https://ai-extend.ai.cc/';
... ... @@ -21,6 +25,23 @@ class AiBlogService
public $task_id = '';//任务id
public $author_id = '';//作者id
public function __construct($project_id = 0)
{
if($project_id){
$projectAiSettingModel = new ProjectAiSetting();
$aiSettingInfo = $projectAiSettingModel->read(['project_id'=>$project_id]);
$this->mch_id = $aiSettingInfo['mch_id'];
$this->key = $aiSettingInfo['key'];
}
}
public function setRoute($keyword)
{
$this->route = generateRoute(Translate::tran($keyword, 'en'));
return $this;
}
/**
* @remark :创建项目
* @name :createProject
... ...
... ... @@ -191,6 +191,12 @@ return [
'level' => 'debug',
'days' => 14,
],
'ai_blog' => [
'driver' => 'daily',
'path' => storage_path('logs/ai_blog/laravel.log'),
'level' => 'debug',
'days' => 30,
],
],
//操作日志
'operator_log' =>[
... ...