生成文件
This commit is contained in:
@@ -3227,4 +3227,60 @@ class Production extends Base
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成初稿
|
||||||
|
* @param article_id 文章ID
|
||||||
|
*/
|
||||||
|
public function createArticlePdf($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];
|
||||||
|
$aProductionArticle = Db::name('production_article')->where($aWhere)->find();
|
||||||
|
if(empty($aProductionArticle)){
|
||||||
|
return json_encode(array('status' => 3,'msg' => 'No articles found' ));
|
||||||
|
}
|
||||||
|
|
||||||
|
//内容
|
||||||
|
$oLatexContent = new \app\common\LatexContent;
|
||||||
|
|
||||||
|
//内容生成
|
||||||
|
//获取第一页内容
|
||||||
|
$aResult = $oLatexContent->buildFirst($aProductionArticle);
|
||||||
|
$iStatus = empty($aResult['status']) ? 0 : $aResult['status'];
|
||||||
|
$sMsg = empty($aResult['msg']) ? 'Content generation failed-First' : $aResult['msg'];
|
||||||
|
$sFirstTemplateInfo = empty($aResult['data']) ? '' : $aResult['data'];
|
||||||
|
|
||||||
|
if($iStatus != 1){
|
||||||
|
return json_encode(array('status' => 4,'msg' => $sMsg));
|
||||||
|
}
|
||||||
|
if(empty($sFirstTemplateInfo)){
|
||||||
|
return json_encode(array('status' => 5,'msg' => 'Article content retrieval failed'));
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成主内容
|
||||||
|
$aResult = $oLatexContent->buildMain($aProductionArticle);
|
||||||
|
$iStatus = empty($aResult['status']) ? 0 : $aResult['status'];
|
||||||
|
$sMsg = empty($aResult['msg']) ? 'Content generation failed-Main' : $aResult['msg'];
|
||||||
|
$sMainTemplateInfo = empty($aResult['data']) ? '' : $aResult['data'];
|
||||||
|
if($iStatus != 1){
|
||||||
|
return json_encode(array('status' => 4,'msg' => $sMsg));
|
||||||
|
}
|
||||||
|
if(empty($sMainTemplateInfo)){
|
||||||
|
return json_encode(array('status' => 5,'msg' => 'Article content retrieval failed'));
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成文件
|
||||||
|
$sTemplateInfo = $sFirstTemplateInfo."\n".$sMainTemplateInfo;
|
||||||
|
return json_encode(array('status' => 1,'msg' => 'PDF generated successfully'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
618
application/common/LatexContent.php
Normal file
618
application/common/LatexContent.php
Normal file
@@ -0,0 +1,618 @@
|
|||||||
|
<?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];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
Reference in New Issue
Block a user