Files
tougao/application/common/Aiarticle.php
2025-05-17 18:13:07 +08:00

2272 lines
96 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\api\controller;
use app\api\controller\Base;
use think\Controller;
use think\Db;
use app\common\QrCodeImage;
use think\Cache;
/**
* @title 数据库接口
* @description 数据库接口
* @group 数据库接口
*/
class Aiarticle extends Base
{
protected $aImage = [
'640.png' => ['media_id' => 'Cn8zlXvVB5DwjcA9h40z9eW0lwKRJjo_skJ0AmRAwthNP62sxfHGXoC1uIBqzhtc','url' => 'http://mmbiz.qpic.cn/mmbiz_png/QHFVW13lONaQJxK9QbHU9CtrvTS2ModZC7TJuqGRGX6dBIzou8E4d2vfgib3hiaJC5Vv8cI5BTN78FAMqXXL6PmQ/0?wx_fmt=png'],
'blackground.png' => ['media_id' => 'Cn8zlXvVB5DwjcA9h40z9ZL-R__Pwz7qdbJfxSHmuBjNbphyBFlanm-sBQ_nWUYC','url' => 'http://mmbiz.qpic.cn/mmbiz_png/QHFVW13lONaQJxK9QbHU9CtrvTS2ModZfssPs0wTQYhX6ctSiaY1Uck0WTJ1xXZsZlhU05sOjUqFRmLWamH3XKQ/0?wx_fmt=png'],
'dongtu.gif' => ['media_id' => 'Cn8zlXvVB5DwjcA9h40z9b7p9bSZhAeYdRRstPiBXjqSRboKJcxeHKz6VsG5H8ZG','url' => 'http://mmbiz.qpic.cn/mmbiz_gif/QHFVW13lONaQJxK9QbHU9CtrvTS2ModZK6wx6OQLlIiaDRcp0sgxXkZQgwWfDcoM7KzErBE6Nvq4IVf4iaX2icrUQ/0?wx_fmt=gif'],
'weixin.jpeg' => ['media_id' => 'Cn8zlXvVB5DwjcA9h40z9VDBX-gpcy4OA13l_atzNZ8NLWvSV7YA82IlpP6Q1672','url' => 'http://mmbiz.qpic.cn/mmbiz_jpg/QHFVW13lONaQJxK9QbHU9CtrvTS2ModZknGn1cCteibInoxTDzD0EGt5mL7S170R99QGv7ibwWnQFJRZFLN7iaD5g/0?wx_fmt=jpeg'],
];
protected $aLogo = ['media_id' => 'Cn8zlXvVB5DwjcA9h40z9fprHDoc3Jqv97SwrInpmyYiilkeRdKvpD63cWqTYHfz','url' => 'http://mmbiz.qpic.cn/mmbiz_jpg/QHFVW13lONaQJxK9QbHU9CtrvTS2ModZnUyeAvuVN67t8XP85DxVJwDJf2YxCTalrsr17jS080xM6xQv5yGiaEQ/0?wx_fmt=jpeg'];//默认头像
protected $sAppID = 'wx03cb871b66e34e10';
protected $sAppSecret = 'f59ccaf00383dcfab489292c4697620a';
protected $sWechatAccessToken = 'wechat_access_token';
protected $proxy;
protected $sUrl;
protected $curl;
protected $sResponesData;
protected $sError;
protected $timeout = 60;
protected $aAiFileds = ['article_id','title_english','title_chinese','journal_id','covered','digest','research_result','content','highlights','discussion','prospect','research_background',];
protected $sJournalUrl = 'http://journalapi.tmrjournals.com/public/index.php';//'http://zmzm.journal.dev.com'; //
protected $sJournalUsx = 'https://www.tmrjournals.com';
protected $sSubmissionUrl = 'https://submission.tmrjournals.com/';
protected $aOpenAiAsk = [
1 => '
**核心要求**
"将以下内容翻译为中文,仅返回翻译结果,不要解释:\n {#content#}"
',
2 => '
**核心要求**
1 ​内容涵盖哪些学科及方法请罗列
2 结构化摘要生成【四要素模版】
3 研究背景提炼【三段式结构】
发病率+当前治疗缺口如5年OS<20%
引用2-3篇高被引论文的矛盾结论如Nature vs Cell观点分歧
基于团队前期工作如预实验发现X调控Y
4 针对稿件内容进行结论撰写
与TOP3高被引文献的对比用"与A研究的X结论不同..."句式) 机制解释的3级证据链基因敲除→通路抑制→表型逆转 临床转化的可行性路径基于RECIST标准的ORR提升研究局限性分方法学/样本量/随访维度)
5 针对稿件内容进行展望撰写
现有方法的可扩展性(如空间组学升级计划)
6 按点总结归纳研究结果并做简要阐述【3点以上】
7 总结归纳亮点【3点以上】
8 禁用清单
直接复制讨论部分的原文
未达到统计学显著性的趋势描述
稿件内未提及的内容一定不要总结归纳出来
"可能""或许"等不确定性词汇
单纯古籍原文翻译(需结合现代数据解读)
未经验证的因果断言(如"证明XX药治愈癌症"
9 请将标题翻译成中文
{#title_chinese#}
10 请将稿件内容翻译成中文
{#content#}
**稿件关键信息**
- 稿件简介:{#abstract#}
- 稿件内容:{#content#}
**输出格式**
中文格式[英文简写忽略首字母大写]
格式内容
```json
{
"title_chinese": "",
"content": "",
"covered": "【总字数<=100】",
"digest": "【总字数<=500】",
"research_background": "",
"research_result": "",
"highlights": "",
"prospect": "",
"discussion": ""
}'
];
//文章图片icon地址
protected $sArticleIcon = '/public/articleicon/';
//期刊图片icon地址
protected $sJournalIcon = '/public/journalicon/';
//期刊编辑二维码地址
protected $sJournalEditorQrcode = '/public/journaleditorqrcode/';
//"highlights": {
// "theory_innovation": "【中西医理论结合点】",
// "methodology": "【关键技术+量化指标】",
// "data_strength": "【数据规模/古籍分析深度】"
// }
public function __construct(\think\Request $request = null) {
// 从配置读取敏感信息(非硬编码)
$this->sApiKey = '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';
$this->proxy = '';
$this->sUrl = 'https://api.openai.com/v1/chat/completions';
parent::__construct($request);
}
/**
* CURL 发送请求到 OpenAI
* @param $messages 内容
* @param $model 模型类型
*/
protected function curlOpenAI($messages, $model = 'gpt-4o'){
$sUrl = $this->sUrl;
$data = [
'model' => $model,
'messages' => $messages,
'temperature' => 0.7
];
$this->curl = curl_init();
// 通用配置
curl_setopt($this->curl, CURLOPT_URL, $sUrl);
// 设置头信息
curl_setopt($this->curl, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $this->sApiKey
]);
curl_setopt($this->curl, CURLOPT_PROXY,$this->proxy);
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER,true);
curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST,2);
curl_setopt($this->curl, CURLOPT_POST, true); //设置为POST方式
curl_setopt($this->curl, CURLOPT_POSTFIELDS,json_encode($data));
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, TRUE) ; // 获取数据返回
// curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);
$result = curl_exec($this->curl);
//请求失败
if (curl_errno($this->curl)){
$this->sError = curl_errno($this->curl);
curl_close($this->curl);
return FALSE;
}
$this->sResponesData = json_decode($result);
curl_close($this->curl);
return TRUE;
}
/**
* @title 请求OPENAI
* @param aSearch array 模版内容
* @param iTemplateId 模版ID
*/
private function _createContentForOpenAI($aSearch = [],$iTemplateId = 0){
if(empty($aSearch) || empty($iTemplateId)){
return json_encode(array('status' => 2,'msg' => 'Please select a template or enter the content you want to consult'.$this->sError));
}
//组织参数
$sTemplate = $this->aOpenAiAsk[$iTemplateId];
$sTemplate = str_replace(array_keys($aSearch), array_values($aSearch), $sTemplate);
$messages = [
[
'role' => 'user', //角色platform平台;developer:开发者user:用户;guideline:模型规范“指南”部分:连接https://model-spec.openai.com/2025-02-12.html#chain_of_command
'content' => $sTemplate
]
];
//请求接口
$sModel = $aParam['api_model'] ?? 'gpt-4o';
$result = $this->curlOpenAI($messages,$sModel);
if($result == FALSE){
return json_encode(array('status' => 2,'msg' => 'Interface request failed'.$this->sError));
}
//处理返回信息
$data = $this->sResponesData;
if(!is_object($data)){
return json_encode(array('status' => 3,'msg' => 'There is a misunderstanding in the data returned by the interface'));
}
$data = object_to_array($data);
$aChoices = $data['choices'] ?? [];
if(empty($aChoices)){
return json_encode(array('status' => 4,'msg' => 'OPENAI did not return data'));
}
$aChoicesInfo = $aChoices[0] ?? [];
$aMessage = $aChoicesInfo['message'] ?? [];
if(empty($aMessage['content'])){
return json_encode(array('status' => 5,'msg' => 'OPENAI returns empty data'));
}
$sContent = trim(trim($aMessage['content'],'```json'),'```');
$aContent = json_decode($sContent,true);
return json_encode(array('status' => 1,'msg' => 'OPENAI successfully generated content','data' => $aContent));
}
/**
* @title AI生成稿件文章
* @param article_id 文章ID
* @param model 接口模型
* @param stream 是否流式输出 true是false否
*/
public function create(){
//获取参数
$aParam = $this->request->post();
$iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id'];
if(empty($iArticleId)){
return json_encode(array('status' => 2,'msg' => 'Please select an article' ));
}
//获取文章是否生成AI内容
$aResult = json_decode($this->getArticle($iArticleId),true);
$iStatus = empty($aResult['status']) ? 0 : $aResult['status'];
if($iStatus != 1){
return json_encode($aResult);
}
//获取数据
$aArticleContent = empty($aResult['data']) ? [] : $aResult['data'];
//文章数据
$aArticle = empty($aArticleContent['article']) ? [] : $aArticleContent['article'];
if(empty($aArticle)){
return json_encode(['status' => 3,'msg' => 'The content of the article is empty']);
}
//查询AI内容是否生成
$aAiArticle = json_decode($this->getAiArticle($iArticleId),true);
$aAiArticleContent = empty($aAiArticle['data']) ? [] : $aAiArticle['data'];
$aAiArticle = empty($aAiArticleContent['ai_article']) ? [] : $aAiArticleContent['ai_article'];
$iId = empty($aAiArticle['ai_article_id']) ? 0 : $aAiArticle['ai_article_id'];
if(empty($aAiArticle)){
//插入t_ai_article数据
$aInsert = ['title_english' => $aArticle['title'],'article_id' => $iArticleId,'create_time' => time()];
$iId = Db::name('ai_article')->insertGetId($aInsert);
if($iId === false){
return json_encode(['status' => 4,'msg' => 'Data insertion failed']);
}
$aAiArticle = array_merge(['ai_article_id' => $iId,'article_id' => $iArticleId,'is_generate' => 2],$aInsert);
}
//判断是否生成
if(!empty($aAiArticle['is_generate']) && $aAiArticle['is_generate'] == 1){
return json_encode(['status' => 5,'msg' => 'The data has been generated, please proceed with the next steps']);
}
//请求OPENAI
return $this->createForOpenAi($aArticleContent,$aAiArticle);
}
public function createForOpenAi($aArticleContent = [],$aAiArticle = []){
if(empty($aArticleContent)){
$aParam = $this->request->post();
$iId = empty($aParam['ai_article_id']) ? 0 : $aParam['ai_article_id'];
//查询AI内容是否生成
$aAiArticle = json_decode($this->getAiArticle(0,1,$iId),true);
$aAiArticleContent = empty($aAiArticle['data']) ? [] : $aAiArticle['data'];
$aAiArticle = empty($aAiArticleContent['ai_article']) ? [] : $aAiArticleContent['ai_article'];
if(empty($aAiArticle)){
return json_encode(['status' => 4,'msg' => 'The article has not been generated, please confirm']);
}
//判断是否生成
if($aAiArticle['is_generate'] == 1){
return json_encode(['status' => 5,'msg' => 'The data has been generated, please proceed with the next steps']);
}
$iArticleId = empty($aAiArticle['article_id']) ? '' : $aAiArticle['article_id'];
//获取文章是否生成AI内容
$aResult = json_decode($this->getArticle($iArticleId),true);
$iStatus = empty($aResult['status']) ? 0 : $aResult['status'];
if($iStatus != 1){
return json_encode($aResult);
}
//获取数据
$aArticleContent = empty($aResult['data']) ? [] : $aResult['data'];
}
$iId = empty($aAiArticle['ai_article_id']) ? 0 : $aAiArticle['ai_article_id'];
$iArticleId = empty($aAiArticle['article_id']) ? 0 : $aAiArticle['article_id'];
//文章数据
$aArticle = empty($aArticleContent['article']) ? [] : $aArticleContent['article'];
//期刊数据
$aJournal = empty($aArticleContent['journal']) ? [] : $aArticleContent['journal'];
//子期刊数据
$aJournalStage = empty($aArticleContent['journal_stage']) ? [] : $aArticleContent['journal_stage'];
//通讯作者
$aAuthor = empty($aArticleContent['author']) ? [] : $aArticleContent['author'];
//生成期刊图片二维码
$aJournalQrCode = $this->createJournalQrCode($aJournal);
if(empty($aJournalQrCode['qrcode_url'])){
return json_encode(['status' => 3,'msg' => 'Journal QR code not generated']);
}
//生成文章图片二维码
$aArticleQrCode = $this->createArticleQrCode($aArticle);
if(empty($aArticleQrCode['qrcode_url'])){
return json_encode(['status' => 4,'msg' => 'Article QR code not generated']);
}
//查询文章内容
$aMain = empty($aArticleContent['main']) ? [] : $aArticleContent['main'];;
$sContent = empty($aMain) ? '' : implode(',', $aMain);
//请求OPENAI生成微信公众号文章内容
$aSearch = [];
$aSearch['{#content#}'] = $this->basic_html_filter($sContent);
$aSearch['{#abstract#}'] = $this->basic_html_filter($aArticle['abstract']);
$aSearch['{#title_chinese#}'] = $this->basic_html_filter($aArticle['title']);
$aSearch['{#journal_content#}'] = $this->basic_html_filter($aJournal['journal_content'] ?? '');
$aSearch['{#journal_content#}'] = trim(trim($aSearch['{#journal_content#}'],'.'),'。');
$aResult = $this->_createContentForOpenAI($aSearch,2);
$aResult = json_decode($aResult,true);
if($aResult['status'] != 1){
return json_encode($aResult);
}
$aContent = empty($aResult['data']) ? [] : $aResult['data'];
if(empty($aContent)){
return json_encode(['status' => 4,'msg' => 'Data is empty']);
}
//组装数据
$aContent['article_id'] = $iArticleId;
$aContent['title_english'] = $aArticle['title'];
$aContent['journal_id'] = $aArticle['journal_id'];
//更新数据库
$aContent['ai_article_id'] = $iId;
$aContent['author'] = empty($aJournal['publish_author']) ? 'TMR编辑部' : $aJournal['publish_author'];
$aResult = $this->updateAiArticle($aContent);
return $aResult;
}
// public function createForOpenAi($aArticleContent = [],$iId = 0){
// if(empty($aArticleContent) || empty($iId)){
// return json_encode(['status' => 2,'msg' => 'data is empty']);
// }
// //文章数据
// $aArticle = empty($aArticleContent['article']) ? [] : $aArticleContent['article'];
// //期刊数据
// $aJournal = empty($aArticleContent['journal']) ? [] : $aArticleContent['journal'];
// //子期刊数据
// $aJournalStage = empty($aArticleContent['journal_stage']) ? [] : $aArticleContent['journal_stage'];
// //通讯作者
// $aAuthor = empty($aArticleContent['author']) ? [] : $aArticleContent['author'];
// //生成期刊图片二维码
// $aJournalQrCode = $this->createJournalQrCode($aJournal);
// if(empty($aJournalQrCode['qrcode_url'])){
// return json_encode(['status' => 3,'msg' => 'Journal QR code not generated']);
// }
// //生成文章图片二维码
// $aArticleQrCode = $this->createArticleQrCode($aArticle);
// if(empty($aArticleQrCode['qrcode_url'])){
// return json_encode(['status' => 4,'msg' => 'Article QR code not generated']);
// }
// //查询文章内容
// $aMain = empty($aArticleContent['main']) ? [] : $aArticleContent['main'];;
// $sContent = empty($aMain) ? '' : implode(',', $aMain);
// //请求OPENAI生成微信公众号文章内容
// $aSearch = [];
// $aSearch['{#content#}'] = $this->basic_html_filter($sContent);
// $aSearch['{#abstract#}'] = $this->basic_html_filter($aArticle['abstract']);
// $aSearch['{#title_chinese#}'] = $this->basic_html_filter($aArticle['title']);
// $aSearch['{#journal_content#}'] = $this->basic_html_filter($aJournal['journal_content'] ?? '');
// $aSearch['{#journal_content#}'] = trim(trim($aSearch['{#journal_content#}'],'.'),'。');
// $aResult = $this->_createContentForOpenAI($aSearch,2);
// $aResult = json_decode($aResult,true);
// if($aResult['status'] != 1){
// return json_encode($aResult);
// }
// $aContent = empty($aResult['data']) ? [] : $aResult['data'];
// if(empty($aContent)){
// return json_encode(['status' => 4,'msg' => 'Data is empty']);
// }
// //组装数据
// $aContent['article_id'] = $iArticleId;
// $aContent['title_english'] = $aArticle['title'];
// $aContent['journal_id'] = $aArticle['journal_id'];
// //更新数据库
// $aContent['ai_article_id'] = $iId;
// $aResult = $this->updateAiArticle($aContent);
// return $aResult;
// }
/**
* 处理文章引用
* @param string $html
* @return string
*/
private function _cite($aArticle = [],$aJournal = [],$aJournalStage = []){
$no = empty($aJournalStage['stage_no']) ? ':' : '(' . $aJournalStage['stage_no'] . '):';
$jabbr = empty($aJournal['jabbr']) ? '' : $aJournal['jabbr'];
$stage_year = empty($aJournalStage['stage_year']) ? '' : $aJournalStage['stage_year'];
$stage_vol = empty($aJournalStage['stage_vol']) ? '' : $aJournalStage['stage_vol'];
$sCite = '';
if ($aArticle['journal_id'] == 22) {
$sCite = $aArticle['abbr'] . '. ' . $aArticle['title'] . '[J]. ' . choiseJabbr($aArticle['article_id'],$jabbr) . ',' . $stage_year . ',' . $stage_vol . $no . $aArticle['npp'] . '. doi:' . $aArticle['doi'];
} else {
$sCite = $aArticle['abbr'] . '. ' . $aArticle['title'] . '. <i>' . choiseJabbr($aArticle['article_id'], $jabbr) . '</i>. ' . $stage_year . ';' . $stage_vol . $no . $aArticle['npp'] . '. doi:' . $aArticle['doi'];
}
return $sCite;
}
/**
* @title 处理作者数据
* @param article_id 文章ID
* @param content 内容
*/
protected function _dealAuthor($aAuthor = array()){
//返回数组
if(empty($aAuthor)){
return [];
}
//根据邮箱查询作者信息
$aArticleId = array_unique(array_column($aAuthor, 'article_id'));
$iArticleId = $aArticleId[0];
$aEmail = array_unique(array_column($aAuthor, 'email'));
$aWhere = ['email' => ['in',$aEmail]];
$aUser = Db::name('user')->field('user_id,realname,email,localname,icon')->where($aWhere)->select();
if(empty($aUser)){
return [];
}
//查询作者详情
$aUserId = array_column($aUser, 'user_id');
$aWhere = ['reviewer_id' => ['in',$aUserId]];
$aUserInfo = DB::name('user_reviewer_info')->field('reviewer_id,technical,introduction,company')->where($aWhere)->select();
if(empty($aUserInfo)){
return [];
}
//数据处理
$aUserInfo = array_column($aUserInfo, null,'reviewer_id');
$aAuthor = array_column($aAuthor, null,'email');
$aInfo = [];
foreach ($aUser as $key => $value) {
//姓名
$sName = empty($aAuthor[$value['email']]['author_name']) ? '' : $aAuthor[$value['email']]['author_name'];
$sName = empty($sName) ? $value['localname'] : $sName;
$sName = empty($sName) ? $value['realname'] : $sName;
//单位
$sCompany = empty($aAuthor[$value['email']]['company']) ? '' : $aAuthor[$value['email']]['company'];
$sCompany1 = empty($aUserInfo[$value['user_id']]['company']) ? '' : $aUserInfo[$value['user_id']]['company'];
$sCompany = empty($sCompany) ? $sCompany1 : $sCompany;
//职称
$sTechnical = empty($aUserInfo[$value['user_id']]['technical']) ? '' : $aUserInfo[$value['user_id']]['technical'];
//简介
$sIntroduction = empty($aUserInfo[$value['user_id']]['introduction']) ? '' : $aUserInfo[$value['user_id']]['introduction'];
$aInfo[] = ['user_id' => $value['user_id'],'email' => $value['email'],'author_name' => $sName,'technical' => $sTechnical,'introduction' => $sIntroduction,'company' => $sCompany,'article_id' => $iArticleId,'create_time' => time(),'icon' => $value['icon']];
}
return $aInfo;
}
/**
* 接口请求获取Journal数据库文章信息
* @param article_id 文章ID
*/
public function getArticle($iArticleId = ''){
$aParam = $this->request->post();
$iArticleId = empty($iArticleId) ? $aParam['article_id'] : $iArticleId;
//接口请求地址
$sUrl = $this->sJournalUrl.'/wechat/Article/getArticle';
//请求接口
$aParam['article_id'] = $iArticleId;
$aResult = object_to_array(json_decode(myPost($sUrl, $aParam)));
$iStatus = empty($aResult['status']) ? 0 : $aResult['status'];
if($iStatus != 1){
return json_encode(['status' => 0,'msg' => $aResult['msg'] ?? '操作异常']);
}
$aContent = empty($aResult['data']) ? [] : $aResult['data'];
if(!empty($aContent['journal'])){
$aJournal = $aContent['journal'];
//查询期刊主题
$aWhere['issn'] = $aJournal['issn'];
$aJournalInfo = Db::name('journal')->field('journal_topic')->where($aWhere)->find();
$aContent['journal']+=$aJournalInfo;
}
return json_encode(['status' => 1,'msg' => 'success','data' => $aContent]);
}
/**
* 获取Ai生成文章信息
* @param article_id 文章ID
*/
public function getAiArticle($iArticleId = 0,$iSelectAuthor = 2,$iAiArticleId = 0){
$aParam = $this->request->post();
//文章ID
$iArticleId = empty($iArticleId) ? '' : $iArticleId;
$iArticleIdParam = empty($aParam['article_id']) ? '' : $aParam['article_id'];
$iArticleId = empty($iArticleId) ? $iArticleIdParam : $iArticleId;
//AI生成文章ID
$iAiArticleId = empty($iAiArticleId) ? '' : $iAiArticleId;
$iAiArticleIdParam = empty($aParam['ai_article_id']) ? '' : $aParam['ai_article_id'];
$iAiArticleId = empty($iAiArticleId) ? $iAiArticleIdParam : $iAiArticleId;
if(empty($iArticleId) && empty($iAiArticleId)){
return json_encode(['status' => 2,'msg' => 'Please select the article to be generated']);
}
//查询AI生成的文章内容
$aWhere = ['is_delete' => 2];
if(!empty($iArticleId)){
$aWhere['article_id'] = $iArticleId;
}
if(!empty($iAiArticleId)){
$aWhere['ai_article_id'] = $iAiArticleId;
}
$aAiArticle = Db::name('ai_article')->where($aWhere)->find();
if(empty($aAiArticle)){
return json_encode(['status' => 1,'msg' => 'data is null','data' => ['ai_article' => []]]);
}
$iArticleId = empty($aAiArticle['article_id']) ? 0 : $aAiArticle['article_id'];
//查询文章通讯作者
$aAiAuthor = [];
if($iSelectAuthor == 2){
$aResult = json_decode($this->getArticle($iArticleId),true);
if($aResult['status'] == 1){
//获取数据
$aArticleContent = empty($aResult['data']) ? [] : $aResult['data'];
//通讯作者
$aAuthor = empty($aArticleContent['author']) ? [] : $aArticleContent['author'];
if(!empty($aAuthor)){
$aAiAuthor = $this->_dealAuthor($aAuthor);
if(!empty($aAiAuthor)){
foreach ($aAiAuthor as $key => $value) {
$aAiAuthor[$key]['icon_path'] = empty($value['icon']) ? '/static/img/userImg.f3d9bc3b.jpg' : '/public/usericon/'.$value['icon'];
}
}
}
}
}
//查询是否上传到微信草稿箱
if(!empty($iArticleId)){
$aDraft = Db::name('ai_wechat_article')->where(['article_id' => $iArticleId,'is_delete' => 2])->column('template_id');
$aAiArticle['upload_draft'] = $aDraft;
}
return json_encode(['status' => 1,'msg' => 'success','data' => ['ai_article' => $aAiArticle,'ai_article_author' => $aAiAuthor]]);
}
/**
* 基础HTML过滤
* @param string $html
* @return string
*/
private function basic_html_filter($html) {
// 移除所有HTML标签及PHP标签
$text = empty($html) ? '' : strip_tags($html);
// 转换HTML实体
$text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
// 合并连续空白字符
$text = preg_replace('/\s+/u', ' ', $text);
return trim($text);
}
/**
* @title AI生成稿件内容入库
* @param article_id 文章ID
* @param content 内容
*/
protected function addAiArticle($aParam = array(),$aAuthor = []){
//返回数组
$aResult = ['status' => 1,'msg' => 'AI article added successfully','data' => []];
//必填参数验证
$aFields = $this->aAiFileds;
$bStatus = true;
$sFiled = '';
$aInsertParam = [];
foreach($aFields as $val){
if(empty($aParam[$val])){
$bStatus = false;
$sFiled = $val;
break;
}
if($val == 'article_id'){
$aInsertParam[$val] = $aParam[$val];
continue;
}
$aInsertParam[$val] = empty($aParam[$val]) ? '' : addslashes(strip_tags($aParam[$val]));
}
if($bStatus == false){
return json_encode(['status' => 2,'msg' => $sFiled.'cannot be empty']);
}
//执行入库
$aInsertParam['create_time'] = time();
//作者判断空值
$aInsertParam['author'] = empty($aInsertParam['author']) ? 'TMR编辑部' : $aInsertParam['author'];
if(!$iId = Db::name('ai_article')->insertGetId($aInsertParam)){
return ['status' => 3,'msg' => 'Adding AI article failed'];
}
$aResult['data'] = array_merge($aInsertParam,['ai_article_id' => $iId]);
return json_encode($aResult);
}
/**
* @title AI生成稿件内容入库
* @param article_id 文章ID
* @param content 内容
*/
public function updateAiArticle($aParam = array()){
//返回数组
$aResult = ['status' => 1,'msg' => 'AI article updated successfully','data' => []];
//获取参数
$aParam = empty($aParam) ? $this->request->post() : $aParam;
//主键ID
$iAiArticleId = empty($aParam['ai_article_id']) ? 0 : $aParam['ai_article_id'];
//文章ID
$iArticleId = empty($aParam['article_id']) ? 0 : $aParam['article_id'];
//查询内容是否存在
$aWhere = ['is_delete' => 2];
if(empty($iArticleId) && empty($iArticleId)){
return json_encode(['status' => 2,'msg' => 'Please select the article to be modified']);
}
if(!empty($iArticleId)){
$aWhere['article_id'] = $iArticleId;
}
if(!empty($iAiArticleId)){
$aWhere['ai_article_id'] = $iAiArticleId;
}
$aAiArticle = Db::name('ai_article')->where($aWhere)->find();
if(empty($aAiArticle)){
return json_encode(['status' => 3,'msg' => 'he article content of WeChat official account has not been generated']);
}
//必填参数验证
$aFields = $this->aAiFileds;
$sFiled = '';
$aUpdateParam = [];
foreach($aFields as $val){
if(!isset($aParam[$val])){
continue;
}
$aUpdateParam[$val] = empty($aParam[$val]) ? '' : addslashes(strip_tags($aParam[$val]));
}
if(empty($aUpdateParam)){
return json_encode(['status' => 1,'msg' => 'No data currently being processed']);
}
Db::startTrans();
//执行入库
$aUpdateParam['update_time'] = time();
// $aUpdateParam['author'] = empty($aUpdateParam['author']) ? 'TMR编辑部' : $aUpdateParam['author'];
$aUpdateParam['is_generate'] = 1;
$result = Db::name('ai_article')->where('ai_article_id',$iAiArticleId)->limit(1)->update($aUpdateParam);
if($result === false){
$aResult = json_encode(['status' => 3,'msg' => 'UPDATEING AI article failed']);
}
$aResult['data'] = $aUpdateParam;
//更新作者信息
$aAuthorList = empty($aParam['author_list']) ? []: $aParam['author_list'];
$aAuthorList = is_array( $aAuthorList) ? $aAuthorList: json_decode($aAuthorList,true);
if(!empty($aAuthorList)){
$aAuthorList = array_column($aAuthorList, null,'email');
//根据邮箱查询作者信息
$aEmail = array_keys($aAuthorList);
$aUserInfo = $aUserReviewer = [];
if(!empty($aEmail)){
$aUserParam = ['email' => ['in',$aEmail]];
$aUserInfo = Db::name('user')->field('email,user_id')->where($aUserParam)->select();
if(!empty($aUserInfo)){
$aUserId = array_column($aUserInfo, 'user_id');
//查询用户附表
$aWhere = ['reviewer_id' => ['in',$aUserId]];
$aUserReviewer = Db::name('user_reviewer_info')->where($aWhere)->column('reviewer_id');
}
}
//更新用户信息
if(!empty($aUserInfo)){
foreach ($aUserInfo as $key => $value) {
$aUser = empty($aAuthorList[$value['email']]) ? [] : $aAuthorList[$value['email']];
if(empty($aUser)){
continue;
}
//更新作者名字
if(isset($aUser['author_name'])){
$aUpdate = ['localname' => $aUser['author_name']];
Db::name('user')->where('user_id',$value['user_id'])->update($aUpdate);
}
//更新作者简介和单位
$aUpdateReviewer = [];
if(isset($aUser['technical'])){
$aUpdateReviewer['technical'] = $aUser['technical'];
}
if(isset($aUser['introduction'])){
$aUpdateReviewer['introduction'] = $aUser['introduction'];
}
if(isset($aUser['company'])){
$aUpdateReviewer['company'] = $aUser['company'];
}
if(isset($aUpdateReviewer)){
if(in_array($value['user_id'], $aUserReviewer)){//更新
Db::name('user_reviewer_info')->where('reviewer_id',$value['user_id'])->limit(1)->update($aUpdateReviewer);
}
if(!in_array($value['user_id'], $aUserReviewer)){//插入
$aUpdateReviewer['reviewer_id'] = $value['user_id'];
Db::name('user_reviewer_info')->insert($aUpdateReviewer);
}
}
}
}
}
Db::commit();
$aResult['data'] = $aUpdateParam;
return json_encode($aResult);
}
/**
* 文章内容选择模版生成数据
* @param article_id 文章ID
* @param template_id 模版ID
* @param $iIsSync 是否同步素材到微信 1是2否
*/
public function getTemplateContent($iArticleId = '',$iTemplateId = '',$iIsSync = 2){
//获取参数
$aParam = $this->request->post();
//文章ID
$iArticleId = empty($iArticleId) ? $aParam['article_id'] ?? '' : $iArticleId;
//模版ID
$iTemplateId = empty($iTemplateId) ? $aParam['template_id'] ?? '' : $iTemplateId;
//必填参数验证
if(empty($iArticleId)){
return json_encode(['status' => 2, 'msg' => 'Please select an article']);
}
if(empty($iTemplateId)){
return json_encode(['status' => 2, 'msg' => 'Please select a template']);
}
//获取AI生成文章内容
$aAiContent = json_decode($this->getAiArticle($iArticleId,1),true);
$aAiContent = empty($aAiContent['data']) ? [] : $aAiContent['data'];
$aAiArticle = empty($aAiContent['ai_article']) ? [] : $aAiContent['ai_article'];
//判断是否生成AI内容
if(empty($aAiArticle)){
return json_encode(['status' => 3, 'msg' => 'The article content of WeChat official account has not been generated']);
}
//模版ID
$iTemplateId = empty($iTemplateId) ? $aAiArticle['template_id'] : $iTemplateId;
//获取文章内容
$aResult = json_decode($this->getArticle($iArticleId),true);
if($aResult['status'] != 1){
return json_encode($aResult);
}
//获取数据
$aArticleContent = empty($aResult['data']) ? [] : $aResult['data'];
//文章数据
$aArticle = empty($aArticleContent['article']) ? [] : $aArticleContent['article'];
//期刊数据
$aJournal = empty($aArticleContent['journal']) ? [] : $aArticleContent['journal'];
//子期刊数据
$aJournalStage = empty($aArticleContent['journal_stage']) ? [] : $aArticleContent['journal_stage'];
//通讯作者
$aAuthor = empty($aArticleContent['author']) ? [] : $aArticleContent['author'];
//文章图片
$sArticleIcon = trim($this->sJournalUsx,'/').$this->sArticleIcon.$aArticle['article_icon'];
//期刊图片
$sJournalIcon = trim($this->sJournalUsx,'/').$this->sJournalIcon.$aJournal['journal_icon'];
//期刊编辑二维码
$sEditorQrcode = empty($aJournal['editor_qrcode']) ? '' : $aJournal['editor_qrcode'];
$sEditorQrcode = trim($this->sSubmissionUrl,'/').$this->sJournalEditorQrcode.$sEditorQrcode;
//获取期刊图片二维码
$aJournalQrCode = $this->createJournalQrCode($aJournal);
$sJournalCode = empty($aJournalQrCode['qrcode_url']) ? '' : $this->sSubmissionUrl.'public/qrcode/'.$aJournalQrCode['qrcode_url'];
$aAiArticle['journal_qrcode'] = $sJournalCode;
//文章图片二维码
$aArticleQrCode = $this->createArticleQrCode($aArticle);
$sArticleCode = empty($aArticleQrCode['qrcode_url']) ? '' : $this->sSubmissionUrl.'public/qrcode/'.$aArticleQrCode['qrcode_url'];
$aAiArticle['article_qrcode'] = $sArticleCode;
//文章cite
$aAiArticle['cite'] = $this->_cite($aArticle,$aJournal,$aJournalStage);
// //上传素材到微信
if($iIsSync == 1){
//文章图片上传
$aUpload = ['article_id' => $iArticleId,'icon' => $sArticleIcon];
$aArticleResult = json_decode($this->_addArticleMaterial($aUpload),true);
$aArticleData = empty($aArticleResult['data']) ? [] : $aArticleResult['data'];
$aAiArticle['article_icon'] = empty($aArticleData['media_url']) ? $sArticleIcon : $aArticleData['media_url'];
//期刊图片上传
$aUpload = ['journal_id' => $aAiArticle['journal_id'],'icon' => $sJournalIcon];
$aJournalResult = json_decode($this->_addJournalMaterial($aUpload),true);
$aJournalData = empty($aJournalResult['data']) ? [] : $aJournalResult['data'];
$aAiArticle['journal_icon'] = empty($aJournalData['media_url']) ? $sJournalIcon : $aJournalData['media_url'];
//期刊二维码图片上传
$aUpload = ['journal_id' => $aAiArticle['journal_id']];
$aJournalQrCodeResult = json_decode($this->_updateJournalQrcode($aUpload),true);
$aJournalQrCodeData = empty($aJournalQrCodeResult['data']) ? [] : $aJournalQrCodeResult['data'];
$aAiArticle['journal_qrcode'] = empty($aJournalQrCodeData['media_url']) ? $sJournalIcon : $aJournalQrCodeData['media_url'];
//文章二维码图片上传
$aUpload = ['article_id' => $iArticleId];
$aArticleQrCodeResult = json_decode($this->_updateArticleQrcode($aUpload),true);
$aArticleQrCodeData = empty($aArticleQrCodeResult['data']) ? [] : $aArticleQrCodeResult['data'];
$aAiArticle['article_qrcode'] = empty($aArticleQrCodeData['media_url']) ? $sArticleIcon : $aArticleQrCodeData['media_url'];
//作者图片上传
if(!empty($aAuthor)){
$aAuthor = $this->_dealAuthor($aAuthor);
foreach ($aAuthor as $key => $value) {
if(empty($value['icon'])){
continue;
}
//文章二维码图片上传
$aUpload = ['email' => $value['email'],'icon' => $value['icon'],'user_id' => $value['user_id']];
$aAuthorResult = json_decode($this->_updateArticleAuthor($aUpload),true);
$aAuthorData = empty($aAuthorResult['data']) ? [] : $aAuthorResult['data'];
$aAuthor[$key]['icon'] = empty($aAuthorData['media_url']) ? $value['icon'] : $aAuthorData['media_url'];
}
}
//上传期刊编辑二维码
$aUpload = ['editor_qrcode' => $aJournal['editor_qrcode']??'','journal_id' => $aAiArticle['journal_id']];
$aJournalEditorQrCodeResult = json_decode($this->_updateJournalEditorQrcode($aUpload),true);
$aJournalEditorQrCodeData = empty($aJournalEditorQrCodeResult['data']) ? [] : $aJournalEditorQrCodeResult['data'];
$aAiArticle['editor_qrcode'] = empty($aJournalEditorQrCodeData['media_url']) ? $sEditorQrcode : $aJournalEditorQrCodeData['media_url'];
}else{
//处理文章图片地址数据
$aAiArticle['article_icon'] = $sArticleIcon;
//处理文章期刊图片地址数据
$aAiArticle['journal_icon'] = $sJournalIcon;
//期刊编辑二维码图片地址数据
$aAiArticle['editor_qrcode'] = $sEditorQrcode;
//作者信息处理
if(!empty($aAuthor)){
$aAuthor = $this->_dealAuthor($aAuthor);
}
}
//期刊访问地址
$journal_usx = trim($this->sJournalUsx,'/').'/';
if(!empty($aJournal['journal_usx'])){
//地址
$journal_usx .= $aJournal['journal_usx']??''.'/';
}
$aAiArticle['journal_usx_url'] = trim($journal_usx);
//处理期刊内容
if(empty($aJournal['journal_content'])){
$aJournal['journal_content'] = empty($aJournal['journal_content']) ? $aJournal['journal_content_english'] : $aJournal['journal_content'];
}
$aAiArticle += $aJournal;
//获取模版信息
$sTemplatePath = ROOT_PATH."public/wechatTemplate/".$iTemplateId.'.html';
// 验证文件有效性
if (!file_exists($sTemplatePath)) {
return json_encode(['status' => 4, 'msg' => 'Article template does not exist']);
}
if (!is_readable($sTemplatePath)) {
return json_encode(['status' => 5, 'msg' => 'The article template is unreadable']);
}
//获取模版内容
$sTemplate = file_get_contents($sTemplatePath);
//数据处理
$aSearch = [];
foreach ($aAiArticle as $key => $value) {
if(is_array($value)){
continue;
}
$aSearch['{###'.$key.'###}'] = empty($value) ? '' : htmlspecialchars(strip_tags($value));
}
//处理通讯作者信息数据
$aAuthorInfo = json_decode($this->dealTemplateAuthor($aAuthor,$iTemplateId),true);
$aAuthorInfo = empty($aAuthorInfo['data']) ? [] : $aAuthorInfo['data'];
//通讯作者列表
$sAuthorList = empty($aAuthorInfo['author_info']) ? '' : implode("\n", $aAuthorInfo['author_info']);
if(empty($sAuthorList)){
$aSearch['{###author_summary###}'] = '';
}else{
//获取通讯作者模版数据
$sSummaryTemplatePath = ROOT_PATH."public/wechatTemplate/".$iTemplateId.'_author_summary.html';
$sSummaryTemplatePath = file_get_contents($sSummaryTemplatePath);
//替换数据处理
$sSummaryTemplate = str_replace('{###author_info###}', $sAuthorList, $sSummaryTemplatePath);
$aSearch['{###author_summary###}'] = $sSummaryTemplate;
}
$aSearch['{###author###}'] = empty($aAuthorInfo['author']) ? ' ' : $aAuthorInfo['author'];
//处理往期推荐数据
$aPreviousRecommend = json_decode($this->dealTemplatePreviousRecommend($aArticle,$iTemplateId),true);
if(empty($aPreviousRecommend['data'])){
$aSearch['{###previous_recommend_summary###}'] = '';
}else{
$sSummaryTemplatePath = ROOT_PATH."public/wechatTemplate/".$iTemplateId.'_previous_recommend_summary.html';
$sSummaryTemplate = file_get_contents($sSummaryTemplatePath);
$aSearchInfo['{###previous_recommend###}'] = empty($aPreviousRecommend['data']) ? ' ' : implode("\n", $aPreviousRecommend['data']);
$sSummaryTemplate = str_replace(array_keys($aSearchInfo), array_values($aSearchInfo), $sSummaryTemplate);
$aSearch['{###previous_recommend_summary###}'] = $sSummaryTemplate;
}
//处理期刊主题数据
$sJournalTopic = empty($aJournal['journal_topic']) ? '' : $aJournal['journal_topic'];
$aTopic = json_decode($this->dealTemplateTopic($sJournalTopic,$iTemplateId),true);
if(empty($aTopic['data'])){
$aSearch['{###topic_name_summary###}'] = '';
}else{
$sSummaryTemplatePath = ROOT_PATH."public/wechatTemplate/".$iTemplateId.'_topic_summary.html';
$sSummaryTemplate = file_get_contents($sSummaryTemplatePath);
$aSearchInfo['{###topic_name###}'] = empty($aTopic['data']) ? ' ' : implode("\n", $aTopic['data']);
$sSummaryTemplate = str_replace(array_keys($aSearchInfo), array_values($aSearchInfo), $sSummaryTemplate);
$aSearch['{###topic_name_summary###}'] = $sSummaryTemplate;
}
//模版替换变量
if(empty($aSearch)){
return json_encode(['status' => 6, 'msg' => '模版内容不能为空']);
}
$aSearch['{###jabbr###}'] = trim(trim($aSearch['{###jabbr###}'],'.'),'。');
$aSearch['{###free_year###}'] = date('Y');
$aSearch['{###covered###}'] = '内容涵盖'.str_replace('研究涵盖', '', $aSearch['{###covered###}']);
$sTemplate = str_replace(array_keys($aSearch), array_values($aSearch), $sTemplate);
file_put_contents(ROOT_PATH.'public/template_info.html', $sTemplate);
return json_encode(['status' => 1, 'msg' => '模版生成成功','data' => ['template' => $sTemplate]]);
}
/**
* 处理模版通讯作者
* @param article_id 文章ID
*/
private function dealTemplateAuthor($aAuthor = [],$iTemplateId = 0){
//必填字段判断
if(empty($aAuthor) || empty($iTemplateId)){
return json_encode(['status' => 2,'msg' => 'Corresponding author or template does not exist']);
}
//处理作者
// $aAuthor = $this->_dealAuthor($aAuthor);
//获取通讯作者模版
$sAuthorTemplatePath = ROOT_PATH."public/wechatTemplate/".$iTemplateId.'_author.html';
if (!file_exists($sAuthorTemplatePath)) {
return json_encode(['status' => 3, 'msg' => 'Corresponding author template does not exist','data' => '']);
}
if (!is_readable($sAuthorTemplatePath)) {
return json_encode(['status' => 4, 'msg' => 'The corresponding author template is unreadable','data' => '']);
}
$sAuthorTemplate = file_get_contents($sAuthorTemplatePath);
//处理模版变量
$aAuthorSerachInfo = [];
$sAuthorInfo = '';
$aLogo = $this->aLogo;
//请求AI翻译
$sContent = '';
$aSearch['{#content#}'] = json_encode($aAuthor);
$aResult = json_decode($this->_createContentForOpenAI($aSearch,1),true);
$aContent = empty($aResult['data']) ? [] : array_column($aResult['data'], null,'email');
foreach ($aAuthor as $key => $value) {
//请求AI翻译
$aInfo = empty($aContent[$value['email']]) ? [] : $aContent[$value['email']];
//替换模版
$aAuthorSerach = [];
//所属单位处理
$value['company'] = empty($aInfo['company']) ? $value['company'] : $aInfo['company'];
if(!empty($value['company'])){
$value['company'] =str_replace('', ',', $value['company']);
$aCompany = explode(',', $value['company']);
}
$value['company'] = empty($aCompany[0]) ? $value['company'] : trim($aCompany[0],',');
//简介处理
$value['introduction'] = empty($aInfo['introduction']) ? $value['introduction'] : $aInfo['introduction'];
//职称处理
$value['technical'] = empty($aInfo['technical']) ? $value['technical'] : $aInfo['technical'];
if(empty($value['introduction'])){//简介为空不处理
$sTechnical = empty($value['technical']) ? '老师' : $value['technical'];
$sAuthorInfo .= $value['company'].$value['author_name'].$sTechnical.',';
continue;
}
//缓缓处理进行模版替换
foreach ($value as $k => $val) {
if($k == 'icon'){//头像拼接处理
$sIconInfo = empty($val) ? $aLogo['url'] : $val;
$aParsedUrl = parse_url($sIconInfo);
if(empty($aParsedUrl['scheme'])){
$aAuthorSerach['{###icon_path###}'] = trim($this->sSubmissionUrl,'/').'/public/usericon/'.$val;
}else{
$aAuthorSerach['{###icon_path###}'] = $val;
}
$aAuthorSerach['{###icon_path###}'] = trim($aAuthorSerach['{###icon_path###}'],'/');
}else{
$aAuthorSerach['{###'.$k.'###}'] = trim($val,'/');
}
}
$aAuthorSerachInfo[] = str_replace(array_keys($aAuthorSerach), array_values($aAuthorSerach), $sAuthorTemplate);
}
$sAuthorInfo = trim($sAuthorInfo,',');
return json_encode(['status' => 1,'msg' => 'success','data' => ['author_info' => $aAuthorSerachInfo,'author' => trim($sAuthorInfo,';')]]);
}
/**
* 处理模版主题
* @param article_id 文章ID
*/
private function dealTemplateTopic($sTopic = '',$iTemplateId = 0){
if(empty($iTemplateId)){
return json_encode(['status' => 2,'template does not exist']);
}
if(empty($sTopic)){
return json_encode(['status' => 2,'topic does not exist']);
}
//获取主题模版
$sTemplatePath = ROOT_PATH."public/wechatTemplate/".$iTemplateId.'_topic.html';
if (!file_exists($sTemplatePath)) {
return json_encode(['status' => 4, 'msg' => 'Corresponding author template does not exist']);
}
if (!is_readable($sTemplatePath)) {
return json_encode(['status' => 5, 'msg' => 'The corresponding author template is unreadable']);
}
$sTemplate = file_get_contents($sTemplatePath);
//数据处理
$sTopic = trim($sTopic);
$aTopic = empty($sTopic) ? [] : explode(',', $sTopic);
$aSearchInfo = [];
if(!empty($aTopic)){
foreach ($aTopic as $key => $value) {
$aSerach['{###topic_name###}'] = trim(trim(trim($value),'【'),'】');
$aSearchInfo[] = str_replace(array_keys($aSerach), array_values($aSerach), $sTemplate);
}
}
return json_encode(['status' => 1,'msg' => 'success','data' => $aSearchInfo]);
}
/**
* 处理往期推荐
* @param article_id 文章ID
*/
private function dealTemplatePreviousRecommend($aArticle=[],$iTemplateId = 0){
if(empty($iTemplateId)){
return json_encode(['status' => 2,'template does not exist']);
}
//获取往期推荐模版
$sTemplatePath = ROOT_PATH."public/wechatTemplate/".$iTemplateId.'_previous_recommend.html';
if (!file_exists($sTemplatePath)) {
return json_encode(['status' => 3, 'msg' => 'Corresponding author template does not exist']);
}
if (!is_readable($sTemplatePath)) {
return json_encode(['status' => 4, 'msg' => 'The corresponding author template is unreadable']);
}
$sTemplate = file_get_contents($sTemplatePath);
//判断是否关联文章
if(empty($aArticle['related'])){
return json_encode(['status' => 6, 'msg' => 'Unrelated articles']);
}
//获取关联文章信息
$aWhere = ['article_id' => ['in',json_decode($aArticle['related'],true)],'is_delete' => 2];
$aRecommend = Db::name('ai_article')->field('article_id')->where($aWhere)->select();
$aSearchInfo = [];
if(!empty($aRecommend)){
$aId = array_column($aRecommend, 'article_id');
//查询是否推送到微信公众号并且已发布
$aWhere['template_id'] = $iTemplateId;//,'is_publish' => 1
$aWechatArticle = Db::name('ai_wechat_article')->where($aWhere)->column('article_id');
if(!empty($aWechatArticle)){
return json_encode(['status' => 6, 'msg' => 'No article published on WeChat official account was found']);
}
//查询文章图片
$aWhere = ['w_article_id' => ['in',$aId]];
$aProductionArticle = Db::name('production_article')->where($aWhere)->column('w_article_id,icon');
foreach ($aRecommend as $key => $value) {
if(!in_array($value['article_id'], $aWechatArticle)){
continue;
}
$aSerach['{###wechat_url###}'] = $value['wechat_url'];
$sIcon = empty($aProductionArticle[$value['article_id']]) ? '' : trim($this->sJournalUsx,'/').$this->sArticleIcon.$aProductionArticle[$value['article_id']];
$aSerach['{###wechat_media_url###}'] = empty($value['wechat_media_url']) ? $sIcon : $value['wechat_media_url'];
$aSearchInfo[] = str_replace(array_keys($aSerach), array_values($aSerach), $sTemplate);
}
}
return json_encode(['status' => 1,'msg' => 'success','data' => $aSearchInfo]);
}
/**
* @title 文章AI生成稿件内容查询
* @param aJournal 期刊信息
*/
private function createJournalQrCode($aJournal = []){
$iJournalId = empty($aJournal['journal_id']) ? 0 : $aJournal['journal_id'];
//判断期刊二维码是否生成
$aWhere = ['journal_id' => $iJournalId];
$aQrCode = Db::name('ai_journal_qrcode')->where($aWhere)->find();
if(!empty($aQrCode)){
return $aQrCode;
}
//创建二维码
//生成图片地址
$sImagePath = 'journal/'.$iJournalId.'.jpg';
$sQrCodeUrl = ROOT_PATH.'public/qrcode/'.$sImagePath;
// // 验证图片是否存在
// if (file_exists($sQrCodeUrl)) {
// return ['qrcode_url' => $sImagePath];
// }
//地址
$journal_usx = empty($aJournal['journal_usx']) ? '' : $aJournal['journal_usx'];
$sUrl = trim($this->sJournalUsx,'/').'/'.$journal_usx.'/';
//二维码中间图片
$sLogo = empty($aJournal['journal_icon']) ? '' : $aJournal['journal_icon'];
if(empty($sLogo)){
$sImg = QrCodeImage::generate($sUrl,500,$sQrCodeUrl);
}else{
$sLogo = trim($this->sJournalUsx,'/').$this->sJournalIcon.$sLogo;
$aImageInfo = json_decode($this->getImage($sLogo,$iJournalId,'journal'),true);
if(empty($aImageInfo['data'])){
$sImg = QrCodeImage::generate($sUrl,500,$sQrCodeUrl);
}
$sImg = QrCodeImage::withLogo($sUrl,$aImageInfo['data'],500,100, $sQrCodeUrl);
}
//查询是否生成
$aQrcode = Db::name('ai_journal_qrcode')->where('journal_id',$iJournalId)->find();
//插入期刊二维码表
$aParam = ['journal_id' => $iJournalId,'qrcode_url' => $sImagePath,'create_time' => time()];
Db::startTrans();
$result = Db::name('ai_journal_qrcode')->insertGetId($aParam);
if(!empty($aQrcode)){
$aUpdate['update_time'] = time();
$aUpdate['is_delete'] = 1;
$responseUpdate = Db::name('ai_journal_qrcode')->where('id',$aQrcode['id'])->limit(1)->update($aUpdate);
}
Db::commit();
return $aParam;
}
/**
* @title 文章AI生成稿件内容查询
* @param aArticle 文章信息
*/
private function createArticleQrCode($aArticle = []){
$iArticleId = empty($aArticle['article_id']) ? 0 : $aArticle['article_id'];
//判断期刊二维码是否生成
$aWhere = ['article_id' => $iArticleId];
$aQrCode = Db::name('ai_article_qrcode')->where($aWhere)->find();
if(!empty($aQrCode)){
return $aQrCode;
}
//创建二维码
//生成图片地址
$sImagePath = 'article/'.$iArticleId.'.jpg';
$sQrCodeUrl = ROOT_PATH.'public/qrcode/'.$sImagePath;
// 验证图片是否存在
// if (file_exists($sQrCodeUrl)) {
// return ['qrcode_url' => $sImagePath];
// }
//地址
$sUrl = trim($this->sJournalUsx,'/').'/'.'article.html?J_num='.$aArticle['journal_id'].'&a_id='.$iArticleId;
//二维码中间图片
$sLogo = $aArticle['article_icon'];
if(empty($sLogo)){
$sImg = QrCodeImage::generate($sUrl,500,$sQrCodeUrl);
}else{
$sLogo = trim($this->sJournalUsx,'/').$this->sArticleIcon.$sLogo;
$aImageInfo = json_decode($this->getImage($sLogo,$iArticleId,'article'),true);
if(empty($aImageInfo['data'])){
$sImg = QrCodeImage::generate($sUrl,500,$sQrCodeUrl);
}
$sImg = QrCodeImage::withLogo($sUrl,$aImageInfo['data'],500,100, $sQrCodeUrl);
}
//查询是否生成
$aQrcode = Db::name('ai_article_qrcode')->where('article_id',$iArticleId)->find();
//插入期刊二维码表
$aParam = ['article_id' => $iArticleId,'qrcode_url' => $sImagePath,'create_time' => time()];
Db::startTrans();
$result = Db::name('ai_article_qrcode')->insertGetId($aParam);
if(!empty($aQrcode)){
$aUpdate['update_time'] = time();
$aUpdate['is_delete'] = 1;
$responseUpdate = Db::name('ai_article_qrcode')->where('id',$aQrcode['id'])->limit(1)->update($aUpdate);
}
Db::commit();
return $aParam;
}
/**
* @title 请求OPENAI翻译内容
* @param article_id 文章ID
*/
public function translate($param = [],$url=''){
if (!is_array($param)) {
throw new Exception("参数必须为array");
}
$httph = curl_init($url);
// curl_setopt($httph, CURLOPT_SSL_VERIFYPEER, 0);
// curl_setopt($httph, CURLOPT_SSL_VERIFYHOST, 1);
curl_setopt($httph, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($httph, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
curl_setopt($httph, CURLOPT_POST, 1); //设置为POST方式
curl_setopt($httph, CURLOPT_POSTFIELDS, $param);
curl_setopt($httph, CURLOPT_SSL_VERIFYPEER, false);
// curl_setopt($httph, CURLOPT_RETURNTRANSFER,0);
// curl_setopt($httph, CURLOPT_HEADER,1);
$rst = curl_exec($httph);
curl_close($httph);
return json_decode($rst,true);
}
/**
* @title curl 请求获取图片保存到本地
* @param sPath 图片链接地址
*/
public function getImage($sPath = '',$iId = 0,$sType = 'journal'){
//判断参数
if(empty($sPath)){
return json_encode(['status' => 2,'msg' => 'url is empty','data' => '']);
}
//获取图片名称
$aImageInfo = pathinfo($sPath);
//图片后缀名
$sExtension = empty($aImageInfo['extension']) ? 'jpg' : $aImageInfo['extension'];
//图片地址
$sImagePath = $sType.'/imgae_'.$iId.'.'.$sExtension;
$sImagePath = ROOT_PATH.'public/qrcode/'.$sImagePath;
if (file_exists($sImagePath)) {
return json_encode(['status' => 1,'msg' => 'success','data' => $sImagePath]);
}
//curl 请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$sPath); // 设置请求URL
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 设置返回数据而不是直接输出
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 禁用SSL验证
$response = curl_exec($ch);
if (curl_errno($ch)) {
return json_encode(['status' => 3,'msg' => 'Error:' . curl_error($ch),'data' => $sImagePath]);
}
//保存图片
file_put_contents($sImagePath, $response);
curl_close($ch);
return json_encode(['status' => 1,'msg' => 'success','data' => $sImagePath]);
}
/**
* 文章同步到微信公众号草稿箱
* @param article_id 文章ID
*/
public function syncWechat(){
//获取参数
$aParam = $this->request->post();
//文章ID
$iArticleId = empty($iArticleId) ? $aParam['article_id'] ?? '' : $iArticleId;
//模版ID
$iTemplateId = empty($iTemplateId) ? $aParam['template_id'] ?? '' : $iTemplateId;
//必填参数验证
if(empty($iArticleId)){
return json_encode(['status' => 2, 'msg' => 'Please select an article']);
}
if(empty($iTemplateId)){
return json_encode(['status' => 2, 'msg' => 'Please select a template']);
}
//获取模版生成内容
$aResult = json_decode($this->getTemplateContent($iArticleId,$iTemplateId,1),true);
$iStatus = empty($aResult['status']) ? 0 : $aResult['status'];//状态
$sMsg = empty($aResult['msg']) ? 'The content is empty' : $aResult['msg'];
if($iStatus != 1){
return json_encode(['status' => 3, 'msg' => $sMsg]);
}
$aData = empty($aResult['data']) ? [] : $aResult['data'];
if(empty($aData['template'])){
return json_encode(['status' => 4, 'msg' => $sMsg]);
}
//请求微信公众号接口推送
$aParam['template_content'] = $aData['template'];
$aParam['template_id'] = $iTemplateId;
$aResult = $this->addDraft($aParam);
return $aResult;
}
/**
* 添加文章素材
* @param article_id 文章ID
* @param media_id 微信公众号素材media_id
* @param media_url 微信公众号素材地址
* @param sType select 查询add 新增
* @param $sPath 图片地址
*/
private function _addArticleMaterial($aParam = []){
//文章ID
$iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id'];
//文章图片
$sIcon = empty($aParam['icon']) ? '' : $aParam['icon'];
//必填验证
if(empty($iArticleId) || empty($sIcon)){
return json_encode(['status' => 2,'msg' => 'article_id or article_image is empty']);
}
//处理图片地址
$aImageInfo = pathinfo($sIcon);
//图片后缀名
$sExtension = empty($aImageInfo['extension']) ? 'jpg' : $aImageInfo['extension'];
$sImagePath = 'article/imgae_'.$iArticleId.'.'.$sExtension;
$sImagePath = ROOT_PATH.'public/qrcode/'.$sImagePath;
// if (!file_exists($sImagePath)) {//下载图片
$aImageInfo = json_decode($this->getImage($sIcon,$iArticleId,'article'),true);
if(empty($aImageInfo['data'])){
return json_encode(['status' => 3,'msg' => 'Image download failed']);
}
// }
//调用微信新增素材接口上传
$aUploadResult = json_decode($this->uploadMaterial($sImagePath),true);
$iStatus = empty($aUploadResult['status']) ? 0 : $aUploadResult['status'];
$sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
if($iStatus != 1){
return json_encode(['status' => 4,'msg' => $sMsg]);
}
$aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
if(empty($aData['url'])){
return json_encode(['status' => 5,'msg' => 'Material not obtained']);
}
//查询是否添加素材
$aWhere = ['article_id' => $iArticleId,'is_delete' => 2];
$aMaterial = Db::name('ai_article_material')->where($aWhere)->find();
//处理入库数据
$sMediaId = empty($aData['media_id']) ? [] : $aData['media_id'];
$sMediaUrl = empty($aData['url']) ? [] : $aData['url'];
$iTime = empty($aUploadResult['created_at']) ? time() : $aUploadResult['created_at'];
//入库数据组装
$aInsert = ['type' => 'image','media_id' => $sMediaId,'create_time' => $iTime,'article_id' => $iArticleId,'media_url' => $sMediaUrl];
Db::startTrans();
$aInsert['create_time'] = $iTime;
$responseInsert = Db::name('ai_article_material')->insert($aInsert);
if(!empty($aMaterial)){
$aUpdate['update_time'] = $iTime;
$aUpdate['is_delete'] = 1;
$responseUpdate = Db::name('ai_article_material')->where('id',$aMaterial['id'])->limit(1)->update($aUpdate);
}
Db::commit();
return json_encode(['status' => 1,'msg' => 'success','data' => $aInsert]);
}
/**
* 添加期刊素材
*/
private function _addJournalMaterial($aParam = []){
//期刊ID
$iJournalId = empty($aParam['journal_id']) ? '' : $aParam['journal_id'];
//期刊图片
$sIcon = empty($aParam['icon']) ? '' : $aParam['icon'];
if(empty($iJournalId) || empty($sIcon)){
return json_encode(['status' => 2,'msg' => 'journal_id or image is empty']);
}
//处理图片地址
$aImageInfo = pathinfo($sIcon);
//图片后缀名
$sExtension = empty($aImageInfo['extension']) ? 'jpg' : $aImageInfo['extension'];
$sImagePath = 'journal/imgae_'.$iJournalId.'.'.$sExtension;
$sImagePath = ROOT_PATH.'public/qrcode/'.$sImagePath;
// if (!file_exists($sImagePath)) {//下载图片
$aImageInfo = json_decode($this->getImage($sIcon,$iJournalId,'journal'),true);
if(empty($aImageInfo['data'])){
return json_encode(['status' => 3,'msg' => 'Image download failed']);
}
// }
//调用微信新增素材接口上传
$aUploadResult = json_decode($this->uploadMaterial($sImagePath),true);
$iStatus = empty($aUploadResult['status']) ? 0 : $aUploadResult['status'];
$sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
if($iStatus != 1){
return json_encode(['status' => 4,'msg' => $sMsg]);
}
$aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
if(empty($aData['url'])){
return json_encode(['status' => 5,'msg' => 'Material not obtained']);
}
//查询是否添加素材
$aWhere = ['journal_id' => $iJournalId,'is_delete' => 2];
$aMaterial = Db::name('ai_journal_material')->field('id,media_id,media_url')->where($aWhere)->find();
//处理入库数据
$sMediaId = empty($aData['media_id']) ? [] : $aData['media_id'];
$sMediaUrl = empty($aData['url']) ? [] : $aData['url'];
$iTime = empty($aUploadResult['created_at']) ? time() : $aUploadResult['created_at'];
//操作数据组装
$aInsert = ['type' => 'image','media_id' => $sMediaId,'journal_id' => $iJournalId,'media_url' => $sMediaUrl];
Db::startTrans();
$aInsert['create_time'] = $iTime;
$responseInsert = Db::name('ai_journal_material')->insert($aInsert);
if(!empty($aMaterial)){
$aUpdate['update_time'] = $iTime;
$aUpdate['is_delete'] = 1;
$responseUpdate = Db::name('ai_journal_material')->where('id',$aMaterial['id'])->limit(1)->update($aUpdate);
}
Db::commit();
return json_encode(['status' => 1,'msg' => 'success','data' => $aInsert]);
}
/**
* 更新期刊二维码关联微信公众号素材
*/
private function _updateJournalQrcode($aParam = []){
//期刊ID
$iJournalId = empty($aParam['journal_id']) ? '' : $aParam['journal_id'];
if(empty($iJournalId)){
return json_encode(['status' => 2,'msg' => 'journal_id or image is empty']);
}
//查询是否生成二维码
$aWhere = ['journal_id' => $iJournalId,'is_delete' => 2];
$aMaterial = Db::name('ai_journal_qrcode')->field('qrcode_url,media_id,media_url')->where($aWhere)->find();
if(empty($aMaterial)){
return json_encode(['status' => 3,'msg' => 'data is null']);
}
// if(!empty($aMaterial['media_url'])){
// return json_encode(['status' => 1,'msg' => 'success','data' => $aMaterial]);
// }
//处理图片地址
$sImagePath = ROOT_PATH.'public/qrcode/'.$aMaterial['qrcode_url'];
//调用微信新增素材接口上传
$aUploadResult = json_decode($this->uploadMaterial($sImagePath),true);
$iStatus = empty($aUploadResult['status']) ? 0 : $aUploadResult['status'];
$sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
if($iStatus != 1){
return json_encode(['status' => 4,'msg' => $sMsg]);
}
$aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
if(empty($aData['url'])){
return json_encode(['status' => 5,'msg' => 'Material not obtained']);
}
$sMediaId = empty($aData['media_id']) ? [] : $aData['media_id'];
$sMediaUrl = empty($aData['url']) ? [] : $aData['url'];
$iTime = empty($aUploadResult['created_at']) ? time() : $aUploadResult['created_at'];
$aUpdate = ['media_id' => $sMediaId,'media_url' => $sMediaUrl,'update_time' => $iTime];
$response = Db::name('ai_journal_qrcode')->where('journal_id',$iJournalId)->limit(1)->update($aUpdate);
if($response === false){
return json_encode(['status' => 3,'msg' => 'fail']);
}
return json_encode(['status' => 1,'msg' => 'success','data' => $aUpdate]);
}
/**
* 更新文章二维码关联微信公众号素材
*/
private function _updateArticleQrcode($aParam = []){
$iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id'];
if(empty($iArticleId)){
return json_encode(['status' => 2,'msg' => 'article_id is empty']);
}
//查询是否添加素材
$aWhere = ['article_id' => $iArticleId,'is_delete' => 2];
$aMaterial = Db::name('ai_article_qrcode')->field('qrcode_url,media_id,media_url')->where($aWhere)->find();
if(empty($aMaterial)){
return json_encode(['status' => 3,'msg' => 'data is null']);
}
// if(!empty($aMaterial['media_url'])){
// return json_encode(['status' => 1,'msg' => 'success','data' => $aMaterial]);
// }
//处理图片地址
$sImagePath = ROOT_PATH.'public/qrcode/'.$aMaterial['qrcode_url'];
//调用微信新增素材接口上传
$aUploadResult = json_decode($this->uploadMaterial($sImagePath),true);
$iStatus = empty($aUploadResult['status']) ? 0 : $aUploadResult['status'];
$sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
if($iStatus != 1){
return json_encode(['status' => 4,'msg' => $sMsg]);
}
$aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
if(empty($aData['url'])){
return json_encode(['status' => 5,'msg' => 'Material not obtained']);
}
//更新
$sMediaId = empty($aData['media_id']) ? [] : $aData['media_id'];
$sMediaUrl = empty($aData['url']) ? [] : $aData['url'];
$iTime = empty($aUploadResult['created_at']) ? time() : $aUploadResult['created_at'];
$aUpdate = ['media_id' => $sMediaId,'media_url' => $sMediaUrl,'update_time' => $iTime];
$response = Db::name('ai_article_qrcode')->where('article_id',$iArticleId)->limit(1)->update($aUpdate);
if($response === false){
return json_encode(['status' => 3,'msg' => 'update fail']);
}
return json_encode(['status' => 1,'msg' => 'success','data' => $aUpdate]);
}
/**
* 更新通讯作者关联微信公众号素材
*/
private function _updateArticleAuthor($aParam = []){
$sEmail = empty($aParam['email']) ? '' : $aParam['email'];
//文章图片
$sIcon = empty($aParam['icon']) ? '' : $aParam['icon'];
if(empty($sEmail) || empty($sIcon)){
return json_encode(['status' => 2,'msg' => 'email is empty']);
}
//查询是否添加素材
$aWhere = ['email' => $sEmail];
$aMaterial = Db::name('ai_author_material')->where($aWhere)->find();
if(!empty($aMaterial['media_url'])){
return json_encode(['status' => 1,'msg' => 'success','data' => $aMaterial]);
}
//处理图片地址
$sImagePath = ROOT_PATH.'/public/usericon/'.trim($sIcon,'/');
if(trim($sIcon) != '/static/img/userImg.f3d9bc3b.jpg'){//非默认头像
//调用微信新增素材接口上传
$aUploadResult = json_decode($this->uploadMaterial($sImagePath),true);
$iStatus = empty($aUploadResult['status']) ? 0 : $aUploadResult['status'];
$sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
if($iStatus != 1){
return json_encode(['status' => 4,'msg' => $sMsg]);
}
$aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
if(empty($aData['url'])){
return json_encode(['status' => 5,'msg' => 'Material not obtained']);
}
}
if(trim($sIcon) == '/static/img/userImg.f3d9bc3b.jpg'){//默认头像
$aData = $this->aLogo;
}
//更新
$sMediaId = empty($aData['media_id']) ? [] : $aData['media_id'];
$sMediaUrl = empty($aData['url']) ? [] : $aData['url'];
$iTime = empty($aUploadResult['created_at']) ? time() : $aUploadResult['created_at'];
$aInsert = ['media_id' => $sMediaId,'media_url' => $sMediaUrl,'create_time' => $iTime,'email' => $sEmail,'user_id' => $aParam['user_id']];
$response = Db::name('ai_author_material')->insert($aInsert);
if($response === false){
return json_encode(['status' => 3,'msg' => 'fail']);
}
exit;
return json_encode(['status' => 1,'msg' => 'success','data' => $aInsert]);
}
/**
* 更新通讯作者关联微信公众号素材
*/
private function _updateJournalEditorQrcode($aParam = []){
$iJournalId = empty($aParam['journal_id']) ? '' : $aParam['journal_id'];
//文章图片
$sIcon = empty($aParam['editor_qrcode']) ? '20250515/103a7cdf2f76dc4d522b7273d4b149e5.jpg' : $aParam['editor_qrcode'];
if(empty($iJournalId) || empty($sIcon)){
return json_encode(['status' => 2,'msg' => 'The journal editor did not upload the QR code']);
}
//处理图片地址
$sImagePath = ROOT_PATH.'/public/journaleditorqrcode/'.trim($sIcon,'/');
//调用微信新增素材接口上传
$aUploadResult = json_decode($this->uploadMaterial($sImagePath),true);
$iStatus = empty($aUploadResult['status']) ? 0 : $aUploadResult['status'];
$sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
if($iStatus != 1){
return json_encode(['status' => 4,'msg' => $sMsg]);
}
$aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
if(empty($aData['url'])){
return json_encode(['status' => 5,'msg' => 'Material not obtained']);
}
//查询是否添加素材
$aWhere = ['journal_id' => $iJournalId,'is_delete' => 2];
$aMaterial = Db::name('ai_journal_editor_material')->field('id,media_id,media_url')->where($aWhere)->find();
//处理入库数据
$sMediaId = empty($aData['media_id']) ? [] : $aData['media_id'];
$sMediaUrl = empty($aData['url']) ? [] : $aData['url'];
$iTime = empty($aUploadResult['created_at']) ? time() : $aUploadResult['created_at'];
//操作数据组装
$aInsert = ['type' => 'image','media_id' => $sMediaId,'journal_id' => $iJournalId,'media_url' => $sMediaUrl];
Db::startTrans();
$aInsert['create_time'] = $iTime;
$responseInsert = Db::name('ai_journal_editor_material')->insert($aInsert);
if(!empty($aMaterial)){
$aUpdate['update_time'] = $iTime;
$aUpdate['is_delete'] = 1;
$responseUpdate = Db::name('ai_journal_editor_material')->where('id',$aMaterial['id'])->limit(1)->update($aUpdate);
}
Db::commit();
return json_encode(['status' => 1,'msg' => 'success','data' => $aInsert]);
}
/**
* 获取Ai生成文章状态
* @param article_id 文章ID
*/
public function getAiArticleStatus(){
$aParam = $this->request->post();
//AI生成文章ID
$iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id'];
if(empty($iArticleId)){
return json_encode(['status' => 2,'msg' => 'Please select the article to be generated']);
}
//查询AI生成的文章内容
$aWhere = ['is_delete' => 2];
if(!empty($iArticleId)){
$aWhere['article_id'] = $iArticleId;
}
$aAiArticle = Db::name('ai_article')->field('is_generate')->where($aWhere)->find();
// 生成状态
$aMsg = [1 => 'The data has been generated, please proceed with the next steps',2 => 'AI content generation in progress',3 => 'AI content not generated'];
$iStatus = empty($aAiArticle['is_generate']) ? 3 : $aAiArticle['is_generate'];
$sMsg = empty($aMsg[$iStatus]) ? 'illegal request' : $aMsg[$iStatus];
return json_encode(['status' => 1,'msg' => $sMsg,'data' => ['is_generate' => $iStatus]]);
}
/**
* CURL 发送请求获取Token
* @param $appid AppID(小程序ID)
* @param $secret AppSecret(小程序密钥)
*/
private function getAccessToken() {
//Token缓存值
$sToken = Cache::get($this->sWechatAccessToken);
//判断缓存是否存在
if (!$sToken) { //不存在
//组装接口地址
$sUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
. $this->sAppID . "&secret=" . $this->sAppSecret;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $sUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout);
$result = curl_exec($curl);
//请求失败
if (curl_errno($curl)){
$this->sError = curl_errno($curl);
curl_close($curl);
return FALSE;
}
$result = json_decode($result, true);
if (!empty($result['access_token'])) {
$sToken = $result['access_token'];
Cache::set($this->sWechatAccessToken, $sToken, 7000); // 有效期7200秒
}
curl_close($curl);
}
return $sToken;
}
/**
* CURL 发送请求上传永久素材
* @param $sToken Token
* @param $sPath 图片地址
*/
public function uploadMaterial($sPath = '') {
$aParam = $this->request->post();
$sPath = empty($sPath) ? $aParam['path'] : $sPath;
// $sPath = ROOT_PATH.'static/img/'.$sPath;
// return json_encode(['status' => 1,'data' => ['media_id' => '1111111','url' => '22222']]);
//返回结果数组
$aResult = ['status' => 1,'msg' => '上传素材成功','data' => []];
$sPath = empty($sPath) ? $aParam['image_path']?? '' : $sPath;//文件地址
$sType = empty($aParam['type']) ? 'image' : $aParam['type'];//文件类型
// 验证文件有效性
if (!file_exists($sPath)) {
return json_encode(['status' => 2,'msg' => '素材不存在'.$sPath]);
}
if (!is_readable($sPath)) {
return json_encode(['status' => 3,'msg' => '素材不可读']);
}
if (filesize($sPath) > 10 * 1024 * 1024) {
return json_encode(['status' => 4,'msg' => '素材不能超过10MB']);
}
//获取Token
$sToken = $this->getAccessToken();
if (empty($sToken)) {
return json_encode(['status' => 5, 'msg' => '获取access_token失败']);
}
//CURL 请求接口
//文件参数
$data = [
'media' => new \CURLFile(
realpath($sPath),
mime_content_type($sPath), // 自动检测MIME类型
basename($sPath) // 上传后的文件名
), // 关键使用CURLFile对象
];
$sUrl = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={$sToken}&type={$sType}";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $sUrl);
curl_setopt($curl, CURLOPT_POST, true); //设置为POST方式
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE) ; // 获取数据返回
curl_setopt($curl, CURLOPT_PROXY,$this->proxy);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,false);
//执行
$response = curl_exec($curl);
//请求失败
if (curl_errno($curl)){
curl_close($curl);
return json_encode(['status' => 6,'msg' => "网络请求失败: " . curl_errno($curl)]);
}
curl_close($curl);//关闭请求
//获取返回结果
$response = json_decode($response, true);
if (!empty($response['errcode']) && $response['errcode'] != 0) {
return json_encode(['status' => 7,'msg' => "微信接口错误: [{$response['errcode']}] {$response['errmsg']}"]);
}
//插入数据库
if(empty($response['media_id'])){
return json_encode(['status' => 8,'msg' => "未获取到上传素材"]);
}
return json_encode(['status' => 1,'msg' => 'success','data' => $response]);
}
/**
* CURL 发送请求到 微信公众号
* @param $messages 内容
* @param $model 模型类型
*/
private function curlWechatApi($sUrl = '',$sJsonData = ''){
//发送CURL请求
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $sUrl);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $sJsonData);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($sJsonData)
]);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); // 关闭SSL验证生产环境建议开启
$response = curl_exec($curl);
//请求失败
if (curl_errno($curl)){
curl_close($curl);
return ['status' => 2,'msg' => "网络请求失败: " . curl_errno($curl)];
}
curl_close($curl);//关闭请求
// 数据处理
$response = json_decode($response, true);
if (!empty($response['errcode'])) {
return ['status' => 3, 'msg' => '接口请求异常'.$response['errmsg'] ?? $response['errcode']];
}
return ['status' => 1,'msg' => '接口请求成功','data' => $response];
}
/**
* CURL 添加文章到草稿箱
* @param $sToken Token
* @param $sPath 图片地址
*/
public function addDraft($aParam = []){
//返回结果数组
$aResult = ['status' => 1,'msg' => 'Upload draft box successfully','data' => []];
//文章ID
$iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id'];
//模版ID
$iTemplateId = empty($aParam['template_id']) ? '' : $aParam['template_id'];
//生成模版内容
$sContent = empty($aParam['template_content']) ? '' : $aParam['template_content'];
if(empty($iArticleId) || empty($iTemplateId) || empty($sContent)){
return json_encode(['status' => 2,'msg' => 'article_id OR template_content is empty']);
}
//查询文章是否存在
$aWhere = ['article_id' => $iArticleId,'is_delete' => 2];
$aAiArticle = Db::name('ai_article')->field('title_chinese as title,author,journal_id')->where($aWhere)->find();
if(empty($aAiArticle)){
return json_encode(['status' => 3, 'msg' => 'The article does not exist']);
}
//查询该模版是否推送到微信公众号
$aWhere['template_id'] = $iTemplateId;
$aWechatArticle = Db::name('ai_wechat_article')->where($aWhere)->find();
if(!empty($aWechatArticle)){
return json_encode(['status' => 4, 'msg' => 'Already uploaded to draft box']);
}
//查询文章封面
$aMaterial = Db::name('ai_article_material')->field('media_id as thumb_media_id')->where('article_id',$iArticleId)->find();
if(!empty($aMaterial)){
$aAiArticle += $aMaterial;
}
$aAiArticle['content'] = $sContent;
unset($aAiArticle['journal_id']);
//获取Token
$sToken = $this->getAccessToken();
if (empty($sToken)) {
return json_encode(['status' => 5, 'msg' => 'Failed to obtain access_token']);
}
//发送CURL请求
$sUrl = "https://api.weixin.qq.com/cgi-bin/draft/add?access_token={$sToken}";
//参数组装
$sJsonData = json_encode([
'articles' => [$aAiArticle]
], JSON_UNESCAPED_UNICODE);
$aCurlResult = $this->curlWechatApi($sUrl,$sJsonData);
if($aCurlResult['status'] != 1){
return json_encode($aCurlResult);
}
$response = empty($aCurlResult['data']) ? [] : $aCurlResult['data'];
//判断是否推送成功
if(empty($response['media_id'])){
return json_encode(['status' => 5,'msg' => "Unable to obtain the uploaded draft"]);
}
//判断文章类型
$article_type = empty($aParam['article_type']) ? 'news' : $aParam['article_type'];
if(!in_array($article_type, ['news','newspic'])){
return json_encode(['status' => 6,'msg' => "The article type does not match"]);
}
//是否打开评论0不打开(默认)1打开
$need_open_comment = empty($aParam['need_open_comment']) ? 1 : $aParam['need_open_comment'];
//是否粉丝才可评论0所有人可评论(默认)1粉丝才可评论
$only_fans_can_comment = empty($aParam['only_fans_can_comment']) ? 1 : $aParam['only_fans_can_comment'];
//插入文章表
$aParam = ['media_id' => $response['media_id'],'update_time' => time(),'template_id' => $iTemplateId,'template_content' => $aParam['template_content'],'article_id' => $iArticleId,'article_type' => $article_type,'need_open_comment' => $need_open_comment,'only_fans_can_comment' => $only_fans_can_comment,'template_id' => $iTemplateId,'create_time' => time()];
$result = Db::name('ai_wechat_article')->insert($aParam);
if($result === false){
return json_encode(['status' => 8,'msg' => "Article data insertion failed"]);
}
return json_encode($aResult);
}
/**
* CURL 获取草稿箱的文章
* @param $sToken Token
* @param media_id string 微信公众号media_id
*/
public function getDraft($sMediaId = ''){
//返回结果数组
$aResult = ['status' => 1,'msg' => 'Successfully obtained draft','data' => []];
//获取参数
$aParam = $this->request->post();
$sMediaId = empty($sMediaId) ? $aParam['media_id'] : $sMediaId;
if(empty($sMediaId)){
return json_encode(['status' => 2, 'msg' => 'Parameter: media_id cannot be empty']);
}
//查询关联文章信息
$aArticle = Db::name('ai_wechat_article')->field('media_id')->where(['media_id'=>$sMediaId])->find();
if(empty($aArticle)){
return json_encode(['status' => 3,'msg' => 'The article does not exist']);
}
//获取Token
$sToken = $this->getAccessToken();
if (empty($sToken)) {
return json_encode(['status' => 4, 'msg' => 'Failed to obtain access_token']);
}
//CURL请求
$sUrl = "https://api.weixin.qq.com/cgi-bin/draft/get?access_token={$sToken}";
//参数组装
$sJsonData = json_encode([
'media_id' => $aArticle['media_id']
], JSON_UNESCAPED_UNICODE);
//发送CURL请求
$aCurlResult = $this->curlWechatApi($sUrl,$sJsonData);
if($aCurlResult['status'] != 1){
return json_encode(['status' => 5,'msg' => 'Acquisition failed']);
}
$response = empty($aCurlResult['data']) ? [] : $aCurlResult['data'];
$aResult['data'] = $response['news_item'] ?? [];
return json_encode($aResult);
}
/**
* CURL 发布草稿箱的文章
* @param $sToken Token
* @param article_id int 文章ID
*/
public function publishDraft($sMediaId = ''){
//返回结果数组
$aResult = ['status' => 1,'msg' => 'Draft box article successfully published','data' => []];
//获取参数
$aParam = $this->request->post();
$sMediaId = empty($sMediaId) ? $aParam['media_id'] : $sMediaId;
if(empty($sMediaId)){//为空
//必填参数验证
//文章ID
$iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id'];
//模版ID
$iTemplateId = empty($aParam['template_id']) ? '' : $aParam['template_id'];
if(empty($iArticleId) || empty($iTemplateId)){
return json_encode(['status' => 2,'msg' => 'Please select the article or article template to publish']);
}
//获取文章信息
$aAiContent = json_decode($this->getAiArticle($iArticleId,1),true);
$aAiContent = empty($aAiContent['data']) ? [] : $aAiContent['data'];
$aAiArticle = empty($aAiContent['ai_article']) ? [] : $aAiContent['ai_article'];
//判断是否生成AI内容
if(empty($aAiArticle)){
return json_encode(['status' => 3, 'msg' => 'The article content of WeChat official account has not been generated']);
}
//查询该模版是否推送到微信公众号
$aWhere['article_id'] = $iArticleId;
$aWhere['template_id'] = $iTemplateId;
}
if(!empty($sMediaId)){
$aWhere['media_id'] = $sMediaId;
}
$aWechatArticle = Db::name('ai_wechat_article')->field('id,is_publish,media_id,publish_status')->where($aWhere)->find();
if(empty($aWechatArticle)){
return json_encode(['status' => 4, 'msg' => 'The article was not found in the draft box of WeChat official account']);
}
$iId = empty($aWechatArticle['id']) ? 0 : $aWechatArticle['id'];
//判断是否发布
if($aWechatArticle['publish_status'] != '-1'){
return json_encode(['status' => 5, 'msg' => 'The article has been published, please confirm']);
}
//判断微信公众号media_id 是否为空
$sMediaId = empty($aWechatArticle['media_id']) ? '' : $aWechatArticle['media_id'];
if(empty($sMediaId)){
return json_encode(['status' => 5,'msg' => 'The article has not been pushed to the draft box of WeChat official account, please confirm'],true);
}
//获取Token
$sToken = $this->getAccessToken();
if (empty($sToken)) {
return json_encode(['status' => 6, 'msg' => '获取access_token失败']);
}
//验证公众号是否存在该文章
$aInfo = json_decode($this->getDraft($sMediaId),true);
if($aInfo['status'] != 1){
return json_encode($aInfo);
}
// //CURL请求
// $sUrl = "https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token={$sToken}";
// //参数组装
// $sJsonData = json_encode([
// 'media_id' => $sMediaId
// ], JSON_UNESCAPED_UNICODE);
// //发送CURL请求
// $aCurlResult = $this->curlWechatApi($sUrl,$sJsonData);
// if($aCurlResult['status'] != 1){
// return $aCurlResult;
// }
// $response = empty($aCurlResult['data']) ? [] : $aCurlResult['data'];
// //判断是否推送成功
// if(empty($response['publish_id'])){
// return json_encode(['status' => 9,'msg' => "未获取到发布草稿的publish_id"]);
// }
$response['publish_id'] = '100000001';
//更新文章表publish_id
$aUpdate = ['update_time' => time(),'is_publish' => 1,'publish_id' => $response['publish_id'],'publish_status' => 1];
$result = Db::name('ai_wechat_article')->where('id',$iId)->limit(1)->update($aUpdate);
if($result === false){
return json_encode(['status' => 9,'msg' => "Failed to update the status of the published article"]);
}
return json_encode($aResult);
}
/**
* CURL 查询文章的发布状态
* @param $sToken Token
* @param article_id array 文章ID
*/
public function freePublish(){
//返回结果数组
$aResult = ['status' => 1,'msg' => 'Successfully synchronized the publishing status of the article','data' => []];
//获取参数
$aParam = $this->request->post();
$aWhere = ['is_publish' => 1,'publish_id' => ['<>',''],'publish_status' => 1,'is_delete' => 2];
if(!empty($aParam['article_id'])){
$aWhere['id'] = $aParam['article_id'];
}
//查询文章发布ID
$aArticlePublishId = Db::name('ai_wechat_article')->where($aWhere)->column('publish_id');
if(empty($aArticlePublishId)){
return json_encode(['status' => 2,'msg' => 'No articles requiring synchronization status were found'],true);
}
//循环查询
$aInsert = $aUpdate = [];
foreach ($aArticlePublishId as $key => $value) {
if(empty($value)){
continue;
}
$aResult = json_decode($this->_freePublish(100000001),true);
if($aResult['status'] != 1){
continue;
}
$aData = empty($aResult['data']) ? [] : $aResult['data'];
if(empty($aData)){
continue;
}
$aInsert[] = $aData;
$aUpdate[$aData['publish_status']][] = $value;
}
//插入日志表
if(!empty($aInsert)){
$result = Db::name('wechat_article_publish_log')->insertAll($aInsert);
}
//更新文章表的发布状态
if(!empty($aUpdate)){
Db::startTrans();
foreach ($aUpdate as $key => $value) {
if(empty($value)){
continue;
}
$result = Db::name('ai_wechat_article')->whereIn('publish_id',$value)->limit(count($value))->update(['publish_status' => $key,'update_time' => time()]);
}
Db::commit();
}
return json_encode($aResult);
}
private function _freePublish($sPublishId = '100000001'){
//获取参数
// $aParam = $this->request->post();
// $sPublishId = empty($sPublishId) ? $aParam['publish_id']?? '' : $sPublishId;//文件地址
// if(empty($sPublishId)){
// return json_encode(['status' => 2, 'msg' => '请选择要查询的文章发布ID']);
// }
// //获取Token
// $sToken = $this->getAccessToken();
// if (empty($sToken)) {
// return json_encode(['status' => 3, 'msg' => '获取access_token失败']);
// }
// //CURL请求
// $sUrl = "https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token={$sToken}";
// //参数组装
// $sJsonData = json_encode([
// 'publish_id' => $sPublishId
// ], JSON_UNESCAPED_UNICODE);
// //发送CURL请求
// $aCurlResult = $this->curlWechatApi($sUrl,$sJsonData);
// if($aCurlResult['status'] != 1){
// return $aCurlResult;
// }
// $response = empty($aCurlResult['data']) ? [] : $aCurlResult['data'];
$response = ['publish_id' => '1000001','publish_status' => 2,'article_id'=> '','article_detail','fail_idx' => [1,2]];
//log日志需要参数
$aField = ['publish_id','publish_status' ,'article_id' ,'article_detail' ,'fail_idx' ,'create_time'];
$aInsert = [];
foreach ($aField as $value) {
if($value == 'create_time'){
$aInsert[$value] = time();
continue;
}
$aInsert[$value] = empty($response[$value]) ? ' ' : $response[$value];
if(is_array($aInsert[$value])){
$aInsert[$value] = json_encode($aInsert[$value]);
}
}
$aResult['status'] = 1;
$aResult['data'] = $aInsert;
return json_encode($aResult);
}
// /**
// * CURL 获取微信公众号信息
// * @param $sToken Token
// * @param article_id array 文章ID
// */
// public function getWechatAccountInfo(){
// //获取Token
// $sToken = $this->getAccessToken();
// if (empty($sToken)) {
// return json_encode(['status' => 5, 'msg' => 'Failed to obtain access_token']);
// }
// $sUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=".$sToken.'&openid=OPENID&lang=zh_CN'
// $ch = curl_init();
// curl_setopt($ch, CURLOPT_URL, $sUrl);
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// $response = curl_exec($ch);
// echo '<pre>';var_dump($response);exit;
// curl_close($ch);
// return json_decode($response, true);
// }
}