diff --git a/application/common/Aiarticle.php b/application/common/Aiarticle.php new file mode 100644 index 0000000..85be5e1 --- /dev/null +++ b/application/common/Aiarticle.php @@ -0,0 +1,2271 @@ + ['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'] . '. ' . choiseJabbr($aArticle['article_id'], $jabbr) . '. ' . $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 '
';var_dump($response);exit;
+// curl_close($ch);
+// return json_decode($response, true);
+// }
+}
diff --git a/application/common/Material.php b/application/common/Material.php
new file mode 100644
index 0000000..7e1392e
--- /dev/null
+++ b/application/common/Material.php
@@ -0,0 +1,460 @@
+ 'Cn8zlXvVB5DwjcA9h40z9fprHDoc3Jqv97SwrInpmyYiilkeRdKvpD63cWqTYHfz','url' => 'http://mmbiz.qpic.cn/mmbiz_jpg/QHFVW13lONaQJxK9QbHU9CtrvTS2ModZnUyeAvuVN67t8XP85DxVJwDJf2YxCTalrsr17jS080xM6xQv5yGiaEQ/0?wx_fmt=jpeg'];//默认头像
+
+ //文章图片icon地址
+ protected $sArticleIcon = '/public/articleicon/';
+ //期刊图片icon地址
+ protected $sJournalIcon = '/public/journalicon/';
+ //作者头像地址
+ protected $sUserIcon = '/public/usericon/';
+ //期刊编辑二维码地址
+ protected $sJournalEditorQrcode = '/public/journaleditorqrcode/';
+ //二维码地址
+ protected $sQrCodeUrl = 'public/qrcode/';
+ //官网地址
+ protected $sJournalUsx = 'https://www.tmrjournals.com';
+ //默认头像
+ protected $sDefaultUserIcon = '/static/img/userImg.f3d9bc3b.jpg';
+
+ public function __construct(\think\Request $request = null) {
+
+ }
+
+ /**
+ * @title 生成期刊二维码
+ * @param aJournal 期刊信息
+ */
+ public function createJournalQrCode($aJournal = []){
+
+ $iJournalId = empty($aJournal['journal_id']) ? 0 : $aJournal['journal_id'];
+
+ //生成图片地址
+ $sImagePath = 'journal/'.$iJournalId.'.jpg';
+ $sQrCodeUrl = ROOT_PATH.$this->sQrCodeUrl.$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);
+ }
+
+ //插入字段
+ $aInsertParam = ['journal_id' => $iJournalId,'qrcode_url' => $sImagePath,'create_time' => time(),'update_time' => time()];
+
+ $sStartSql = 'INSERT INTO t_ai_journal_qrcode ('.implode(',', array_keys($aInsertParam)).') VALUES (';
+ $sEndSql = ') ON DUPLICATE KEY UPDATE update_time = VALUES(update_time)';
+
+ $sSql = '';
+ foreach ($aInsertParam as $key => $value) {
+ $sSql .= '"'.$value.'",';
+ }
+ $sSql = $sStartSql.trim($sSql,',').$sEndSql;
+ $result = Db::execute($sSql);
+ return $aInsertParam;
+ }
+
+ /**
+ * @title 生成文章二维码
+ * @param aArticle 文章信息
+ */
+ public function createArticleQrCode($aArticle = []){
+
+ $iArticleId = empty($aArticle['article_id']) ? 0 : $aArticle['article_id'];
+
+ //创建二维码
+ //生成图片地址
+ $sImagePath = 'article/'.$iArticleId.'.jpg';
+ $sQrCodeUrl = ROOT_PATH.$this->sQrCodeUrl.$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);
+ }
+
+ //插入字段
+ $aInsertParam = ['article_id' => $iArticleId,'qrcode_url' => $sImagePath,'create_time' => time(),'update_time' => time()];
+
+ $sStartSql = 'INSERT INTO t_ai_article_qrcode ('.implode(',', array_keys($aInsertParam)).') VALUES (';
+ $sEndSql = ') ON DUPLICATE KEY UPDATE update_time = VALUES(update_time)';
+
+ $sSql = '';
+ foreach ($aInsertParam as $key => $value) {
+ $sSql .= '"'.$value.'",';
+ }
+ $sSql = $sStartSql.trim($sSql,',').$sEndSql;
+ $result = Db::execute($sSql);
+ return $aInsertParam;
+ }
+
+
+ /**
+ * @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.$this->sQrCodeUrl.$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
+ * @param media_id 微信公众号素材media_id
+ * @param media_url 微信公众号素材地址
+ * @param sType select 查询|add 新增
+ * @param $sPath 图片地址
+ */
+ public 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.$this->sQrCodeUrl.$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']);
+ }
+ }
+
+
+ //调用微信新增素材接口上传
+ $oWechat = new Wechat;
+ $sWechatAppId = empty($aParam['wechat_app_id']) ? '' : $aParam['wechat_app_id'];
+ $sWechatAppSecret = empty($aParam['wechat_app_secret']) ? '' : $aParam['wechat_app_secret'];
+ $aImageParam = ['image_url' => $sImagePath,'wechat_app_id' => $sWechatAppId,'wechat_app_secret' => $sWechatAppSecret];
+ $aUploadResult = json_decode($oWechat->uploadMaterial($aImageParam),true);
+ $sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
+ $aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
+ if(empty($aData['url'])){
+ return json_encode(['status' => 4,'msg' => $sMsg]);
+ }
+
+ //处理入库数据
+ $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,'update_time' => $iTime];
+
+ $sStartSql = 'INSERT INTO t_ai_article_material ('.implode(',', array_keys($aInsert)).') VALUES (';
+ $sEndSql = ') ON DUPLICATE KEY UPDATE update_time = VALUES(update_time),media_id = VALUES(media_id),media_url = VALUES(media_url)';
+
+ $sSql = '';
+ foreach ($aInsert as $key => $value) {
+ $sSql .= '"'.$value.'",';
+ }
+ $sSql = $sStartSql.trim($sSql,',').$sEndSql;
+ $result = Db::execute($sSql);
+ return json_encode(['status' => 1,'msg' => 'success','data' => $aInsert]);
+ }
+ /**
+ * 添加期刊素材
+ */
+ public 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.$this->sQrCodeUrl.$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']);
+ }
+ }
+
+ //调用微信新增素材接口上传
+ $oWechat = new Wechat;
+ $sWechatAppId = empty($aParam['wechat_app_id']) ? '' : $aParam['wechat_app_id'];
+ $sWechatAppSecret = empty($aParam['wechat_app_secret']) ? '' : $aParam['wechat_app_secret'];
+ $aImageParam = ['image_url' => $sImagePath,'wechat_app_id' => $sWechatAppId,'wechat_app_secret' => $sWechatAppSecret];
+ $aUploadResult = json_decode($oWechat->uploadMaterial($aImageParam),true);
+ $sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
+ $aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
+ if(empty($aData['url'])){
+ return json_encode(['status' => 4,'msg' => $sMsg]);
+ }
+
+ //处理入库数据
+ $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,'journal_id' => $iJournalId,'media_url' => $sMediaUrl,'update_time' => $iTime];
+
+ $sStartSql = 'INSERT INTO t_ai_journal_material ('.implode(',', array_keys($aInsert)).') VALUES (';
+ $sEndSql = ') ON DUPLICATE KEY UPDATE update_time = VALUES(update_time),media_id = VALUES(media_id),media_url = VALUES(media_url)';
+
+ $sSql = '';
+ foreach ($aInsert as $key => $value) {
+ $sSql .= '"'.$value.'",';
+ }
+ $sSql = $sStartSql.trim($sSql,',').$sEndSql;
+ $result = Db::execute($sSql);
+ return json_encode(['status' => 1,'msg' => 'success','data' => $aInsert]);
+ }
+ /**
+ * 更新期刊二维码关联微信公众号素材
+ */
+ public 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']);
+ }
+ //处理图片地址
+ $sImagePath = ROOT_PATH.$this->sQrCodeUrl.$aMaterial['qrcode_url'];
+
+ //调用微信新增素材接口上传
+ $oWechat = new Wechat;
+ $sWechatAppId = empty($aParam['wechat_app_id']) ? '' : $aParam['wechat_app_id'];
+ $sWechatAppSecret = empty($aParam['wechat_app_secret']) ? '' : $aParam['wechat_app_secret'];
+ $aImageParam = ['image_url' => $sImagePath,'wechat_app_id' => $sWechatAppId,'wechat_app_secret' => $sWechatAppSecret];
+ $aUploadResult = json_decode($oWechat->uploadMaterial($aImageParam),true);
+ $sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
+ $aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
+ if(empty($aData['url'])){
+ return json_encode(['status' => 4,'msg' => $sMsg]);
+ }
+
+ $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]);
+ }
+
+ /**
+ * 更新文章二维码关联微信公众号素材
+ */
+ public 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']);
+ }
+
+ //处理图片地址
+ $sImagePath = ROOT_PATH.$this->sQrCodeUrl.$aMaterial['qrcode_url'];
+
+ //调用微信新增素材接口上传
+ $oWechat = new Wechat;
+ $sWechatAppId = empty($aParam['wechat_app_id']) ? '' : $aParam['wechat_app_id'];
+ $sWechatAppSecret = empty($aParam['wechat_app_secret']) ? '' : $aParam['wechat_app_secret'];
+ $aImageParam = ['image_url' => $sImagePath,'wechat_app_id' => $sWechatAppId,'wechat_app_secret' => $sWechatAppSecret];
+ $aUploadResult = json_decode($oWechat->uploadMaterial($aImageParam),true);
+ $sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
+ $aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
+ if(empty($aData['url'])){
+ return json_encode(['status' => 5,'msg' => $sMsg]);
+ }
+
+ //更新
+ $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]);
+ }
+
+ /**
+ * 更新通讯作者关联微信公众号素材
+ */
+ public 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']);
+ }
+
+ //处理图片地址
+ $sImagePath = ROOT_PATH.$this->sUserIcon.trim($sIcon,'/');
+
+ if(trim($sIcon) != $this->sDefaultUserIcon){//非默认头像
+ //调用微信新增素材接口上传
+ $oWechat = new Wechat;
+ $sWechatAppId = empty($aParam['wechat_app_id']) ? '' : $aParam['wechat_app_id'];
+ $sWechatAppSecret = empty($aParam['wechat_app_secret']) ? '' : $aParam['wechat_app_secret'];
+ $aImageParam = ['image_url' => $sImagePath,'wechat_app_id' => $sWechatAppId,'wechat_app_secret' => $sWechatAppSecret];
+ $aUploadResult = json_decode($oWechat->uploadMaterial($aImageParam),true);
+ $sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
+ $aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
+ if(empty($aData['url'])){
+ return json_encode(['status' => 5,'msg' => $sMsg]);
+ }
+ }
+ if(trim($sIcon) == $this->sDefaultUserIcon){//默认头像
+ $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'],'update_time' => $iTime];
+
+ $sStartSql = 'INSERT INTO t_ai_author_material ('.implode(',', array_keys($aInsert)).') VALUES (';
+ $sEndSql = ') ON DUPLICATE KEY UPDATE update_time = VALUES(update_time),media_id = VALUES(media_id),media_url = VALUES(media_url)';
+
+ $sSql = '';
+ foreach ($aInsert as $key => $value) {
+ $sSql .= '"'.$value.'",';
+ }
+ $sSql = $sStartSql.trim($sSql,',').$sEndSql;
+ $result = Db::execute($sSql);
+ return json_encode(['status' => 1,'msg' => 'success','data' => $aInsert]);
+ }
+
+ /**
+ * 更新通讯作者关联微信公众号素材
+ */
+ public function updateJournalEditorQrcode($aParam = []){
+
+ $iJournalId = empty($aParam['journal_id']) ? '' : $aParam['journal_id'];
+ //文章图片
+ $sIcon = empty($aParam['editor_qrcode']) ? '' : $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.$this->sJournalEditorQrcode.trim($sIcon,'/');
+
+ //调用微信新增素材接口上传
+ $oWechat = new Wechat;
+ $sWechatAppId = empty($aParam['wechat_app_id']) ? '' : $aParam['wechat_app_id'];
+ $sWechatAppSecret = empty($aParam['wechat_app_secret']) ? '' : $aParam['wechat_app_secret'];
+ $aImageParam = ['image_url' => $sImagePath,'wechat_app_id' => $sWechatAppId,'wechat_app_secret' => $sWechatAppSecret];
+ $aUploadResult = json_decode($oWechat->uploadMaterial($aImageParam),true);
+ $sMsg = empty($aUploadResult['msg']) ? 'Failed to upload materials' : $aUploadResult['msg'];
+ $aData = empty($aUploadResult['data']) ? [] : $aUploadResult['data'];
+ if(empty($aData['url'])){
+ return json_encode(['status' => 5,'msg' => $sMsg]);
+ }
+
+ //处理入库数据
+ $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,'journal_id' => $iJournalId,'media_url' => $sMediaUrl,'create_time' => $iTime,'update_time' => $iTime];
+
+ $sStartSql = 'INSERT INTO t_ai_journal_editor_material ('.implode(',', array_keys($aInsert)).') VALUES (';
+ $sEndSql = ') ON DUPLICATE KEY UPDATE update_time = VALUES(update_time),media_id = VALUES(media_id),media_url = VALUES(media_url)';
+
+ $sSql = '';
+ foreach ($aInsert as $key => $value) {
+ $sSql .= '"'.$value.'",';
+ }
+ $sSql = $sStartSql.trim($sSql,',').$sEndSql;
+ $result = Db::execute($sSql);
+ return json_encode(['status' => 1,'msg' => 'success','data' => $aInsert]);
+ }
+}
diff --git a/application/common/Wechat.php b/application/common/Wechat.php
new file mode 100644
index 0000000..c415f60
--- /dev/null
+++ b/application/common/Wechat.php
@@ -0,0 +1,496 @@
+sWechatAccessToken.'_'.$this->sAppID);
+ //判断缓存是否存在
+ 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.'_'.$this->sAppID, $sToken, 7000); // 有效期7200秒
+ }
+ curl_close($curl);
+ }
+ return $sToken;
+ }
+
+ /**
+ * CURL 发送请求上传永久素材
+ * @param $sToken Token
+ * @param $sPath 图片地址
+ */
+ public function uploadMaterial($aParam = []) {
+ $aParam = empty($aParam) ? $this->request->post() : $aParam;
+
+ //图片地址
+ $sPath = empty($aParam['image_url']) ? '' : $aParam['image_url'];
+ if(empty($sPath)){
+ return json_encode(['status' => 2,'msg' => 'Please choose to upload materials']);
+ }
+
+ // 获取微信公众号APPID和APPKEY
+ $this->sAppID = empty($aParam['wechat_app_id']) ? '' : $aParam['wechat_app_id'];
+ $this->sAppSecret = empty($aParam['wechat_app_secret']) ? '' : $aParam['wechat_app_secret'];
+ if(empty($this->sAppID) || empty($this->sAppSecret)){
+ return json_encode(['status' => 2,'msg' => 'Please configure the AppID and AppSecret']);
+ }
+
+ $sType = empty($aParam['type']) ? 'image' : $aParam['type'];//文件类型
+
+ // 验证文件有效性
+ if (!file_exists($sPath)) {
+ return json_encode(['status' => 3,'msg' => 'The material does not exist'.$sPath]);
+ }
+ if (!is_readable($sPath)) {
+ return json_encode(['status' => 3,'msg' => 'The material is unreadable']);
+ }
+ if (filesize($sPath) > 10 * 1024 * 1024) {
+ return json_encode(['status' => 4,'msg' => 'The material cannot exceed 10MB']);
+ }
+
+ //获取Token
+ $sToken = $this->getAccessToken();
+ if (empty($sToken)) {
+ return json_encode(['status' => 5, 'msg' => 'Failed to obtain 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' => "Network request failed: " . curl_errno($curl)]);
+ }
+ curl_close($curl);//关闭请求
+
+ //获取返回结果
+ $response = json_decode($response, true);
+ if (!empty($response['errcode']) && $response['errcode'] != 0) {
+ return json_encode(['status' => 7,'msg' => "WeChat interface error: [{$response['errcode']}] {$response['errmsg']}"]);
+ }
+
+ //插入数据库
+ if(empty($response['media_id'])){
+ return json_encode(['status' => 8,'msg' => "Unable to obtain uploaded materials"]);
+ }
+ 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' => "Network request failed: " . curl_errno($curl)];
+ }
+ curl_close($curl);//关闭请求
+
+ // 数据处理
+ $response = json_decode($response, true);
+ if (!empty($response['errcode'])) {
+ return ['status' => 3, 'msg' => 'WeChat interface error:'.$response['errmsg'] ?? $response['errcode']];
+ }
+
+ return ['status' => 1,'msg' => 'success','data' => $response];
+ }
+
+ /**
+ * CURL 添加文章到草稿箱
+ * @param $sToken Token
+ * @param $sPath 图片地址
+ */
+ public function addDraft($aParam = []){
+
+ $aParam = empty($aParam) ? $this->request->post() : $aParam;
+
+ //文章ID
+ $iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id'];
+ if(empty($iArticleId)){
+ return json_encode(['status' => 2,'msg' => 'article_id is empty']);
+ }
+ //模版ID
+ $iTemplateId = empty($aParam['template_id']) ? '' : $aParam['template_id'];
+ if(empty($iTemplateId)){
+ return json_encode(['status' => 2,'msg' => 'Template ID is empty']);
+ }
+ //发布公众号ID
+ $sWechatId = empty($aParam['wechat_id']) ? 0 : $aParam['wechat_id'];
+ if(empty($sWechatId)){
+ return json_encode(['status' => 2,'msg' => 'Please select the official account to be pushed']);
+ }
+ //生成模版内容
+ $sContent = empty($aParam['content']) ? '' : $aParam['content'];
+ if(empty($sContent)){
+ return json_encode(['status' => 2,'msg' => 'The published content is empty']);
+ }
+
+ // 获取微信公众号APPID和APPKEY
+ $this->sAppID = empty($aParam['wechat_app_id']) ? '' : $aParam['wechat_app_id'];
+ $this->sAppSecret = empty($aParam['wechat_app_secret']) ? '' : $aParam['wechat_app_secret'];
+ if(empty($this->sAppID) || empty($this->sAppSecret)){
+ return json_encode(['status' => 2,'msg' => 'Please configure the AppID and AppSecret']);
+ }
+
+ //获取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' => [$aParam]
+ ], 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' => $sContent,'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(),'wechat_id' => $sWechatId];
+ $result = Db::name('ai_wechat_article')->insert($aParam);
+ if($result === false){
+ return json_encode(['status' => 8,'msg' => "Article data insertion failed"]);
+ }
+ return json_encode(['status' => 1,'msg' => 'Upload draft box successfully','data' => []]);
+ }
+
+ /**
+ * 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' => 'Failed to obtain 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' => 'Failed to obtain 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);
+ }
+}