618 lines
28 KiB
PHP
618 lines
28 KiB
PHP
<?php
|
||
namespace app\common;
|
||
use think\Db;
|
||
use app\common\LatexTable;
|
||
/**
|
||
* LaTeX内容生成类
|
||
*/
|
||
class LatexContent{
|
||
//期刊相关的信息
|
||
private $iYear = 2025;//年
|
||
private $iPeriod = 1;//期
|
||
private $sAbbr = 'tmr';//期刊缩写
|
||
private $sWebsite = 'https://www.tmrjournals.com/tmr';//期刊官网
|
||
//模版地址
|
||
private $sLatexUrl = '/public/latex/';
|
||
//期刊官网接口地址
|
||
private $sJournalUrl = 'http://zmzm.journal.dev.com/';//'http://journalapi.tmrjournals.com/public/index.php/';//
|
||
//文章图片
|
||
private $sArticleIcon = '/public/articleicon/';
|
||
//文章图片
|
||
private $sArticleMainImage = '/public/articleImage/';
|
||
//编辑系统URL
|
||
private $sSubmissionUrl = 'https://submission.tmrjournals.com/';
|
||
//图片模版
|
||
private $sImageTempalte = '\begin{figure}[hbt!]
|
||
\centering
|
||
\includegraphics[width=0.75\linewidth]{{{img_url}}}
|
||
\caption{{{img_title}}}
|
||
\label{{{img_fig_sim}}}
|
||
\end{figure}' ;
|
||
//首页内容
|
||
private $sFirst = '\documentclass[
|
||
journal={{journal_abbr}},
|
||
journalname={{{{journal_title}}}},
|
||
layout=largetwo,
|
||
year={{stage_year}},%年
|
||
volume={{stage_vol}},%卷
|
||
no={{stage_no}},%期
|
||
page={{stage_page}},%号
|
||
]{tmr-tex}
|
||
|
||
\doi{{{doi}}}
|
||
\journalweb{{{website}}}
|
||
|
||
% \def\ORCIdICONNAME{{{CLSFILEURL}}/orcid_icon.png} %定义ORCID图片
|
||
% \def\TMRLOGONAME{{{CLSFILEURL}}/tmr-logo.pdf} % 定义期刊LOGO图片
|
||
|
||
\usepackage{amsmath}
|
||
\usepackage[nopatch]{microtype}
|
||
\usepackage{booktabs}
|
||
\usepackage[backend=biber]{biblatex}
|
||
\usepackage{xcolor} % 蓝色字体(参考文献)
|
||
\usepackage{multirow} % 单元格合并(必选)
|
||
\usepackage{array} % 列格式居中(必选)
|
||
\usepackage{geometry} % 页面适配,避免内容溢出
|
||
\addbibresource{example.bib}
|
||
|
||
\title{{{article_title}}}
|
||
|
||
{{author_info}}
|
||
|
||
\addbibresource{example.bib}
|
||
|
||
{{correspondence_info}}
|
||
|
||
|
||
\keywords{keyword entry 1, keyword entry 2, keyword entry 3} %% First letter not capped
|
||
|
||
{{author_contribution}}
|
||
\competinginterests{The authors declare no conflicts of interest.}
|
||
{{article_acknowledgment}}
|
||
\Peerreviewinformation{{{journal_title}} thanks all anonymous reviewers for their contribution to the peer review of this paper}
|
||
{{article_abbreviation}}
|
||
{{article_cite}}
|
||
\received{{{received_date}}}
|
||
\revised{{{revision_date}}}
|
||
\accepted{{{accepted_date}}}
|
||
\Availableonline{{{pub_date}}}
|
||
{{executive_editor}}
|
||
{{abstract}}
|
||
{{keywords}}
|
||
|
||
|
||
{{article_icon}}';
|
||
//正文内容
|
||
private $sMain = '\begin{document}
|
||
\twocolumn
|
||
{{tmr_highlight}}
|
||
{{article_main}}
|
||
\end{document}';
|
||
/**
|
||
* 生成初稿-基本内容
|
||
* @param article_id 文章ID
|
||
*/
|
||
public function buildFirst($aProductionArticle = []){
|
||
|
||
//获取模版
|
||
$sTemplateInfo = $this->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[^>]*>(.*?)<\/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];
|
||
|
||
}
|
||
|
||
}
|
||
?>
|