GeoWritingsTask.php 5.6 KB
<?php
/**
 * @remark :
 * @name   :GeoWritingsTask.php
 * @author :lyh
 * @method :post
 * @time   :2025/10/27 14:12
 */

namespace App\Console\Commands\Geo;

use App\Helper\Gpt;
use App\Models\Geo\GeoWritings;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;
use App\Models\Geo\GeoWritingsTask as GeoWritingsTaskModel;

class GeoWritingsTask extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'geo_writings_task';

    public $porject_id;//记录当时执行的project_id

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'geoAi生成文章';

    public function handle(){
        while (true){
            $geoWritingsTaskModel = new GeoWritingsTaskModel();
            $task_id = $this->getTaskId();
            if(empty($task_id)){
                sleep(60);
                continue;
            }
            echo date("Y-m-d H:i:s").',执行的任务id'.$task_id.PHP_EOL;
            $info = $geoWritingsTaskModel->read(['id'=>$task_id,'status'=>1]);
            if($info === false){
                echo date("Y-m-d H:i:s").',任务id数据不存在/或已被执行:'.$task_id.PHP_EOL;
                continue;
            }
            //修改状态为生成中
            $geoWritingsModel = new GeoWritings();
            $geoWritingsModel->edit(['status'=>$geoWritingsModel::STATUS_AI_RUNNING],['id'=>$info['writings_id']]);
            //生成引言
            $aiCommand1 = "请根据这个文章标题:{$info['title']},并同时参考公司的介绍’{$info['description']}‘以及公司参与的事件内容’{$info['event_content']}‘,给我写一个英文Press Release前言内容,前言内容请参考并引用{$info['keyword']}行业的一些专业数据报告,只需要1个段落,大约150-200字,请一定要出现这个关键词“{$info['prefix']}{$info['keyword']}{$info['suffix']}”,所有内容一定要用英文, 只需要回复我引言内容,不需要别的内容(比如序号、你的提示、寒暄、解释、注释之类的)";
            $gptHelper = new Gpt();
            $introduction = $gptHelper->openai_chat_qqs($aiCommand1);
            //生成内容
            $aiCommand2 = "请根据这个文章标题:{$info['title']},并同时参考公司的介绍{$info['description']},以及公司参与的事件内容{$info['event_content']},给我写一篇英文Press Release内容正文(已经有前言内容了),内容请参考并引用“{$info['prefix']}{$info['keyword']}{$info['suffix']}”行业的一些专业数据报告,新闻内容需要 5-6 个大纲,每个大纲需要标题和 1-2 段内容,最后1-2个大纲主要介绍企业的核心优势、主营产品应用场景、主要客户案例,并最后附带内容{$info['footer']},最后只需要回复我新闻稿内容,整个新闻稿内容字数1000字左右,不需要别的内容(比如序号、你的提示、寒暄、解释、注释之类的)";
            $main = $gptHelper->openai_chat_qqs($aiCommand2);
            $images = explode(',',$info['img']);
            //组装一条数据
            if(isset($images[0]) && !empty($images[0])){
                $images[0] = '<img src="' . $images[0] . '" alt="">';
            }
            if(isset($images[1]) && !empty($images[1])){
                $images[1] = '<img src="' . $images[1] . '" alt="">';
            }
            try {
                $saveData = [
                    'title'=>$info['title'],
                    'content'=>$introduction.($images[0] ?? '').PHP_EOL.$main.($images[1] ?? ''),
                    'content_length'=>strlen($introduction.PHP_EOL.$main),
                    'status'=>$geoWritingsModel::STATUS_INIT
                ];
                $geoWritingsModel->edit($saveData,['id'=>$info['writings_id']]);
                $data = [
                    'introduction'=>$introduction,
                    'main'=>$main,
                    'status'=>2,
                ];
                $geoWritingsTaskModel->edit($data,['id'=>$task_id]);
            }catch (\Exception $e){
                echo date('Y-m-d H:i:s').'保存失败:'.$task_id.$e->getMessage().PHP_EOL;
                continue;
            }
        }
    }

    /**
     * @remark :获取任务id
     * @name   :getTaskId
     * @author :lyh
     * @method :post
     * @time   :2025/10/27 14:22
     */
    public function getTaskId()
    {
        $task_id = Redis::rpop('geo_writings_task');
        // 如果队列空了,尝试补充
        if (empty($task_id)) {
            $lock_key = 'geo_writings_task_lock';
            $lock_ttl = 10; // 锁过期时间10秒,防止死锁
            $lock = Redis::set($lock_key, 1, 'EX', $lock_ttl, 'NX');
            if ($lock) {
                try {
                    $geoWritingsTaskModel = new GeoWritingsTaskModel();
                    $ids = $geoWritingsTaskModel->formatQuery(['status' => 0])->limit(100)->pluck('id');
                    if (!$ids->isEmpty()) {
                        // 标记这批任务为“生成中”
                        $geoWritingsTaskModel->edit(['status' => 1], ['id' => ['in', $ids]]);
                        foreach ($ids as $id) {
                            Redis::lpush('geo_writings_task', $id);
                        }
                    }
                } finally {
                    // 释放锁
                    Redis::del($lock_key);
                }
                // 再次从队列中取任务
                $task_id = Redis::rpop('geo_writings_task');
            }
        }
        return $task_id;
    }

}