2272 lines
96 KiB
PHP
2272 lines
96 KiB
PHP
<?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);
|
||
// }
|
||
}
|