diff --git a/app/model/ExpiosiveReplica.php b/app/model/ExpiosiveReplica.php index 083a61f..edf843f 100644 --- a/app/model/ExpiosiveReplica.php +++ b/app/model/ExpiosiveReplica.php @@ -30,4 +30,8 @@ class ExpiosiveReplica extends BaseModel */ public $timestamps = true; + public function getAiTimeAttr($attr) + { + return $attr == 0 ? '未完成' : date('Y-m-d H:i:s', $attr); + } } \ No newline at end of file diff --git a/app/queue/redis/CreationTask.php b/app/queue/redis/CreationTask.php index a2984df..b38fd8d 100644 --- a/app/queue/redis/CreationTask.php +++ b/app/queue/redis/CreationTask.php @@ -6,7 +6,6 @@ use app\dao\CreationArticleDao; use app\dao\CreationTaskDao; use app\dao\DistillationQuestionsDao; use app\dao\DistillationWordDao; -use app\dao\EnterprisePortraitCategoryDao; use app\dao\EnterprisePortraitLibraryDao; use plugin\piadmin\app\utils\openai\OpenAiClient; use Webman\RedisQueue\Consumer; @@ -156,10 +155,10 @@ class CreationTask implements Consumer private function getPortraitLibrary($task) { echo "开始获取配图\n"; - $categoryDao = app()->make(EnterprisePortraitCategoryDao::class); - $category = $categoryDao->getOne(['id' => $task['portrait_category_id']]); +// $categoryDao = app()->make(EnterprisePortraitCategoryDao::class); +// $category = $categoryDao->getOne(['id' => $task['portrait_category_id']]); $libraryDao = app()->make(EnterprisePortraitLibraryDao::class); - $library = $libraryDao->getColumn(['category_id' => $category['id']], 'url'); + $library = $libraryDao->getColumn(['category_id' => $task['portrait_category_id']], 'url'); if (!$library) { return [ 'images' => [], diff --git a/app/queue/redis/ExpiosiveReplica.php b/app/queue/redis/ExpiosiveReplica.php new file mode 100644 index 0000000..b851bf6 --- /dev/null +++ b/app/queue/redis/ExpiosiveReplica.php @@ -0,0 +1,222 @@ + + + 2025年科技行业发展趋势 + + +

2025年科技行业发展趋势

+

随着科技的飞速发展,2025年科技行业呈现出许多新的趋势。

+

人工智能在医疗、教育和交通等领域的应用越来越广泛。

+

5G技术的普及也推动了物联网的发展。

+

此外,量子计算和区块链技术也在逐步走向商业化应用。

+ + + ``` + 提取结果如下: + ```json + { + "title": "2025年科技行业发展趋势", + "content": "随着科技的飞速发展,2025年科技行业呈现出许多新的趋势。人工智能在医疗、教育和交通等领域的应用越来越广泛。5G技术的普及也推动了物联网的发展。此外,量子计算和区块链技术也在逐步走向商业化应用。" + }'; + + //爆文复刻用提示词 + private $defaultPrompt = '- Role: 爆文复刻专家、内容优化顾问及视觉内容整合师 +- Background: 用户需要对提供的标题和文章进行复刻,以满足特定的要求。用户会提供一些配图,并指定在文章合适的位置插入这些图片。这意味着用户希望在保留原文核心内容和风格的基础上,对文章进行优化和调整,使其更接近“爆文”的标准,同时通过视觉元素增强文章的吸引力和可读性。 +- Profile: 你是一位在爆文创作、内容优化和视觉内容整合领域有着丰富经验的专家,能够精准地把握爆文的特点和用户的需求,对文章进行高质量的复刻。你熟悉各种写作风格和内容结构,能够根据用户的要求,对文章进行有效的调整和优化,同时保留原文的核心价值和风格。 +- Skills: 你具备爆文创作能力、内容优化技巧、语言表达能力、视觉内容整合能力以及对用户需求的敏锐洞察力。能够根据用户提供的标题、文章和配图,结合复刻要求,对文章进行精准的调整和优化,并合理插入配图。 +- Goals: 根据用户提供的标题、文章和配图,按照用户的要求进行复刻,确保复刻后的文章更接近“爆文”的标准,同时保留原文的核心内容和风格,并在合适的位置插入配图,增强文章的视觉效果和可读性。 +- Constrains: 复刻后的文章必须严格遵循用户的要求,包括内容调整、风格优化、语言润色等。确保复刻后的文章在满足要求的同时,保持原有的核心信息和风格特点。配图插入位置应合理,与文章内容紧密相关,增强文章的可读性和视觉效果。 +- OutputFormat: 输出格式为完整的文章正文,包括复刻后的标题和内容。如果用户有特定的格式要求,应严格按照要求输出。配图应插入到文章的合适位置,图片数量符合用户指定的要求。 +- Workflow: + 1. 接收用户提供的标题、文章和配图。 + 2. 仔细分析用户提出的复刻要求,明确复刻的方向和重点。 + 3. 根据复刻要求,对文章的标题和内容进行优化和调整,提升文章的吸引力和可读性。 + 4. 确定配图的插入位置,确保图片与文章内容紧密相关,增强视觉效果。 + 5. 将配图合理插入到文章的合适位置,完成复刻。 + 6. 审核复刻后的文章,确保内容符合用户的要求,语言流畅且逻辑清晰,用户提出的要求仅针对提供的标题和内容,不针对复刻后的标题和内容。 +- Examples: + - 假设用户提供的标题是“如何提高工作效率”,文章内容如下: + ``` + 在当今快节奏的工作环境中,提高工作效率是每个职场人士都关心的问题。以下是一些实用的建议: + - 制定清晰的工作计划。 + - 优先处理重要任务。 + - 避免不必要的干扰。 + - 定期休息,保持精力充沛。 + ``` + 用户提供了两张配图,并要求在合适的位置插入: + ```json + { + "title": "工作效率翻倍的秘密:职场高手的4个绝招", + "content": "在快节奏的职场竞争中,工作效率就是生命线!今天,就来揭秘那些职场高手如何轻松搞定工作,效率翻倍的秘密。![配图1](配图地址1)\n\n首先,高手们都会制定一份超清晰的工作计划,每一步都精准无误。其次,他们总是优先搞定那些最重要的任务,绝不拖泥带水。![配图2](配图地址2)\n\n再来,他们懂得如何屏蔽那些无意义的干扰,专注就是他们的超能力。最后,别小看定期休息,这可是保持精力充沛的不二法门。赶紧试试这些绝招,让你的工作效率瞬间提升!" + }。 + 我提供的JSON数据:配图(images)。创作要求(prompt),仅针对提供的内容(content),不针对创作的文章,尤其是不影响配图的插入。标题(title),内容(contnet)。数据:'; + + // 消费 + public function consume($data) + { + echo "开始消费爆发复刻,数据ID为:" . $data['replica_id'] . "\n"; + //获取复刻任务 + $replicaDao = app()->make(ExpiosiveReplicaDao::class); + //状态改为复刻 + $replicaDao->update($data['replica_id'], ['status' => 2]); + //获取复刻任务明细 + $replicaTask = $replicaDao->get($data['replica_id']); + //解析url获取文章内容 + $html = $this->fetchArticleContent($replicaTask['url']); + $fetch_prompt = $this->fetchWebPrompt . ',需要提取的html为:' . $html; + $result = OpenAiClient::chat($fetch_prompt); + $title = $result['content']['title']; + $content = $result['content']['content']; + //拼接提示词 + $prompts = array_merge($this->getPortraitLibrary($replicaTask),$this->getAiCommand($replicaTask)); + $prompts['title'] = $title; + $prompts['content'] = $content; + $finalPrompt = $this->defaultPrompt . '\n' . json_encode($prompts, JSON_UNESCAPED_UNICODE); +// echo "最终提示词:\n"; +// var_export($finalPrompt); + $airesult = OpenAiClient::chat($finalPrompt); + $updata = [ + 'url_web' => $html, + 'title' => $result['content']['title'], + 'content' => $result['content']['content'], + 'ai_title' => $airesult['content']['title'], + 'ai_content' => $airesult['content']['content'], + 'status' => 3, + 'ai_time' => time() + ]; + var_export($updata); + //更改任务状态为完成 + $replicaDao->update($data['replica_id'], $updata); + var_export('任务完成'); + } + + public function onConsumeFailure(\Throwable $e, $package) + { + echo "执行失败\n"; + echo $e->getMessage() . "\n"; + echo $e->getFile() . "\n"; + echo $e->getLine() . "\n"; + // 无需反序列化 + var_export($package); + //记录失败 + $replicaDao = app()->make(ExpiosiveReplicaDao::class); + $replicaDao->update($package['data']['replica_id'], [ + 'status' => 4, + 'try_count' => $package['attempts'], + 'status_msg' => $package['error'] + ]); + } + + /** + * 获取配图及使用数量 + */ + private function getPortraitLibrary($replicaTask) + { + echo "开始获取配图\n"; + $libraryDao = app()->make(EnterprisePortraitLibraryDao::class); + $library = $libraryDao->getColumn(['category_id' => $replicaTask['portrait_category_id']], 'url'); + echo "获取到配图:" . count($library) . "\n"; + var_export($library); + if (!$library) { + return [ + 'images' => [], + ]; + } + return [ + 'images' => $library, + ]; + } + + /** + * 获取创作指令 + * type = 3 流量复刻 + */ + private function getAiCommand($replicaTask) + { + echo "开始获取指令:" . 3 . "\n"; + $aiCommandDao = app()->make(AiCommandDao::class); + $ai_command_id = $replicaTask['ai_command_id']; + $command = $aiCommandDao->getOne([ + 'type' => 3, + 'id' => $ai_command_id + ]); + echo "获取到指令:" . $command['content'] . "\n"; + if (!$command) { + return [ + 'prompt' => '' + ]; + } + return [ + 'prompt' => $command['content'] + ]; + } + + /** + * 从URL抓取文章内容 + * @param string $url + * @return string + */ + public function fetchArticleContent(string $url): string + { + // 使用 cURL 获取网页内容 + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); + $html = curl_exec($ch); + curl_close($ch); + // 移除script标签及其内容 + $html = preg_replace('/)<[^<]*)*<\/script>/mi', '', $html); + // 移除style标签及其内容 + $html = preg_replace('/)<[^<]*)*<\/style>/mi', '', $html); + // 移除link标签(通常用于引入CSS) + $html = preg_replace('/]*>/mi', '', $html); + // 移除meta标签 + $html = preg_replace('/]*>/mi', '', $html); + // 移除所有标签的style属性(行内样式) + $html = preg_replace('/(<[^>]+) style=".*?"/i', '$1', $html); + // 移除所有标签的class属性 + $html = preg_replace('/(<[^>]+) class=".*?"/i', '$1', $html); + // 移除所有标签的id属性 + $html = preg_replace('/(<[^>]+) id=".*?"/i', '$1', $html); + // 移除多余的空白行 + $html = preg_replace('/^\s*[\r\n]/m', '', $html); + $html = str_replace(' ', '', $html); + return $html; + + } +} \ No newline at end of file diff --git a/app/service/ExpiosiveReplicaService.php b/app/service/ExpiosiveReplicaService.php index adcbe02..ef19c92 100644 --- a/app/service/ExpiosiveReplicaService.php +++ b/app/service/ExpiosiveReplicaService.php @@ -7,6 +7,7 @@ use plugin\piadmin\app\base\BaseService; use plugin\piadmin\app\exception\ApiException; use plugin\piadmin\app\utils\RequestUtils; use support\think\Db; +use Webman\RedisQueue\Redis; class ExpiosiveReplicaService extends BaseService { @@ -31,6 +32,7 @@ class ExpiosiveReplicaService extends BaseService $data = $this->dao->save($params); Db::commit(); // 投递消息 + Redis::send('expiosive_replica', ['replica_id' => $data['id']]); } catch (\Exception $exception) { Db::rollback(); throw new ApiException($exception->getMessage()); @@ -57,7 +59,7 @@ class ExpiosiveReplicaService extends BaseService if (isNotBlank($params['end_time'])) { $query[] = ['create_time', '<=', strtotime($params['end_time'] . ' 23:59:59')]; } - $list = $this->dao->getList($query, '*', $page, $limit, "$sortField $sortRule"); + $list = $this->dao->getList($query, 'id,name,url,title,ai_time', $page, $limit, "$sortField $sortRule"); $count = $this->dao->getCount($query); return compact('list', 'count'); }