sFirst; //查询期刊信息 $iJournalId = empty($aProductionArticle['journal_id']) ? 0 : $aProductionArticle['journal_id']; if(!empty($iJournalId)){ $aWhere = ['journal_id' => $iJournalId,'state' => 0]; $aJournal = Db::name('journal')->where($aWhere)->find(); if(!empty($aJournal)){ //获取编辑信息 $aWhere = ['user_id' => $aJournal['editor_id'],'state' => 0]; $aUser = Db::name('user')->field('realname')->where($aWhere)->find(); } } //子刊信息 $iJournalStageId = empty($aProductionArticle['journal_stage_id']) ? 0 : $aProductionArticle['journal_stage_id']; if(!empty($iJournalStageId)){ $aJournalStage = $this->getJournalStage(['journal_stage_id' => $iJournalStageId]); $aJournalStage = empty($aJournalStage['data']) ? [] : $aJournalStage['data']; } //期刊简写 $sAbbr = empty($aJournal['abbr']) ? $this->sAbbr : $aJournal['abbr']; $sAbbr = strtolower($sAbbr); $sJournalTitle = empty($aJournal['title']) ? '' : $aJournal['title']; //年 $iYear = empty($aJournalStage['stage_year']) ? date('Y') : $aJournalStage['stage_year']; //卷 $iVolume = empty($aJournalStage['stage_vol']) ? 0 : $aJournalStage['stage_vol']; //期 $iPeriod = empty($aJournalStage['stage_no']) ? 0 : $aJournalStage['stage_no']; //页 $sPage = empty($aJournalStage['stage_page']) ? '' : $aJournalStage['stage_page']; //期刊web $sWebsite = empty($aJournal['website']) ? $this->sWebsite : $aJournal['website']; $aSearch = ['{{journal_abbr}}' => $sAbbr,'{{stage_year}}' => $iYear,'{{stage_vol}}' => $iVolume,'{{stage_no}}' => $iPeriod,'{{stage_page}}' => $sPage,'{{website}}' => $sWebsite,'{{journal_title}}' => $sJournalTitle]; //获取DOI $aSearch['{{doi}}'] = empty($aProductionArticle['doi']) ? '' : $aProductionArticle['doi']; //获取作者信息 $aAuthoInfo = $this->dealAuthor(['p_article_id' => $aProductionArticle['p_article_id']]); $aSearch['{{author_info}}'] = empty($aAuthoInfo['author']) ? '' : $aAuthoInfo['author']; //通讯作者信息 $aSearch['{{correspondence_info}}'] = empty($aAuthoInfo['correspondence']) ? '' : '\Correspondence{'.$aAuthoInfo['correspondence'].'}'; //文章基本信息处理 //标题 $sTitle = empty($aProductionArticle['title']) ? '' : $this->dealContent($aProductionArticle['title']); if(!empty($sTitle)){ if(!empty($aProductionArticle['ltai'])){ $aLtai = explode(',', $aProductionArticle['ltai']); foreach ($aLtai as $key => $value) { if(empty($value)){ continue; } $sTitle = str_replace($value, '\textit{'.$value.'}', $sTitle); } } } $aSearch['{{article_title}}'] = $sTitle; //author_contribution $aSearch['{{author_contribution}}'] = empty($aProductionArticle['author_contribution']) ? '' : '\authorcontributions{'.$this->dealContent($aProductionArticle['author_contribution']).'}'; //acknowledgment $aSearch['{{article_acknowledgment}}'] = empty($aProductionArticle['acknowledgment']) ? '' : '\Acknowledgments{'.$this->dealContent($aProductionArticle['acknowledgment']).'}'; //abbreviation $aSearch['{{article_abbreviation}}'] = empty($aProductionArticle['abbreviation']) ? '' : '\Abbreviations{'.$this->dealContent($aProductionArticle['abbreviation']).'}'; //文章引用信息 $sCite = $this->getArticleCite($aProductionArticle,$aJournal,$aJournalStage); $aSearch['{{article_cite}}'] = empty($sCite) ? '' : '\Citation{'.$sCite.'}'; //获取文章时间 $aTime = $this->getArticleTime(['article_id' => $aProductionArticle['article_id']]); $aTime = empty($aTime['data']) ? [] : $aTime['data']; $aSearch['{{received_date}}'] = empty($aTime['received_date']) ? '' : $aTime['received_date']; $aSearch['{{revision_date}}'] = empty($aTime['revision_date']) ? '' : $aTime['revision_date']; $aSearch['{{accepted_date}}'] = empty($aTime['accepted_date']) ? '' : $aTime['accepted_date']; $aSearch['{{pub_date}}'] = empty($aProductionArticle['pub_date']) ? '' : $aProductionArticle['pub_date']; //获取编辑信息 $aSearch['{{executive_editor}}'] = empty($aUser['realname']) ? '' : '\Executiveeditor{'.$this->dealContent($aUser['realname']).'}'; //摘要替换 $sAbstract = empty($aProductionArticle['abstract']) ? '' : $this->dealContent($aProductionArticle['abstract']); if(!empty($sAbstract)){ $aRelace = ['Background:' => '\textcolor[HTML]{0070C0}{\textbf{Background:}}','Methods:' => '\textcolor[HTML]{0070C0}{\textbf{Methods:}}','Results:' => '\textcolor[HTML]{0070C0}{\textbf{Results:}}','Conclusion:' => '\textcolor[HTML]{0070C0}{\textbf{Conclusion:}}']; $sAbstract = str_replace(array_keys($aRelace), array_values($aRelace), $sAbstract); $sAbstract = '\tmrabstract{'.$sAbstract.'}'; } $aSearch['{{abstract}}'] = $sAbstract; //关键词 $sKeywords = empty($aProductionArticle['keywords']) ? '' : '\keywords{'.$this->dealContent($aProductionArticle['keywords']).'}'; $aSearch['{{keywords}}'] = $sKeywords; //文章图片地址 $sIcon = empty($aProductionArticle['icon']) ? '' : $aProductionArticle['icon']; if(!empty($sIcon)){ // $sIconUrl = rtrim(ROOT_PATH).$this->sArticleIcon.'/'.$sIcon; // if(file_exists($sIconUrl)){ // $sIcon = '\KeywordImage{'.$sIconUrl.'}'; // }else{ // $sIcon = ''; // } //下载图片 $sImagePath = trim($this->sSubmissionUrl,'/').$this->sArticleIcon.'/'.$sIcon; $aImageInfo = $this->getImage($sImagePath,$aProductionArticle['p_article_id']); if(!empty($aImageInfo['data'])){ $sIcon = '\KeywordImage{'.$aImageInfo['data'].'}'; }else{ $sIcon = ''; } } $aSearch['{{article_icon}}'] = $sIcon; $aSearch['{{keywords}}'] = $sKeywords; $aSearch['{{CLSFILEURL}}'] = ROOT_PATH.'public/latex/cls'; //模版内容替换 $sTemplateInfo = str_replace(array_keys($aSearch), array_values($aSearch), $sTemplateInfo); //返回内容 return ['status' => 1,'msg' => 'success','data' => $sTemplateInfo]; } /** * 生成初稿-主内容 * @param article_id 文章ID */ public function buildMain($aProductionArticle = []){ //获取模版 $sTemplateInfo = $this->sMain; //数据替换 $aSearch = ['{{tmr_highlight}}' => '','{{article_main}}' => '']; $sHighlight = ''; if($aProductionArticle['journal_id'] == 1){//tmr独有 $tradition_tag = empty($aProductionArticle['tradition_tag']) ? '' : strtolower( $aProductionArticle['tradition_tag']); $tradition = empty($aProductionArticle['tradition']) ? '' : $this->dealContent($aProductionArticle['tradition']); $pattern = '/]*>(.*?)<\/em>/is'; $replacement = '\\emph{$1}'; // $tradition = preg_replace($pattern, $replacement, $tradition); if(in_array($tradition_tag, ['highlight','highlights']) && !empty($tradition)){ $sHighlight .= '\highlightitem{Highlights}{'.$tradition.'}'."\n"; } $mhoo = empty($aProductionArticle['mhoo']) ? '' : $this->dealContent( $aProductionArticle['mhoo']); $mhoo = preg_replace($pattern, $replacement, $mhoo); if(!empty($mhoo)){ $sHighlight .= '\highlightitem{Medical history of objective}{'.$mhoo.'}'."\n"; } } $aSearch['{{tmr_highlight}}'] = empty($sHighlight) ? '' : '\begin{highlight}'."\n".$sHighlight."\n".'\end{highlight}'."\n"; //查询正文信息 // $aProductionArticle['article_id'] = 4477; $aWhere = ['article_id' => $aProductionArticle['article_id'],'state' => 0]; $aArticleMain = Db::name('article_main')->field('am_id,article_id,type,content,ami_id,amt_id,is_h1,is_h2,is_h3,sort')->where($aWhere)->order('sort')->select(); if(!empty($aArticleMain)){ //查询图片 $aAmiId = array_unique(array_column($aArticleMain, 'ami_id')); $aWhere = ['ami_id' => ['in',$aAmiId],'state' => 0]; $aArticleMainImage = Db::name('article_main_image')->field('ami_id,url,note')->where($aWhere)->select(); $aArticleMainImage = empty($aArticleMainImage) ? [] : array_column($aArticleMainImage, null,'ami_id'); //查询表格 $aAmtId = array_unique(array_column($aArticleMain, 'amt_id')); $aWhere = ['amt_id' => ['in',$aAmtId],'state' => 0]; $aArticleMainTable = Db::name('article_main_table')->field('amt_id,type,table_data,url,title,note')->where($aWhere)->select(); $aArticleMainTable = empty($aArticleMainTable) ? [] : array_column($aArticleMainTable, null,'amt_id'); //获取图片模版 $sImageTempalte = $this->sImageTempalte; //数据处理 $iStart = 0; $sMain = ''; $oLatexTable = new LaTeXTable; foreach ($aArticleMain as $key => $value) { if(empty($iStart)){ if($value['is_h1'] == 0){ continue; }else{ $iStart = $value['am_id']; } } if($value['am_id'] >= $iStart){ if($value['is_h1'] == 1){ if(empty($value['content'])){ continue; } $sMain .= '\section{'.$this->dealContent($value['content']).'}'."\n"; } if($value['is_h2'] == 1){ if(empty($value['content'])){ continue; } $sMain .= '\subsection{'.$this->dealContent($value['content']).'}'."\n"; } if($value['is_h3'] == 1){ if(empty($value['content'])){ continue; } $sMain .= '\subsubsection{'.$this->dealContent($value['content']).'}'."\n"; } if($value['is_h1'] == 0 && $value['is_h2'] == 0 && $value['is_h3'] == 0){ if($value['type'] == 0 ){ $sMain .= $this->dealContent($value['content'])."\\par\n"; } if($value['type'] == 1 ){//图片 $aImageInfo = empty($aArticleMainImage[$value['ami_id']]) ? [] : $aArticleMainImage[$value['ami_id']]; if(empty($aImageInfo['url'])){ continue; } // $sIconUrl = rtrim(ROOT_PATH).$this->sArticleIcon.'/'.$sIcon; // if(file_exists($sIconUrl)){ // $sIcon = '\KeywordImage{'.$sIconUrl.'}'; // }else{ // $sIcon = ''; // } //下载图片 $sImagePath = trim($this->sSubmissionUrl,'/').$this->sArticleMainImage.'/'.$aImageInfo['url']; $aResult = $this->getImage($sImagePath,$aProductionArticle['p_article_id']); if(empty($aResult['data'])){ continue; } $aImageSearch = ['{{img_url}}' => $aResult['data'],'{{img_title}}' => $aImageInfo['note'],'{{img_fig_sim}}' => 'img_fig_sim_'.$value['ami_id']]; $sImageTempalteInfo = str_replace(array_keys($aImageSearch), array_values($aImageSearch), $sImageTempalte); $sMain .= $sImageTempalteInfo."\\par\n"; } if($value['type'] == 2 ){//表格 continue; } } } } } $aSearch['{{article_main}}'] = empty($sMain) ? '' : $sMain."\n"; //模版内容替换 $sTemplateInfo = str_replace(array_keys($aSearch), array_values($aSearch), $sTemplateInfo); //返回内容 return ['status' => 1,'msg' => 'success','data' => $sTemplateInfo]; } /** * 生成初稿-作者信息 */ private function dealAuthor($aParam = []){ // 获取作者信息 $aParam = empty($aParam) ? $this->request->post() : $aParam; //必填值验证 $iPArticleId = empty($aParam['p_article_id']) ? '' : $aParam['p_article_id']; if(empty($iPArticleId)){ return json_encode(array('status' => 2,'msg' => 'Please select an article' )); } // //查询作者信息 $aWhere = ['p_article_id' => $iPArticleId,'state' => 0]; $aAuthor = Db::name('production_article_author')->where($aWhere)->select(); if(empty($aAuthor)){ return ['status' => 3,'msg' => 'Author information is empty']; } //查询作者机构 $aWhere['p_article_author_id'] = ['in',array_column($aAuthor, 'p_article_author_id')]; $aAuthorOrgan = Db::name('production_article_author_to_organ')->field('p_article_author_id,p_article_organ_id')->where($aWhere)->select(); //查询机构信息 $aAuthorOrganList = []; if(!empty($aAuthorOrgan)){ unset($aWhere['p_article_author_id']); $aOrganId = array_unique(array_column($aAuthorOrgan, 'p_article_organ_id')); $aWhere['p_article_organ_id'] = ['in',$aOrganId]; $aOrgan = Db::name('production_article_organ')->where($aWhere)->column('p_article_organ_id,organ_name'); if(!empty($aOrgan)) { foreach ($aAuthorOrgan as $key => $value) { if(empty($aOrgan[$value['p_article_organ_id']])){ continue; } $aAuthorOrganList[$value['p_article_author_id']][] = $aOrgan[$value['p_article_organ_id']]; } } } //处理作者 $sAuthor = $sCorrespondence = ''; foreach ($aAuthor as $key => $value) { //作者姓名 $sName = empty($value['fifirst_name']) ? '' : $value['fifirst_name']; $sName = empty($sName) ? '' : $sName . ' ' .$value['last_name']; if(empty($sName)){ $sName = empty($value['author_name']) ? '' : $value['author_name']; } if(empty($sName)){ continue; } $sAuthor .= '\author{'.$this->dealContent($sName).'}'."\n"; if(!empty($value['email']) && $value['is_report'] == 1){ $sAuthor .= '\email{'.$this->dealContent($value['email']).'}'."\n"; } //作者机构 $aOrganList = empty($aAuthorOrganList[$value['p_article_author_id']]) ? [] : $aAuthorOrganList[$value['p_article_author_id']]; if(!empty($aOrganList)){ $i = 0; foreach($aOrganList as $organ){ if(empty($organ)){ continue; } if($i == 0){ $sAuthor .= '\affiliation{'.$this->dealContent($organ).'}'."\n"; }else{ $sAuthor .= '\alsoaffiliation{'.$this->dealContent($organ).'}'."\n"; } $i++; } } if($value['is_first'] == 1){ $sAuthor .= '\firstauthor'."\n"; } if(!empty($value['orcid'])){ $sAuthor .= '\orcid{'.$this->dealContent($value['orcid']).'}'."\n"; } if($value['is_report'] == 1){ $sCorrespondence .= $sName; if(!empty($aOrganList[0])){ $sCorrespondence .= ','.trim($this->dealContent($aOrganList[0]),'.'); } if(!empty($value['email'])){ $sCorrespondence .= '.E-mail: '.trim($this->dealContent($value['email']),'.').'.'; } } } return ['author' => $sAuthor,'correspondence' => $sCorrespondence]; } /** * 生成初稿-获取期刊分期信息 */ private function getJournalStage($aParam = []){ // 获取分期ID $aParam = empty($aParam) ? $this->request->post() : $aParam; //必填值验证 $iJournalStageId = empty($aParam['journal_stage_id']) ? '' : $aParam['journal_stage_id']; if(empty($iJournalStageId)){ return json_encode(array('status' => 2,'msg' => 'Please choose journal installment' )); } $sUrl = $this->sJournalUrl."api/Supplementary/getJournalStage"; $aResult = object_to_array(json_decode(myPost1($sUrl,$aParam))); return $aResult; } /** * 处理文章引用 * @param string $html * @return string */ private function getArticleCite($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']; $aAbbr = empty($aArticle['abbr']) ? '' : explode(',', trim($aArticle['abbr'])); if(!empty($aAbbr)){ $sEnd = end($aAbbr); if($sEnd != 'et al'){ $aArticle['abbr'] = implode(',', array_slice($aAbbr, 0,3)); if(!empty($aArticle['abbr'])){ $aArticle['abbr'] .= ', et al'; } } } $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']; $sCite = $this->dealContent($sCite); } else { $sCite = $this->dealContent($aArticle['abbr']) . '. ' . $this->dealContent($aArticle['title']) . '. \textit{' . $this->dealContent(choiseJabbr($aArticle['article_id'], $jabbr)) . '}. ' . $stage_year . ';' . $stage_vol . $no . $aArticle['npp'] . '. doi:' . $aArticle['doi']; } return $sCite; } private function getArticleTime($aParam = []){ //必填值验证 $iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id']; if(empty($iArticleId)){ return array('status' => 2,'msg' => 'Please select an article' ); } //查询文章 $aWhere = ['article_id' => $iArticleId]; $aArticle= Db::name('article')->field('ctime,received_time')->where($aWhere)->find(); if(empty($aArticle)){ return array('status' => 2,'msg' => 'The article does not exist' ); } //获取文章记录 $aWhere = ['article_id' => $iArticleId,'state' => 0,'state_to' => ['in',[0,1,5]]]; $aArticleMsg = Db::name('article_msg')->field('state_from,state_to,ctime')->where($aWhere)->order('ctime deac')->select(); $iReceivedTime = $iRevisionTime = $iAcceptedTime = 0; if(!empty($aArticleMsg)){ foreach ($aArticleMsg as $key => $value) { if(empty($iReceivedTime) && $value['state_to'] == 0){ $iReceivedTime = $value['ctime']; } if(empty($iRevisionTime) && $value['state_to'] == 1){ $iRevisionTime = $value['ctime']; } if(empty($iAcceptedTime) && $value['state_to'] == 5){ $iAcceptedTime = $value['ctime']; } } } $iReceivedTime = empty($iReceivedTime) ? $aArticle['received_time'] : $iReceivedTime; $iReceivedTime = empty($iReceivedTime) ? $aArticle['ctime'] : $iReceivedTime; $aTime = []; $aTime['received_date'] = empty($iReceivedTime) ? '' : $this->timestampToEnglishDate($iReceivedTime); $aTime['revision_date'] = empty($iRevisionTime) ? '' : $this->timestampToEnglishDate($iRevisionTime); $aTime['accepted_date'] = empty($iAcceptedTime) ? '' : $this->timestampToEnglishDate($iAcceptedTime); return ['status' => 1,'msg' => 'success','data' => $aTime]; } /** * 时间戳转换为「d F Y」格式(如 12 June 2025) * @param int $timestamp 时间戳(如1749600000) * @return string 格式化后的英文日期 */ private function timestampToEnglishDate($timestamp) { //验证时间戳有效性 if (!is_numeric($timestamp) || $timestamp < 0) { return ''; } //设置本地化(确保月份为英文全称,兼容Linux/Windows) $locale = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? 'English_United States.1252' : 'en_US.UTF-8'; setlocale(LC_TIME, $locale); //格式化:d=日(无前导零)、F=英文月份全称、Y=四位年 strftime的%e在Linux下是无前导零的日,Windows用%#d if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { $dateStr = strftime('%#d %B %Y', $timestamp); // Windows } else { $dateStr = strftime('%e %B %Y', $timestamp); // Linux/Mac } return trim($dateStr); } /** * 内容处理 */ private function dealContent($content = '', $target = 'latex',$iIsDeal = 1) { // 空值直接返回 if (empty($content)) { return ''; } //统一编码为UTF-8 $content = mb_convert_encoding($content, 'UTF-8', mb_detect_encoding($content)); //过滤不可见/非法字符 $content = preg_replace('/[\x00-\x1F\x7F]/u', '', $content); //整合所有替换规则(按优先级排序:先处理HTML实体,再处理LaTeX特殊字符) $replaceRules = [ // ========== HTML实体替换 ========== ' ' => '~', // HTML非断行空格 → LaTeX非断行空格 ' ' => '~', // 兼容无分号的  '&' => '\&', // HTML& → LaTeX转义& '<' => '<', // HTML< → 直接保留 '>' => '>', // HTML> → 直接保留 // ========== LaTeX特殊字符转义 ========== '{' => '\{', // 左花括号转义 '}' => '\}', // 右花括号转义 '&' => '\&', // 原生&转义(需在&之后,避免覆盖) '%' => '\%', // 百分号转义(LaTeX注释符) '_' => '\_', // 下划线转义(LaTeX下标符) 'κ' => '$\kappa$', // 希腊字母κ → LaTeX数学环境(避免乱码) '-' => '\text{-}', // 短横线强制保留形态 ':' => ':', // 冒号无需转义(占位,便于统一维护) ]; //执行批量替换 $content = strtr($content, $replaceRules); //清理多余空格/换行 $content = preg_replace('/\s+/u', ' ', trim($content)); return $content; } /** * @title curl 请求获取图片保存到本地 * @param sPath 图片链接地址 */ private function getImage($sPath = '',$iId = 0){ //判断参数 if(empty($sPath) || empty($iId)){ return ['status' => 2,'msg' => 'url is empty','data' => '']; } //获取图片名称 $aImageInfo = pathinfo($sPath); //图片后缀名 $sExtension = empty($aImageInfo['extension']) ? 'jpg' : $aImageInfo['extension']; //图片地址 $sDir = ROOT_PATH.trim($this->sLatexUrl,'/').'/article_pdf/'.$iId.'/'; $sImagePath = $sDir.basename($sPath); if (file_exists($sImagePath)) { return ['status' => 1,'msg' => 'success','data' => $sImagePath]; } //下载图片 if (!is_dir($sDir)) { mkdir($sDir, 0755, true); } //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 ['status' => 3,'msg' => 'Error:' . curl_error($ch),'data' => $sImagePath]; } //保存图片 file_put_contents($sImagePath, $response); curl_close($ch); return ['status' => 1,'msg' => 'success','data' => $sImagePath]; } } ?>