Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -351,7 +351,7 @@ class Article extends Base
|
||||
$aAiReview = array();
|
||||
if (!empty($res)) {
|
||||
$aArticleId = array_column($res, 'article_id');
|
||||
$aAiReview = Db::table('t_article_ai_review')->field('article_id,content')->whereIn('article_id', $aArticleId)->column('article_id,content');
|
||||
$aAiReview = Db::table('t_article_ai_review')->field('article_id,content')->whereIn('article_id', $aArticleId)->where('journal_scope_assessment','<>','')->column('article_id,content');
|
||||
}
|
||||
//查询AI审核内容 chengxiaoling 20250328 end
|
||||
|
||||
@@ -3215,7 +3215,7 @@ class Article extends Base
|
||||
}
|
||||
$info = $this->article_author_obj->where("art_aut_id", $data['art_aut_id'])->find();
|
||||
if ($info['sort'] < 2) {
|
||||
return jsonError("fail");
|
||||
return jsonError("Upward adjustment: Failed to obtain the location of the exchanged author");
|
||||
}
|
||||
$info_1 = $this->article_author_obj->where("article_id", $info['article_id'])->where("state", 0)->where("sort", $info['sort'] - 1)->find();
|
||||
$this->article_author_obj->where("art_aut_id", $info['art_aut_id'])->setDec("sort");
|
||||
@@ -3238,7 +3238,7 @@ class Article extends Base
|
||||
$info = $this->article_author_obj->where("art_aut_id", $data['art_aut_id'])->find();
|
||||
$info_1 = $this->article_author_obj->where("article_id", $info['article_id'])->where("state", 0)->where("sort", $info['sort'] + 1)->find();
|
||||
if ($info_1 == null) {
|
||||
return jsonError("fail");
|
||||
return jsonError("Downward adjustment:Failed to obtain the location of the exchanged author");
|
||||
}
|
||||
$this->article_author_obj->where("art_aut_id", $info['art_aut_id'])->setInc("sort");
|
||||
$this->article_author_obj->where("art_aut_id", $info_1['art_aut_id'])->setDec("sort");
|
||||
@@ -3699,6 +3699,14 @@ class Article extends Base
|
||||
if ($black) {
|
||||
return jsonError("Your account is currently blacklisted by TMR Publishing Group. Please contact the official email of the journal you wish to submit to for further clarification.");
|
||||
}
|
||||
|
||||
//验证前三步骤是否完成
|
||||
$aArticleState = $this->getArticleStateThree($article_info);
|
||||
$iStatus = empty($aArticleState['status']) ? 0 : $aArticleState['status'];
|
||||
$sMsg = empty($aArticleState['msg']) ? '' : $aArticleState['msg'];
|
||||
if($iStatus != 1){
|
||||
return jsonError($sMsg);
|
||||
}
|
||||
//稿件号
|
||||
$sbbr = empty($journal_info['abbr']) ? '' : $journal_info['abbr'];
|
||||
$sArticleType = empty($article_info['type']) ? '' : $article_info['type'];
|
||||
@@ -3856,18 +3864,20 @@ class Article extends Base
|
||||
$this->article_obj->where('article_id', $data['article_id'])->update($update_l);
|
||||
$this->ai_scor($data['article_id']);
|
||||
|
||||
//判断是否有文章领域 进行更新操作 chengxiaoling 20250722 start
|
||||
$iArticleId = empty($data['article_id']) ? 0 : $data['article_id'];//文章ID
|
||||
if(!empty($sMajorData) && !empty($iArticleId)){
|
||||
$this->updateArticleField(['article_id' => $iArticleId,'article_field' => $sMajorData]);
|
||||
}
|
||||
//判断是否有文章领域 进行更新操作 chengxiaoling 20250722 end
|
||||
//AI初审队列 chengxiaoling 20250815 start
|
||||
$iArticleId = empty($data['article_id']) ? 0 : $data['article_id'];//文章ID
|
||||
if(!empty($iArticleId)){
|
||||
$aQueueParam = ['article_id' => $iArticleId];
|
||||
$sQueueId = \think\Queue::push('app\api\job\ArticleReview@fire', $aQueueParam, 'ArticleReview');
|
||||
}
|
||||
//AI初审队列 chengxiaoling 20250815 end
|
||||
|
||||
//判断是否有文章领域 进行更新操作 chengxiaoling 20250722 start
|
||||
if(!empty($sMajorData) && !empty($iArticleId)){
|
||||
$this->updateArticleField(['article_id' => $iArticleId,'article_field' => $sMajorData]);
|
||||
}
|
||||
//判断是否有文章领域 进行更新操作 chengxiaoling 20250722 end
|
||||
|
||||
return json(['code' => 0]);
|
||||
}
|
||||
|
||||
@@ -5394,6 +5404,7 @@ class Article extends Base
|
||||
//第二步 查询作者
|
||||
$iSecondStatus = 1;
|
||||
$is_super = $is_report = 2;
|
||||
$sSecondMsg = $sSecondReportMsg = '';
|
||||
// if($iFirstStatus == 1){
|
||||
$aWhere = ['article_id' => $iArticleId,'state' => 0];
|
||||
$aAuthorData = DB::name('article_author')->where($aWhere)->select();
|
||||
@@ -5404,11 +5415,18 @@ class Article extends Base
|
||||
foreach ($aAuthorData as $key => $value) {
|
||||
if(empty($value['email']) || empty($value['author_title']) || empty($value['company']) || empty($value['firstname']) || empty($value['lastname'])){
|
||||
$iSecondStatus = 2;
|
||||
$sSecondMsg = 'Step 2: The author\'s information is incomplete';
|
||||
break;
|
||||
}
|
||||
if($is_report != 1){
|
||||
if($value['is_report'] == 1 && !empty($value['orcid'])){
|
||||
$is_report = 1;
|
||||
if($value['is_report'] == 1){
|
||||
if(empty($value['orcid'])){
|
||||
$sSecondReportMsg = 'Step 2: Please fill in the ORCID of at least one corresponding author';
|
||||
}
|
||||
if(!empty($value['orcid'])){
|
||||
$is_report = 1;
|
||||
$sSecondReportMsg = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
if($is_super != 1){
|
||||
@@ -5421,7 +5439,7 @@ class Article extends Base
|
||||
}
|
||||
// }
|
||||
if($iSecondStatus == 2){
|
||||
$sSecondMsg = 'Step 2: The author\'s required information is incomplete';
|
||||
$sSecondMsg = empty($sSecondMsg) ? 'Step 2: The author\'s information is incomplete' : $sSecondMsg;
|
||||
}
|
||||
if($iSecondStatus == 1){
|
||||
if($is_super == 2){
|
||||
@@ -5429,7 +5447,7 @@ class Article extends Base
|
||||
$iSecondStatus = 2;
|
||||
}
|
||||
if($is_report == 2){
|
||||
$sSecondMsg = empty($sSecondMsg) ? 'Step 2: Please select the first author' : 'Step 2: Please select the corresponding/first author';
|
||||
$sSecondMsg = empty($sSecondReportMsg) ? 'Step 2: Please select the corresponding author' : $sSecondReportMsg;
|
||||
$iSecondStatus = 2;
|
||||
}
|
||||
}
|
||||
@@ -5702,14 +5720,14 @@ class Article extends Base
|
||||
}
|
||||
|
||||
//参数判空
|
||||
$sMajorData = empty($aParam['major']) ? '' : $aParam['major'];//文章领域
|
||||
$sMajorData = isset($aParam['major']) ? $aParam['major'] : '-1' ;//文章领域
|
||||
// if(empty($sMajorData) && empty($aUpdate)){
|
||||
// return json_encode(['status' => 6,'msg' => 'Update data to empty']);
|
||||
// }
|
||||
|
||||
//文章领域处理
|
||||
$aMajorInsert = $aMajorDelete = [];
|
||||
if(!empty($sMajorData)){
|
||||
if(!empty($sMajorData) && is_string($sMajorData) && $sMajorData != -1){
|
||||
$aField = explode(',', $sMajorData);
|
||||
$aWhere = ['state' => 0, 'article_id' => $iArticleId];
|
||||
$aArticleMajor = Db::name('major_to_article')->where($aWhere)->order('major_id asc')->column('major_id');
|
||||
@@ -5720,34 +5738,41 @@ class Article extends Base
|
||||
//数据处理
|
||||
if (!empty($aInsert)) {//新增
|
||||
foreach ($aInsert as $key => $value) {
|
||||
$value = intval($value);
|
||||
if(empty($value)){
|
||||
continue;
|
||||
}
|
||||
$aMajorInsert[] = ['major_id' => $value, 'article_id' => $iArticleId, 'ctime' => time(), 'state' => 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//转投信息
|
||||
$aTransferJournalId = empty($aParam['checkedjours']) ? [] : $aParam['checkedjours'];
|
||||
if(!empty($aTransferJournalId) && is_string($aTransferJournalId)){
|
||||
$aTransferJournalId = explode(',', $aTransferJournalId);
|
||||
}
|
||||
$aJournalInsert = $aJournalDelete = [];
|
||||
if(!empty($aTransferJournalId)){
|
||||
//查询转投期刊ID
|
||||
if($sMajorData == ''){//为空删除
|
||||
$aWhere = ['state' => 0, 'article_id' => $iArticleId];
|
||||
$aTransferJournal = Db::name('article_transfer')->where($aWhere)->order('journal_id asc')->column('journal_id');
|
||||
//新增
|
||||
$aInsert = array_diff($aTransferJournalId, $aTransferJournal);
|
||||
//删除
|
||||
$aJournalDelete = array_diff($aTransferJournal, $aTransferJournalId);
|
||||
if (!empty($aInsert)) {//新增
|
||||
foreach ($aInsert as $key => $value) {
|
||||
$aJournalInsert[] = ['journal_id' => $value, 'article_id' => $iArticleId, 'ctime' => time(), 'state' => 0];
|
||||
}
|
||||
}
|
||||
$aMajorDelete = Db::name('major_to_article')->where($aWhere)->column('major_id');
|
||||
}
|
||||
//转投信息
|
||||
// $aTransferJournalId = empty($aParam['checkedjours']) ? [] : $aParam['checkedjours'];
|
||||
// if(!empty($aTransferJournalId) && is_string($aTransferJournalId)){
|
||||
// $aTransferJournalId = explode(',', $aTransferJournalId);
|
||||
// }
|
||||
// $aJournalInsert = $aJournalDelete = [];
|
||||
// if(!empty($aTransferJournalId)){
|
||||
// //查询转投期刊ID
|
||||
// $aWhere = ['state' => 0, 'article_id' => $iArticleId];
|
||||
// $aTransferJournal = Db::name('article_transfer')->where($aWhere)->order('journal_id asc')->column('journal_id');
|
||||
// //新增
|
||||
// $aInsert = array_diff($aTransferJournalId, $aTransferJournal);
|
||||
// //删除
|
||||
// $aJournalDelete = array_diff($aTransferJournal, $aTransferJournalId);
|
||||
// if (!empty($aInsert)) {//新增
|
||||
// foreach ($aInsert as $key => $value) {
|
||||
// $aJournalInsert[] = ['journal_id' => $value, 'article_id' => $iArticleId, 'ctime' => time(), 'state' => 0];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//推荐审稿人
|
||||
$aReviewer = isset($aParam['reviewers']) ? $aParam['reviewers'] : [];
|
||||
$aReviewer = isset($aParam['reviewers']) ? $aParam['reviewers'] : '-1';
|
||||
// $json = '{
|
||||
// "article_id": "5997",
|
||||
// "user_id": "54",
|
||||
@@ -5786,7 +5811,7 @@ class Article extends Base
|
||||
// }';
|
||||
// $aReviewer = json_decode($json,true);
|
||||
// $aReviewer = $aReviewer['reviewers'];
|
||||
if(!empty($aReviewer)){
|
||||
if(!empty($aReviewer) && is_array($aReviewer)){
|
||||
|
||||
//根据用户邮箱查询是否注册
|
||||
$aEmail = array_unique(array_column($aReviewer, 'email'));
|
||||
@@ -5877,6 +5902,10 @@ class Article extends Base
|
||||
$aUserRecommendDelete = array_diff($aUserRecommend,$aUserRecommendId);
|
||||
}
|
||||
}
|
||||
if($aReviewer == ''){
|
||||
$aWhere = ['article_id' => $iArticleId];
|
||||
$aUserRecommendDelete = Db::name('user_reviewer_recommend')->where($aWhere)->column('reviewer_id');
|
||||
}
|
||||
Db::startTrans();
|
||||
if(!empty($aMajorInsert)){//新增领域
|
||||
$add_result = Db::name('major_to_article')->insertAll($aMajorInsert);
|
||||
@@ -5885,13 +5914,13 @@ class Article extends Base
|
||||
$aWhere = ['article_id' => $iArticleId, 'state' => 0, 'major_id' => ['in', $aMajorDelete]];
|
||||
$delete_result = Db::name('major_to_article')->where($aWhere)->limit(count($aMajorDelete))->update(['state' => 1, 'ctime' => time()]);
|
||||
}
|
||||
if(!empty($aJournalInsert)){//新增转投期刊
|
||||
$add_journal_result = Db::name('article_transfer')->insertAll($aJournalInsert);
|
||||
}
|
||||
if(!empty($aJournalDelete)){//删除转投期刊
|
||||
$aWhere = ['article_id' => $iArticleId, 'state' => 0, 'journal_id' => ['in', $aJournalDelete]];
|
||||
$delete_journal_result = Db::name('article_transfer')->where($aWhere)->limit(count($aJournalDelete))->delete();
|
||||
}
|
||||
// if(!empty($aJournalInsert)){//新增转投期刊
|
||||
// $add_journal_result = Db::name('article_transfer')->insertAll($aJournalInsert);
|
||||
// }
|
||||
// if(!empty($aJournalDelete)){//删除转投期刊
|
||||
// $aWhere = ['article_id' => $iArticleId, 'state' => 0, 'journal_id' => ['in', $aJournalDelete]];
|
||||
// $delete_journal_result = Db::name('article_transfer')->where($aWhere)->limit(count($aJournalDelete))->delete();
|
||||
// }
|
||||
//更新数据
|
||||
if(!empty($aUpdate)){//更新文章主表数据
|
||||
//数据更新
|
||||
@@ -5915,7 +5944,7 @@ class Article extends Base
|
||||
}
|
||||
if(!empty($aUserRecommendDelete)){
|
||||
$aWhere = ['urr_state' => 0,'article_id' => $iArticleId,'reviewer_id' => ['in',$aUserRecommendDelete]];
|
||||
$sDelete = Db::name('user_reviewer_recommend')->where($aWhere)->limit(count($aUserRecommendDelete))->delete();
|
||||
$sDelete = Db::name('user_reviewer_recommend')->where($aWhere)->limit(count($aUserRecommendDelete))->update(['urr_state' => 1]);
|
||||
}
|
||||
Db::commit();
|
||||
|
||||
@@ -6043,4 +6072,131 @@ class Article extends Base
|
||||
$p = self::getMajorShuList($res['pid']);
|
||||
return $p . ',' . $res['major_id'];
|
||||
}
|
||||
/**
|
||||
* 按步骤获取文章的状态
|
||||
*/
|
||||
private function getArticleStateThree($aArticle = []){
|
||||
|
||||
if(empty($aArticle)){
|
||||
return ['status' => 2,'msg' => 'The article does not exist'];
|
||||
}
|
||||
|
||||
//第一步验证
|
||||
$aFirst = ['title','type','abstrart','journal_id'];
|
||||
$iFirstStatus = 1;
|
||||
$sFirstMsg = $sSecondMsg = $sThreeMsg = $sFourMsg = '';
|
||||
foreach ($aFirst as $key => $value) {
|
||||
if(empty($aArticle[$value])){
|
||||
$iFirstStatus = 2;
|
||||
$sFirstMsg = 'Step 1: Required fields incomplete'.$value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($iFirstStatus == 2){
|
||||
return ['status' => 3,'msg' => $sFirstMsg];
|
||||
}
|
||||
//判断伦理
|
||||
if(!empty($aArticle['approval']) && $aArticle['approval'] == 1 && empty($aArticle['approval_file'])){
|
||||
$iFirstStatus = 2;
|
||||
$sFirstMsg = 'Step 1: Ethics documents not uploaded';
|
||||
return ['status' => 3,'msg' => $sFirstMsg];
|
||||
}
|
||||
if(isset($aArticle['approval']) && $aArticle['approval'] == 0 && empty($aArticle['approval_content'])){
|
||||
$iFirstStatus = 2;
|
||||
$sFirstMsg = 'Step 1: Please explain the lack of ethical recognition';
|
||||
return ['status' => 3,'msg' => $sFirstMsg];
|
||||
}
|
||||
|
||||
//查询manuscirpt文件是否上传
|
||||
$iArticleId = empty($aArticle['article_id']) ? 0 : $aArticle['article_id'];
|
||||
$aWhere = ['article_id' => $iArticleId,'state' => 0,'type_name' => 'manuscirpt'];
|
||||
$aFile = Db::name('article_file')->where($aWhere)->order('ctime desc')->find();
|
||||
if(empty($aFile)){
|
||||
$iFirstStatus = 2;
|
||||
$sFirstMsg = 'Step 1: The manuscirpt file has not been uploaded';
|
||||
return ['status' => 3,'msg' => $sFirstMsg];
|
||||
}
|
||||
|
||||
|
||||
//第二步 查询作者
|
||||
$iSecondStatus = 1;
|
||||
$is_super = 2;
|
||||
$is_report = 2;
|
||||
$sSecondMsg = $sSecondReportMsg = '';
|
||||
$aWhere = ['article_id' => $iArticleId,'state' => 0];
|
||||
$aAuthorData = DB::name('article_author')->where($aWhere)->select();
|
||||
if(empty($aAuthorData)){
|
||||
$iSecondStatus = 2;
|
||||
}
|
||||
if(!empty($aAuthorData)){
|
||||
foreach ($aAuthorData as $key => $value) {
|
||||
if(empty($value['email']) || empty($value['author_title']) || empty($value['company']) || empty($value['firstname']) || empty($value['lastname'])){
|
||||
$iSecondStatus = 2;
|
||||
break;
|
||||
}
|
||||
if($is_report != 1){
|
||||
if($value['is_report'] == 1){
|
||||
if(empty($value['orcid'])){
|
||||
$sSecondReportMsg = 'Step 2: Please fill in the ORCID of at least one corresponding author';
|
||||
}
|
||||
if(!empty($value['orcid'])){
|
||||
$is_report = 1;
|
||||
$sSecondReportMsg = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
if($is_super != 1){
|
||||
if($value['is_super'] == 1){
|
||||
$is_super = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if($iSecondStatus == 2){
|
||||
$sSecondMsg = 'Step 2: The author\'s information is incomplete';
|
||||
return ['status' => 3,'msg' => $sSecondMsg];
|
||||
}
|
||||
if($iSecondStatus == 1){
|
||||
if($is_super == 2){
|
||||
$sSecondMsg = 'Step 2: Please select the first author';
|
||||
$iSecondStatus = 2;
|
||||
return ['status' => 3,'msg' => $sSecondMsg];
|
||||
}
|
||||
if($is_report == 2){
|
||||
$sSecondMsg = empty($sSecondReportMsg) ? 'Step 2: Please select the corresponding author' : $sSecondReportMsg;
|
||||
$iSecondStatus = 2;
|
||||
return ['status' => 3,'msg' => $sSecondMsg];
|
||||
}
|
||||
}
|
||||
|
||||
//第三步
|
||||
$iThreeStatus = 1;
|
||||
$sThreeMsg = '';
|
||||
if($aArticle['is_use_ai'] == 3){//验证是否使用AI
|
||||
$sThreeMsg = 'Step 3: Please check whether to use AI technology';
|
||||
$iThreeStatus = 2;
|
||||
return ['status' => 3,'msg' => $sThreeMsg];
|
||||
}
|
||||
if($aArticle['is_use_ai'] == 1 && empty($aArticle['use_ai_explain'])){//验证是否填写AI说明
|
||||
$sThreeMsg = 'Step 3: Please enter supplementary instructions';
|
||||
$iThreeStatus = 2;
|
||||
return ['status' => 3,'msg' => $sThreeMsg];
|
||||
}
|
||||
if($aArticle['is_figure_copyright'] == 3){//验证是否上传版权声明
|
||||
$sThreeMsg = 'Step 3: Please check whether to upload the figure copyright statement';
|
||||
$iThreeStatus = 2;
|
||||
return ['status' => 3,'msg' => $sThreeMsg];
|
||||
}
|
||||
if($aArticle['is_figure_copyright'] == 1){//验证是否上传版权声明
|
||||
$aWhere = ['article_id' => $iArticleId,'state' => 0,'type_name' => 'figurecopyright'];
|
||||
$aFile = Db::name('article_file')->where($aWhere)->order('ctime desc')->find();
|
||||
if(empty($aFile)){
|
||||
$sThreeMsg = 'Step 3: Please upload the figure copyright declaration file';
|
||||
$iThreeStatus = 2;
|
||||
return ['status' => 3,'msg' => $sThreeMsg];
|
||||
}
|
||||
}
|
||||
return ['status' => 1,'msg' => 'success'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ class Contribute extends Base
|
||||
//获取数据
|
||||
$aDealData = json_decode(ArticleParserService::uploadAndParse($sFileUrl),true);
|
||||
$iStatus = empty($aDealData['status']) ? 0 : $aDealData['status'];
|
||||
$sMsg = empty($aDealData['msg']) ? 'fail' : $aDealData['msg'];
|
||||
$sMsg = empty($aDealData['msg']) ? 'Content parsing failed' : $aDealData['msg'];
|
||||
if($iStatus != 1){
|
||||
return json_encode(['status' => 5, 'msg' => $sMsg]);
|
||||
}
|
||||
@@ -96,7 +96,6 @@ class Contribute extends Base
|
||||
if(!empty($aArticle)){
|
||||
return json_encode(['code' => 7, 'msg' => 'Warning: you are re-submitting the article!']);
|
||||
}
|
||||
|
||||
//数据入库
|
||||
$aData += $aParam;
|
||||
$result = $this->_addData($aData);
|
||||
@@ -121,34 +120,36 @@ class Contribute extends Base
|
||||
//插入基础表 t_article
|
||||
$aInsert = [];
|
||||
//标题
|
||||
if(empty($aArticle['title'])){
|
||||
// if(empty($aArticle['title'])){
|
||||
$sTitile = empty($aParam['title']) ? '' : $aParam['title'];
|
||||
if(!empty($sTitile)){
|
||||
$aInsert['title'] = $sTitile;
|
||||
$aInsert['title'] = is_string($sTitile) ? strip_tags($sTitile) : '';
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
//关键词
|
||||
if(empty($aArticle['keywords'])){
|
||||
// if(empty($aArticle['keywords'])){
|
||||
$sKeyWords = empty($aParam['keywords']) ? '' : $aParam['keywords'];
|
||||
if(!empty($sKeyWords)){
|
||||
$aInsert['keywords'] = is_array($sKeyWords) ? implode(',', $sKeyWords) : $sKeyWords;
|
||||
$aInsert['keywords'] = is_string($aInsert['keywords']) ? str_replace(';', ',', $aInsert['keywords']) : '';
|
||||
|
||||
}
|
||||
}
|
||||
// }
|
||||
//摘要
|
||||
if(empty($aArticle['abstrart'])){
|
||||
// if(empty($aArticle['abstrart'])){
|
||||
$sAbstrart = empty($aParam['abstrart']) ? '' : $aParam['abstrart'];
|
||||
if(!empty($sAbstrart)){
|
||||
$aInsert['abstrart'] = $sAbstrart;
|
||||
$aInsert['abstrart'] = is_string($sAbstrart) ? strip_tags($sAbstrart) : '';
|
||||
}
|
||||
}
|
||||
// }
|
||||
//基金
|
||||
if(empty($aArticle['fund'])){
|
||||
// if(empty($aArticle['fund'])){
|
||||
$sFund = empty($aParam['fund']) ? '' : $aParam['fund'];
|
||||
if(!empty($sAbstrart)){
|
||||
$aInsert['fund'] = $sFund;
|
||||
if(!empty($sFund)){
|
||||
$aInsert['fund'] = is_string($sFund) ? strip_tags($sFund) : '';
|
||||
}
|
||||
}
|
||||
// }
|
||||
//期刊ID
|
||||
$iJournalId = empty($aParam['journal_id']) ? 0 : $aParam['journal_id'];
|
||||
if(!empty($iJournalId)){
|
||||
@@ -182,19 +183,14 @@ class Contribute extends Base
|
||||
$aInsert['state'] = -1;
|
||||
$aInsert['is_use_ai'] = 3;
|
||||
$aInsert['is_figure_copyright'] = 3;
|
||||
$aInsert['is_transfer'] = 3;
|
||||
// $aInsert['is_transfer'] = 3;
|
||||
$aInsert['is_become_reviewer'] = 3;
|
||||
$sType = empty($aParam['type']) ? 'D' : $aParam['type'];
|
||||
$aInsert['accept_sn'] = getArticleSN('Draft',$sType);
|
||||
$iArticleId = Db::name('article')->insertGetId($aInsert);
|
||||
if(empty($iArticleId)){
|
||||
return json_encode(['status' => 3,'msg' => 'Article added successfully']);
|
||||
}
|
||||
//获取accept_sn并更新
|
||||
$sAcceptSn = $this->getArticleAcceptSn(['article_id' => $iArticleId]);
|
||||
if(!empty($sAcceptSn)){
|
||||
$aWhere = ['article_id' => $iArticleId];
|
||||
$aUpdate = ['accept_sn' => $sAcceptSn];
|
||||
$update_result = Db::name('article')->where($aWhere)->limit(1)->update($aUpdate);
|
||||
}
|
||||
}
|
||||
if(!empty($aArticle) && !empty($aInsert)){//更新
|
||||
$aWhere = ['article_id' => $iUpdateArticleId,'state' => ['in',[-1,3]]];
|
||||
@@ -210,11 +206,58 @@ class Contribute extends Base
|
||||
}
|
||||
}
|
||||
|
||||
//作者单位
|
||||
$iArticleId = empty($iArticleId) ? $iUpdateArticleId : $iArticleId;
|
||||
$aCompany = empty($aParam['company']) ? [] : $aParam['company'];
|
||||
//处理作者
|
||||
$aCompanyId = $aAuthor = [];//作者机构ID
|
||||
if(!empty($aParam['author'])){
|
||||
$aAuthor = $aParam['author'];
|
||||
foreach ($aAuthor as $key => $value) {
|
||||
if(empty($iArticleId)){
|
||||
break;
|
||||
}
|
||||
//处理作者名字
|
||||
$aName = empty($value['name']) ? [] : explode(' ', $value['name']);
|
||||
if(empty($aName)){
|
||||
continue;
|
||||
}
|
||||
//名字拆分
|
||||
$sOldLastName = array_pop($aName);
|
||||
$letters = [
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
||||
'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'x', 'y', 'z'
|
||||
];
|
||||
if(in_array(strtolower($sOldLastName), $letters)){
|
||||
$value['company_id'] = [$sOldLastName];
|
||||
$sLastName = array_pop($aName);
|
||||
if(!empty($value['superscript'])){
|
||||
$value['is_super'] = strpos($value['superscript'], '1') !== false ? 1 : 0;
|
||||
$value['superscript'] = $sOldLastName.$value['superscript'];
|
||||
}
|
||||
|
||||
if(!empty($aCompany)){
|
||||
}else{
|
||||
$sLastName = $sOldLastName;
|
||||
}
|
||||
$value['firstname'] = empty($aName) ? '' : trim(implode(' ', $aName));
|
||||
if(empty($value['firstname'])){
|
||||
continue;
|
||||
}
|
||||
if(ctype_upper($value['firstname'][0]) == false){
|
||||
continue;
|
||||
}
|
||||
$value['lastname'] = $sLastName;
|
||||
$aAuthor[$key] = $value;
|
||||
if(!empty($value['company_id'])){
|
||||
$aCompanyId[] = implode(',', $value['company_id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
$aCompanyId = empty($aCompanyId) ? [] : array_unique(explode(',', implode(',', $aCompanyId)));
|
||||
|
||||
//文章机构
|
||||
$iArticleId = empty($iArticleId) ? $iUpdateArticleId : $iArticleId;
|
||||
if(!empty($aCompanyId)){
|
||||
$aCompany = empty($aParam['company']) ? [] : $aParam['company'];
|
||||
$aWhere = ['article_id' => $iArticleId,'state' => 0];
|
||||
$aOrgan = Db::name('article_organ')->field('organ_id,organ_name,sort')->where($aWhere)->select();
|
||||
$aOrganName = empty($aOrgan) ? [] : array_column($aOrgan, 'organ_name');
|
||||
@@ -225,17 +268,19 @@ class Contribute extends Base
|
||||
if(empty($value)){
|
||||
continue;
|
||||
}
|
||||
if(!in_array($key, $aCompanyId)){
|
||||
continue;
|
||||
}
|
||||
$sName = trim(trim(trim($value,'*'),'#'));
|
||||
if(in_array($sName, $aOrganName)){
|
||||
continue;
|
||||
}
|
||||
if(empty($iMaxSort)){
|
||||
$iSort = $key;
|
||||
$aSort[$key] = $key;
|
||||
}else{
|
||||
$iMaxSort++;
|
||||
$iSort = $iMaxSort;
|
||||
$aSort[$key] = $iMaxSort;
|
||||
$iMaxSort++;
|
||||
$iSort = $iMaxSort;
|
||||
$aSort[$key] = $iMaxSort;
|
||||
$sName = is_string($sName) ? strip_tags($sName) : '';
|
||||
if(empty($sName)){
|
||||
continue;
|
||||
}
|
||||
$aCompanyInsert[] = ['article_id' => $iArticleId,'organ_name' =>$sName,'create_time' => time(),'sort' => $iSort];
|
||||
}
|
||||
@@ -246,34 +291,66 @@ class Contribute extends Base
|
||||
return json_encode(['status' => 3,'msg' => 'Article institution insertion failed']);
|
||||
}
|
||||
$aWhere = ['article_id' => $iArticleId,'state' => 0];
|
||||
$aCompanyData = Db::name('article_organ')->where($aWhere)->column('sort,organ_id');
|
||||
$aCompanyData = Db::name('article_organ')->field('sort,organ_id,organ_name')->where($aWhere)->select();
|
||||
$aCompanyData = empty($aCompanyData) ? [] : array_column($aCompanyData, null,'sort');
|
||||
}
|
||||
//处理作者
|
||||
$aAuthorData = $aAuthorOrgn = [];
|
||||
if(!empty($aParam['author'])){
|
||||
$aAuthor = $aParam['author'];
|
||||
if(!empty($aAuthor)){
|
||||
//通讯作者
|
||||
$aCorresponding = empty($aParam['corresponding']) ? [] : array_column($aParam['corresponding'], null,'name');
|
||||
//查询文章作者
|
||||
$aWhere = ['article_id' => $iArticleId,'state' => 0];
|
||||
$aAuthorList = Db::name('article_author')->field('art_aut_id,firstname')->where($aWhere)->select();
|
||||
$aAuthorList = Db::name('article_author')->field('art_aut_id,firstname,sort')->where($aWhere)->select();
|
||||
$aAuthorNameList = empty($aAuthorList) ? [] : array_column($aAuthorList, 'firstname');
|
||||
$iMaxSort = empty($aAuthorList) ? 0 : max(array_column($aAuthorList, 'sort'));
|
||||
foreach ($aAuthor as $key => $value) {
|
||||
if(empty($iArticleId)){
|
||||
break;
|
||||
//处理作者名
|
||||
if(empty($value['firstname'])){
|
||||
continue;
|
||||
}
|
||||
if(ctype_upper($value['firstname'][0]) == false){
|
||||
continue;
|
||||
}
|
||||
//处理作者机构单位关联
|
||||
$aCountry = [];
|
||||
if(!empty($value['company_id'])){
|
||||
foreach ($value['company_id'] as $k => $v) {
|
||||
$iNewSort = empty($aSort[$v]) ? $v : $aSort[$v];
|
||||
$iOrgnId = empty($aCompanyData[$iNewSort]) ? 0 : $aCompanyData[$iNewSort];
|
||||
$iOrgnId = empty($aCompanyData[$iNewSort]['organ_id']) ? 0 : $aCompanyData[$iNewSort]['organ_id'];
|
||||
if(empty($iOrgnId)){
|
||||
continue;
|
||||
}
|
||||
$aAuthorOrgn[] = ['article_id' => $iArticleId,'organ_id' => $iOrgnId,'art_aut_id' => $value['name']];
|
||||
|
||||
//获取
|
||||
$sOrganName = empty($aCompanyData[$iNewSort]['organ_name']) ? 0 : $aCompanyData[$iNewSort]['organ_name'];
|
||||
if(!empty($sOrganName)){
|
||||
$sOrganName = str_replace([', ',','], ',', $sOrganName);
|
||||
$aOrganName = explode(',',$sOrganName);
|
||||
|
||||
$aCountry[] = empty($aOrganName) ? '' : strtolower(end($aOrganName));
|
||||
}
|
||||
$aAuthorOrgn[] = ['article_id' => $iArticleId,'organ_id' => $iOrgnId,'art_aut_id' => $value['firstname']];
|
||||
}
|
||||
}
|
||||
$value['firstname'] = empty($value['name']) ? '' : trim($value['name']);
|
||||
|
||||
//处理城市
|
||||
$aCountry = empty($aCountry) ? [] : array_unique($aCountry);
|
||||
$value['country'] = '';
|
||||
if(count($aCountry) == 1){
|
||||
$value['country'] = empty($aCountry[0]) ? '' : ucfirst($aCountry[0]);
|
||||
}
|
||||
if(count($aCountry) > 1){
|
||||
// 1. 找到目标值的键名
|
||||
$key = array_search('china', $aCountry);
|
||||
// 2. 确认找到后删除(避免键名为 0 时被误判为 false)
|
||||
if ($key !== false) {
|
||||
unset($aCountry[$key]);
|
||||
}
|
||||
$aCountry = empty($aCountry) ? [] : array_values($aCountry);
|
||||
$value['country'] = empty($aCountry[0]) ? '' : ucfirst($aCountry[0]);
|
||||
}
|
||||
|
||||
//已添加
|
||||
if(!empty($value['firstname']) && in_array($value['firstname'], $aAuthorList)){
|
||||
continue;
|
||||
@@ -281,7 +358,10 @@ class Contribute extends Base
|
||||
$value['email'] = empty($aCorresponding[$value['name']]['email']) ? '' : $aCorresponding[$value['name']]['email'];
|
||||
$value['article_id'] = $iArticleId;
|
||||
unset($value['name'],$value['company_id']);
|
||||
$aAuthorData[$key] = $value;
|
||||
$iMaxSort++;
|
||||
$value['sort'] = $iMaxSort;
|
||||
$value['country'] = empty($value['country']) ? '' : ucfirst(str_replace(['Pr '], '', $value['country']));
|
||||
$aAuthorData[] = $value;
|
||||
}
|
||||
}
|
||||
if(!empty($aAuthorData)){
|
||||
@@ -318,42 +398,31 @@ class Contribute extends Base
|
||||
continue;
|
||||
}
|
||||
$value['art_aut_id'] = $iAuthorId;
|
||||
$value['create_time'] = time();
|
||||
$aAuthorOrgnInsert[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($aAuthorOrgnInsert)){
|
||||
$author_orgn_result = DB::name('article_author_organ')->insertAll($aAuthorOrgnInsert);
|
||||
if(empty($author_orgn_result)){
|
||||
return json_encode(['status' => 3,'msg' => 'Adding article author orgn failed']);
|
||||
}
|
||||
}
|
||||
// //处理上传文件
|
||||
// if(!empty($sFileUrl) && !empty($iUserId)){
|
||||
// $aInsertFile['article_id'] = $iArticleId;
|
||||
// $aInsertFile['user_id'] = $iUserId;
|
||||
// $aInsertFile['username'] = empty($aUser['account']) ? '' : $aUser['account'];
|
||||
// $aInsertFile['file_url'] = trim($sFileUrl,'/');
|
||||
// $aInsertFile['type_name'] = 'manuscirpt';
|
||||
// $aInsertFile['ctime'] = time();
|
||||
// $iFileId = Db::name('article_file')->insertGetId($aInsertFile);
|
||||
// }
|
||||
//处理上传文件
|
||||
|
||||
if(!empty($aInsert['manuscirpt_url']) && !empty($iUserId)){
|
||||
$aInsertFile['article_id'] = $iArticleId;
|
||||
$aInsertFile['user_id'] = $iUserId;
|
||||
$aInsertFile['username'] = empty($aUser['account']) ? '' : $aUser['account'];
|
||||
$aInsertFile['file_url'] = $aInsert['manuscirpt_url'];
|
||||
$aInsertFile['type_name'] = 'manuscirpt';
|
||||
$aInsertFile['ctime'] = time();
|
||||
$iFileId = Db::name('article_file')->insertGetId($aInsertFile);
|
||||
}
|
||||
|
||||
Db::commit();
|
||||
$aInsert['article_id'] = $iArticleId;
|
||||
return json_encode(['status' => 1,'msg' => 'Successfully added article','article' => $aInsert]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文章sn号
|
||||
*/
|
||||
private function getArticleAcceptSn($aParam = [],$sFlag = 'Draft')
|
||||
{
|
||||
$iArticleId = empty($aParam['article_id']) ? 0 : $aParam['article_id'];
|
||||
if(empty($iArticleId)){
|
||||
return '';
|
||||
}
|
||||
$sDate = date('Y');
|
||||
$sType = $sDate;
|
||||
return $sFlag.$sType.str_pad($iArticleId,6,'0',STR_PAD_LEFT).rand(100,999);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1137,4 +1137,59 @@ class Finalreview extends Base
|
||||
}
|
||||
return json_encode(['status' => 1,'msg' => 'success','data' => $aReviewerFinal]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @title 获取文章的终审意见
|
||||
* @param article_id
|
||||
*/
|
||||
public function getRecord($aParam = []){
|
||||
|
||||
//获取参数
|
||||
$aParam = empty($aParam) ? $this->request->post() : $aParam;
|
||||
//参数验证-文章ID
|
||||
$iArticleId = empty($aParam['article_id']) ? 0 : $aParam['article_id'];
|
||||
if(empty($iArticleId)){
|
||||
return json_encode(['status' => 2,'msg' => 'Please select a article']);
|
||||
}
|
||||
|
||||
//查询文章
|
||||
$aWhere = ['article_id' => $iArticleId];
|
||||
$aArticle = Db::name('article')->field('ctime')->where($aWhere)->find();
|
||||
if(empty($aArticle)){
|
||||
return json_encode(['status' => 3,'msg' => 'The query article does not exist']);
|
||||
}
|
||||
//查询终审-审稿记录
|
||||
$aWhere = ['article_id' => $iArticleId,'state' => ['in',[1,2,3]]];
|
||||
$aReviewerFinal = Db::name('article_reviewer_final')->field('reviewer_id')->order('review_time desc')->where($aWhere)->find();
|
||||
//查询审稿人姓名
|
||||
$iUserId = empty($aReviewerFinal['reviewer_id']) ? 0 : $aReviewerFinal['reviewer_id'];
|
||||
if(!empty($iUserId)){
|
||||
$aWhere = ['user_id' => $iUserId,'state' => 0];
|
||||
$aUser = Db::name('user')->field('realname')->where($aWhere)->find();
|
||||
$aReviewerFinal['realname'] = empty($aUser['realname']) ? '' : $aUser['realname'];
|
||||
}
|
||||
|
||||
//获取文章记录
|
||||
$aWhere = ['article_id' => $iArticleId,'state' => 0,'state_to' => ['in',[0,4,5]]];
|
||||
$aArticleMsg = Db::name('article_msg')->field('state_from,state_to,ctime')->where($aWhere)->order('ctime deac')->select();
|
||||
if(!empty($aArticleMsg)){
|
||||
$iReceivedTime = $iRevisionTime = $iAcceptedTime = 0;
|
||||
foreach ($aArticleMsg as $key => $value) {
|
||||
if(empty($iReceivedTime) && $value['state_to'] == 0){
|
||||
$iReceivedTime = $value['ctime'];
|
||||
}
|
||||
if(empty($iRevisionTime) && $value['state_to'] == 4){
|
||||
$iRevisionTime = $value['ctime'];
|
||||
}
|
||||
if(empty($iAcceptedTime) && $value['state_to'] == 5){
|
||||
$iAcceptedTime = $value['ctime'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$iReceivedTime = empty($iReceivedTime) ? $aArticle['ctime'] : $iReceivedTime;
|
||||
$aReviewerFinal['received_time'] = empty($iReceivedTime) ? '' :date('Y-m-d H:i:s',$iReceivedTime);
|
||||
$aReviewerFinal['revision_time'] = empty($iRevisionTime) ? '' :date('Y-m-d H:i:s',$iRevisionTime);
|
||||
$aReviewerFinal['accepted_time'] = empty($iAcceptedTime) ? '' :date('Y-m-d H:i:s',$iAcceptedTime);
|
||||
return json_encode(['status' => 1,'msg' => 'success','data' => $aReviewerFinal]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,7 +481,8 @@ class Production extends Base
|
||||
'acknowledgment' => 'require',
|
||||
'keywords' => 'require',
|
||||
'author_contribution' => 'require',
|
||||
'abbr' => 'require'
|
||||
'abbr' => 'require',
|
||||
'abstract' => 'require'
|
||||
]);
|
||||
if (!$rule->check($data)) {
|
||||
return jsonError($rule->getError());
|
||||
@@ -521,7 +522,7 @@ class Production extends Base
|
||||
// $update['doi'] = $doi;
|
||||
|
||||
|
||||
|
||||
$update['abstract'] = isset($data['abstract']) ? trim($data['abstract']) : '';
|
||||
$this->production_article_obj->where('p_article_id', $data['p_article_id'])->update($update);
|
||||
return jsonSuccess($update);
|
||||
}
|
||||
@@ -664,14 +665,16 @@ class Production extends Base
|
||||
$data = $this->request->post();
|
||||
$rule = new Validate([
|
||||
'p_article_id' => 'require|number',
|
||||
'abstract' => 'require',
|
||||
// 'abstract' => 'require',
|
||||
'doi' => 'require',
|
||||
'pub_date' => 'require'
|
||||
]);
|
||||
if (!$rule->check($data)) {
|
||||
return jsonError($rule->getError());
|
||||
}
|
||||
$updata['abstract'] = trim($data['abstract']);
|
||||
if(isset($data['abstract'])){
|
||||
$updata['abstract'] = trim($data['abstract']);
|
||||
}
|
||||
$updata['doi'] = $data['doi'];
|
||||
$updata['pub_date'] = $data['pub_date'];
|
||||
$this->production_article_obj->where('p_article_id', $data['p_article_id'])->update($updata);
|
||||
@@ -1807,8 +1810,8 @@ private function escapeLatexText($text)
|
||||
$typesetInfo['images'] = null;
|
||||
$typesetInfo['tables'] = null;
|
||||
|
||||
// $url = $this->ts_base_url."api/typeset/createDocx";
|
||||
$url = "http://192.168.110.110:8081/typeset/createDocx";
|
||||
$url = $this->ts_base_url."api/typeset/createDocx";
|
||||
// $url = "http://192.168.110.110:8081/typeset/createDocx";
|
||||
// $url = "http://192.168.110.110:8081/typeset/testqt";
|
||||
$res = object_to_array(json_decode(myPost1($url, $typesetInfo)));
|
||||
|
||||
|
||||
@@ -184,10 +184,26 @@ class Reviewer extends Base
|
||||
// ->order('t_article_reviewer.state')
|
||||
->limit($limit_start, $data['pageSize'])
|
||||
->select();
|
||||
|
||||
//查询复审记录 chengxiaoling 20251110 start
|
||||
$aReviewerRepeatLists = [];
|
||||
if(!empty($res)){
|
||||
//查询复审
|
||||
$aArtRevId = array_column($res, 'art_rev_id');
|
||||
$aWhere = ['art_rev_id' => ['in',$aArtRevId],'recommend' => ['between',[1,3]]];
|
||||
$aReviewerRepeat = Db::name('article_reviewer_repeat')->field('art_rev_rep_id,art_rev_id,recommend,ctime,stime')->where($aWhere)->select();
|
||||
if(!empty($aReviewerRepeat)){
|
||||
foreach ($aReviewerRepeat as $key => $value) {
|
||||
$aReviewerRepeatLists[$value['art_rev_id']][] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
//查询复审记录 chengxiaoling 20251110 end
|
||||
foreach ($res as $k => $v) {
|
||||
if ($v['type']) {
|
||||
$res[$k]['type'] = translateType($v['type']);
|
||||
}
|
||||
$res[$k]['repeat'] = empty($aReviewerRepeatLists[$v['art_rev_id']]) ? [] : $aReviewerRepeatLists[$v['art_rev_id']];
|
||||
}
|
||||
|
||||
//加上文章领域
|
||||
@@ -968,12 +984,12 @@ class Reviewer extends Base
|
||||
//生成pdf文件
|
||||
// $reviewer_pdf = self::pdftest($journal_info['title']);
|
||||
$reviewer_ZS = self::createReviewerZS($data['art_rev_id']);
|
||||
|
||||
$sArticleSn = empty($article_info['accept_sn']) ? '' : $article_info['accept_sn'];
|
||||
//发送email->编辑
|
||||
$tt = 'Dear editor,<br>';
|
||||
$tt .= 'Please check the new comments from the reviewer.<br>';
|
||||
$tt .= 'Journal:' . $journal_info['title'] . ' and article title:' . $article_info['title'];
|
||||
|
||||
$tt .= '<br>sn:'.$sArticleSn;
|
||||
$sendEditor = [
|
||||
'title' => $journal_info['title'], // 邮件标题
|
||||
'content' => $tt, //邮件内容
|
||||
@@ -2631,10 +2647,11 @@ class Reviewer extends Base
|
||||
$reviewer_ZS = self::createReviewerZS($data['art_rev_id']);
|
||||
|
||||
//发送email->编辑
|
||||
$sArticleSn = empty($article_info['accept_sn']) ? '' : $article_info['accept_sn'];
|
||||
$tt = 'Dear editor,<br>';
|
||||
$tt .= 'Please check the new comments from the reviewer.sn:'.$article_info['accept_sn'].'<br>';
|
||||
$tt .= 'Please check the new comments from the reviewer.<br>';
|
||||
$tt .= 'Journal:' . $journal_info['title'] . ' and article title:' . $article_info['title'];
|
||||
|
||||
$tt .= '<br>sn:'.$sArticleSn;
|
||||
$sendEditor = [
|
||||
'title' => $journal_info['title'], // 邮件标题
|
||||
'content' => $tt, //邮件内容
|
||||
|
||||
@@ -163,6 +163,14 @@ class Ucenter extends Base{
|
||||
if($check){
|
||||
return jsonError("Your application for Editorial Board is processing. Please do not repeat it.");
|
||||
}
|
||||
|
||||
//判断是否上传CV
|
||||
$aWhere = ['user_id' => $data['user_id'],'state' => 0];
|
||||
$aCv = $this->user_cv_obj->field('user_cv_id')->where($aWhere)->find();
|
||||
if(empty($aCv)){
|
||||
return jsonError("Please upload CV");
|
||||
}
|
||||
|
||||
$insert['user_id'] = $data['user_id'];
|
||||
$insert['journal_id'] = $data['journal_id'];
|
||||
$insert['ctime'] = time();
|
||||
|
||||
@@ -3133,4 +3133,167 @@ class User extends Base
|
||||
die;
|
||||
// return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
public function getUser(){
|
||||
//获取参数
|
||||
$aParam = empty($aParam) ? $this->request->post() : $aParam;
|
||||
|
||||
//获取用户ID
|
||||
$iUserId = empty($aParam['user_id']) ? 0 : $aParam['user_id'];
|
||||
if(empty($iUserId)){
|
||||
return json_encode(['status' => 2,'msg' => 'Please select the user']);
|
||||
}
|
||||
|
||||
//获取主信息
|
||||
$aWhere = ['user_id' => $iUserId,'state' => 0];
|
||||
$aUser = Db::name('user')->field('user_id,account,email,phone,realname')->where($aWhere)->find();
|
||||
if(empty($aUser)){
|
||||
return json_encode(['status' => 2,'msg' => 'User does not exist','data' => []]);
|
||||
}
|
||||
|
||||
//查询用户CV
|
||||
$aCv = Db::name('user_cv')->field('user_cv_id,cv,ctime')->where($aWhere)->select();
|
||||
$aUser['cv'] = empty($aCv) ? [] : $aCv;
|
||||
|
||||
//获取附属信息
|
||||
$aWhere = ['reviewer_id' => $iUserId,'state' => 0];
|
||||
$aUserInfo = Db::name('user_reviewer_info')->field('technical,country,introduction,company,website,field')->where($aWhere)->find();
|
||||
if(!empty($aUserInfo)){
|
||||
$aUser += $aUserInfo;
|
||||
}
|
||||
return json_encode(['status' => 1,'data' => $aUser]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同意青年科学家申请
|
||||
*/
|
||||
public function agreeYboardApplyNew(){
|
||||
//获取参数
|
||||
$data = empty($aParam) ? $this->request->post() : $aParam;
|
||||
//必填信息验证
|
||||
$aField = ['ap_yboard_id','year','realname','technical','country','field','company'];
|
||||
$sMsg = '';
|
||||
|
||||
$aUserUpdate = $aUserReviewer = [];
|
||||
foreach ($aField as $key => $value) {
|
||||
if(empty($data[$value])){
|
||||
$sMsg = 'Incomplete information';
|
||||
break;
|
||||
}
|
||||
if(!in_array($value, ['ap_yboard_id','year','realname'])){
|
||||
$aUserReviewer[$value] = $data[$value];
|
||||
}
|
||||
if($value == 'realname'){
|
||||
$aUser['realname'] = $data[$value];
|
||||
}
|
||||
}
|
||||
if(!empty($sMsg)){
|
||||
return jsonError($sMsg);
|
||||
}
|
||||
|
||||
//查询申请记录
|
||||
$start_time = time();
|
||||
$app_info = $this->apply_yboard_obj->where('ap_yboard_id',$data['ap_yboard_id'])->find();
|
||||
if(empty($app_info)){
|
||||
return jsonError('No application record found');
|
||||
}
|
||||
$user_info = $this->user_obj->where('user_id',$app_info['user_id'])->find();
|
||||
if(empty($user_info)){
|
||||
return jsonError('Basic user information not found');
|
||||
}
|
||||
//获取期刊信息
|
||||
$journal_info = $this->journal_obj->where('journal_id',$app_info['journal_id'])->find();
|
||||
if(empty($journal_info)){
|
||||
return jsonError('No journal information found or journal closed');
|
||||
}
|
||||
//查询是否申请过
|
||||
$check = $this->user_to_yboard_obj->where('user_id',$app_info['user_id'])->where('journal_id',$app_info['journal_id'])->where('start_date',"<=",$start_time)->where('end_date',">=",$start_time)->where('state',0)->find();
|
||||
if($check){
|
||||
return jsonError("Already exists");
|
||||
}
|
||||
|
||||
//数据处理组装
|
||||
if(isset($data['phone'])){
|
||||
$aUser['phone'] = $data['phone'];
|
||||
}
|
||||
if(isset($data['website'])){
|
||||
$aUserReviewer['website'] = $data['website'];
|
||||
}
|
||||
if(isset($data['introduction'])){
|
||||
$aUserReviewer['introduction'] = $data['introduction'];
|
||||
}
|
||||
|
||||
|
||||
Db::startTrans();
|
||||
//更新用户表user
|
||||
if(!empty($aUser)){
|
||||
$aWhere = ['user_id' => $app_info['user_id']];
|
||||
$user_result = Db::name('user')->where($aWhere)->limit(1)->update($aUser);
|
||||
}
|
||||
//更新用户附属表user_reviewer_info
|
||||
if(!empty($aUserReviewer)){
|
||||
$aWhere = ['reviewer_id' => $app_info['user_id']];
|
||||
$aUserReviewerInfo = Db::name('user_reviewer_info')->field('reviewer_id')->where($aWhere)->find();
|
||||
if(empty($aUserReviewerInfo)){
|
||||
$user_reviewer_result = Db::name('user_reviewer_info')->insert($aUserReviewer);
|
||||
}
|
||||
if(!empty($aUserReviewerInfo)){
|
||||
$user_reviewer_result = Db::name('user_reviewer_info')->where($aWhere)->limit(1)->update($aUserReviewer);
|
||||
}
|
||||
}
|
||||
$icon = self::createYboardCert($user_info,$journal_info,$start_time,$data['year']);
|
||||
$insert['user_id'] = $app_info['user_id'];
|
||||
$insert['journal_id'] = $app_info['journal_id'];
|
||||
$insert['start_date'] = $start_time;
|
||||
$insert['end_date'] = strtotime("+ ".$data['year']." year",$start_time);
|
||||
$insert['icon'] = $icon;
|
||||
$insert['ctime'] = $start_time;
|
||||
$this->user_to_yboard_obj->insert($insert);
|
||||
$this->apply_yboard_obj->where('ap_yboard_id',$data['ap_yboard_id'])->update(['state'=>1]);
|
||||
//同意成为青年科学家后,将其添加到审稿人
|
||||
$check_reviewer = $this->reviewer_to_journal_obj->where('journal_id',$app_info['journal_id'])->where('reviewer_id',$app_info['user_id'])->find();
|
||||
if(!$check_reviewer){//如果不存在那么添加审稿人到对应期刊下面
|
||||
$insert_reviewer['reviewer_id'] = $app_info['user_id'];
|
||||
$insert_reviewer['journal_id'] = $app_info['journal_id'];
|
||||
$insert_reviewer['account'] = $user_info['account'];
|
||||
$insert_reviewer['journal_title'] = $journal_info['title'];
|
||||
$insert_reviewer['ctime'] = time();
|
||||
$this->reviewer_to_journal_obj->insert($insert_reviewer);
|
||||
}
|
||||
Db::commit();
|
||||
|
||||
//发送邮件提醒用户//发送邮件给用户
|
||||
$realname = empty($data['realname']) ? $user_info['realname'] : $data['realname'];
|
||||
$dd = "Dear Dr. ".$realname.",<br/><br/>";
|
||||
$dd .= "It is my great pleasure to extend my warmest congratulations to you on being selected as a Young Scientist Board Member for <i>".$journal_info['title']."</i> Journal.<br/><br/>";
|
||||
$dd .= "As a member of the Young Scientist Board, you will be an integral part of the peer-review process and will play a crucial role in ensuring the quality and rigor of the journal's content. Your contributions will be invaluable in shaping the direction of the journal and advancing scholarship in your field.<br/><br/>";
|
||||
$dd .= "You can download the Young Scientist Board certificate from the personal center system: https://submission.tmrjournals.com/<br/><br/>";
|
||||
$dd .= "The rights and duties of the members of the Young Scientist Board are as follows:<br/><br/>";
|
||||
$dd .= "Rights:<br/><br/>";
|
||||
$dd .= "1. Electronic Certificate: As a Young Scientist Board Member, you will receive an electronic certificate to acknowledge your position in our publication.<br/>";
|
||||
$dd .= "2. Opportunity for Advancement: Outstanding Youth Editorial Board Members may be considered as potential candidates for the Editorial Board.<br/>";
|
||||
$dd .= "3. Special Issues: You will have the opportunity to apply for a special Issue to expand your influence and that of your team.<br/><br/>";
|
||||
$dd .= "Obligations:<br/><br/>";
|
||||
$dd .= "1. Peer Review: As a Youth Scientist Board Member, you will be required to review and assess 3-5 manuscripts per year, based on your area of research.<br/>";
|
||||
$dd .= "2. Active Promotion: You should actively promote our publication in your academic and professional circles and recommend quality manuscripts to scholars in your network.<br/>";
|
||||
$dd .= "3. Provide Feedback: You should provide constructive feedback and suggestions to improve the direction and style of our publication. If feasible, you may also attend small forums or conferences to represent our publication.<br/><br/>";
|
||||
$dd .= "We look forward to working with you and benefiting from your insights, expertise, and dedication. We are confident that your contributions will make a significant impact on the journal and the academic community as a whole.<br/><br/>";
|
||||
$dd .= "Once again, congratulations on your appointment as a Young Scientist Board Member for <i>".$journal_info['title']."</i>. We are honored to have you on board and look forward to collaborating with you.<br/><br/>";
|
||||
$dd .= 'Sincerely,<br>Editorial Office<br>';
|
||||
$dd .= $journal_info['title'] . '<br>';
|
||||
$dd .= 'Email: ' . $journal_info['email'] . '<br>';
|
||||
$dd .= 'Website: ' . $journal_info['website'] . '<br>';
|
||||
|
||||
$maidata['email'] = $user_info['email'];
|
||||
$maidata['title'] = $journal_info['title'];
|
||||
$maidata['content'] = $dd;
|
||||
$maidata['tmail'] = $journal_info['email'];
|
||||
$maidata['tpassword'] = $journal_info['epassword'];
|
||||
Queue::push('app\api\job\mail@fire', $maidata, "tmail");
|
||||
|
||||
return jsonSuccess([]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ class ArticleParserService
|
||||
public function __construct($filePath = '')
|
||||
{
|
||||
if (!file_exists($filePath)) {
|
||||
throw new Exception("文档不存在:{$filePath}");
|
||||
return json_encode(['status' => 5, 'msg' => '"文档不存在:{$filePath}"']);
|
||||
}
|
||||
try {
|
||||
// 关键配置:关闭“仅读数据”,保留完整节结构
|
||||
@@ -32,11 +32,162 @@ class ArticleParserService
|
||||
// $this->log("✅ 文档直接加载成功,节数量:{$sectionCount}");
|
||||
$this->phpWord = $reader->load($filePath);
|
||||
$this->sections = $this->phpWord->getSections();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return json(['status' => 'error', 'msg' => $e->getMessage()]);
|
||||
// 预处理:移除 DOCX 中的 EMF 图片
|
||||
$processedFilePath = $this->removeEmfFromDocx($filePath);
|
||||
// 加载处理后的文档
|
||||
$reader = IOFactory::createReader();
|
||||
$reader->setReadDataOnly(false);
|
||||
Settings::setCompatibility(false);
|
||||
Settings::setOutputEscapingEnabled(true);
|
||||
|
||||
$this->phpWord = $reader->load($processedFilePath);
|
||||
$this->sections = $this->phpWord->getSections();
|
||||
|
||||
// 可选:删除临时处理文件(避免冗余)
|
||||
unlink($processedFilePath);
|
||||
return json_encode(['status' => 5, 'msg' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 移除 DOCX 压缩包内的所有 EMF 图片
|
||||
* @param string $docxPath 原 DOCX 文件路径
|
||||
* @return string 处理后的临时 DOCX 路径
|
||||
*/
|
||||
private function removeEmfFromDocx($docxPath){
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($docxPath) !== true) {
|
||||
throw new \Exception("无法打开 DOCX 文件:{$docxPath}");
|
||||
}
|
||||
|
||||
// 1. 创建临时目录用于解压
|
||||
$tempDir = rtrim(ROOT_PATH,'/').'/runtime/'.uniqid('docx_temp_');
|
||||
|
||||
mkdir($tempDir, 0700, true);
|
||||
|
||||
// 2. 解压 DOCX 到临时目录
|
||||
$zip->extractTo($tempDir);
|
||||
$zip->close();
|
||||
|
||||
// 3. 递归删除所有 EMF 文件
|
||||
$dirIterator = new RecursiveDirectoryIterator($tempDir);
|
||||
$iterator = new RecursiveIteratorIterator($dirIterator);
|
||||
foreach ($iterator as $file) {
|
||||
if ($file->isFile() && strtolower(pathinfo($file, PATHINFO_EXTENSION)) === 'emf') {
|
||||
unlink($file->getPathname());
|
||||
}
|
||||
}
|
||||
// 4. 重新打包为 DOCX
|
||||
$processedPath = $tempDir . '_processed.docx';
|
||||
$newZip = new ZipArchive();
|
||||
if ($newZip->open($processedPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
|
||||
throw new \Exception("无法创建处理后的 DOCX 文件");
|
||||
}
|
||||
|
||||
// 遍历临时目录,添加所有文件到新压缩包
|
||||
$this->addFilesToZip($tempDir, $newZip);
|
||||
$newZip->close();
|
||||
|
||||
// 5. 删除临时解压目录
|
||||
$this->deleteDir($tempDir);
|
||||
|
||||
return $processedPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归添加目录文件到 ZipArchive
|
||||
* @param string $dir 目录路径
|
||||
* @param ZipArchive $zip ZipArchive 实例
|
||||
*/
|
||||
private function addFilesToZip($dir, $zip)
|
||||
{
|
||||
$files = scandir($dir);
|
||||
foreach ($files as $file) {
|
||||
if ($file === '.' || $file === '..') continue;
|
||||
|
||||
$filePath = $dir . '/' . $file;
|
||||
if (is_dir($filePath)) {
|
||||
$this->addFilesToZip($filePath, $zip);
|
||||
} else {
|
||||
// 计算压缩包内的相对路径(避免冗余目录层级)
|
||||
$relativePath = str_replace(dirname($dir) . '/', '', $filePath);
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归删除目录
|
||||
* @param string $dir 目录路径
|
||||
*/
|
||||
private function deleteDir($dir){
|
||||
// 1. 基础校验:非空字符串且为有效目录
|
||||
if (trim($dir) === '' || !is_dir($dir)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 统一路径格式(去除尾部分隔符,避免跨系统差异)
|
||||
$dir = rtrim($dir, DIRECTORY_SEPARATOR);
|
||||
$dirName = basename($dir);
|
||||
|
||||
// 3. 前缀强校验:仅处理docx_temp_开头的目录
|
||||
if (strpos($dirName, 'docx_temp_') !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. 路径归属校验(缓存realpath结果,减少I/O)
|
||||
$runtimeDir = rtrim(ROOT_PATH, '/') . '/runtime';
|
||||
$realDir = realpath($dir);
|
||||
$realRuntimeDir = realpath($runtimeDir);
|
||||
if ($realDir === false || $realRuntimeDir === false || strpos($realDir, $realRuntimeDir) !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5. 扫描目录(带错误抑制,处理权限问题)
|
||||
$files = @scandir($dir);
|
||||
if ($files === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$isFullyDeleted = true; // 标记是否完全删除
|
||||
|
||||
// 6. 递归处理子项
|
||||
foreach ($files as $file) {
|
||||
if ($file === '.' || $file === '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$filePath = $dir . DIRECTORY_SEPARATOR . $file;
|
||||
$realFilePath = realpath($filePath);
|
||||
|
||||
// 子路径校验:必须是当前目录的子项(防符号链接跳转)
|
||||
if ($realFilePath === false || strpos($realFilePath, $realDir) !== 0) {
|
||||
$isFullyDeleted = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_dir($realFilePath)) {
|
||||
// 递归删除子目录,继承校验逻辑
|
||||
if (!$this->deleteDir($realFilePath)) {
|
||||
$isFullyDeleted = false;
|
||||
}
|
||||
} else {
|
||||
// 尝试删除文件(失败则标记未完全删除)
|
||||
if (!@unlink($realFilePath)) {
|
||||
$isFullyDeleted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 7. 最终删除目录(确保空目录才删除)
|
||||
$remainingFiles = @scandir($dir);
|
||||
if ($remainingFiles !== false && count($remainingFiles) <= 2) {
|
||||
@rmdir($dir);
|
||||
return $isFullyDeleted; // 若子项完全删除,则返回true
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 上传并解析文档的入口方法
|
||||
public static function uploadAndParse($sFileUrl){
|
||||
@@ -80,9 +231,11 @@ class ArticleParserService
|
||||
|
||||
// 提取文章标题
|
||||
private function getTitle(){
|
||||
if(empty($this->sections)){
|
||||
return '';
|
||||
}
|
||||
$title = '';
|
||||
$maxLength = 0;
|
||||
|
||||
foreach ($this->sections as $section) {
|
||||
foreach ($section->getElements() as $element) {
|
||||
$text = $this->getTextFromElement($element);
|
||||
@@ -94,6 +247,9 @@ class ArticleParserService
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!empty($title) && !mb_check_encoding($title, 'UTF-8')){
|
||||
$title = mb_convert_encoding($title, 'UTF-8', 'GBK');
|
||||
}
|
||||
return $title;
|
||||
}
|
||||
// 提取作者
|
||||
@@ -260,6 +416,168 @@ class ArticleParserService
|
||||
// var_dump($aAuthorData);exit;
|
||||
// return ['author' => $aAuthorData,'report' => array_unique($aReport)];
|
||||
// }
|
||||
|
||||
// 提取作者
|
||||
private function parseAuthorsWithoutRegex($str = '') {
|
||||
if (empty($str)) {
|
||||
return [];
|
||||
}
|
||||
// 清理乱码和特殊字符(扩展全角数字处理)
|
||||
$str = mb_convert_encoding($str, 'UTF-8', 'auto');
|
||||
$str = str_replace(["\xC2\xA0", 'ï¼', '�', ',', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
|
||||
[' ', ' ', ' ', ' ', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], $str);
|
||||
$str = trim(str_replace([' and ', ' AND ', ' And '], ', ', $str));
|
||||
|
||||
// 合并上标中数字与逗号间的空格(如"2, 3"→"2,3")
|
||||
$len = mb_strlen($str);
|
||||
$processed = '';
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$char = mb_substr($str, $i, 1);
|
||||
if ($char === ',' && $i - 1 >= 0 && $i + 2 < $len) {
|
||||
$prevChar = mb_substr($str, $i - 1, 1);
|
||||
$next1 = mb_substr($str, $i + 1, 1);
|
||||
$next2 = mb_substr($str, $i + 2, 1);
|
||||
// 兼容全角数字转半角后的判断
|
||||
if ((ctype_digit($prevChar) || is_numeric($prevChar)) && $next1 === ' ' && (ctype_digit($next2) || is_numeric($next2))) {
|
||||
$processed .= $char;
|
||||
$i += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$processed .= $char;
|
||||
}
|
||||
$str = $processed;
|
||||
|
||||
// 合并数字与符号间的空格(如"1 *"→"1*")
|
||||
$len = mb_strlen($str);
|
||||
$processed = '';
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$char = mb_substr($str, $i, 1);
|
||||
if ((ctype_digit($char) || is_numeric($char)) && $i + 2 < $len) { // 支持数字判断
|
||||
$next1 = mb_substr($str, $i + 1, 1);
|
||||
$next2 = mb_substr($str, $i + 2, 1);
|
||||
if ($next1 === ' ' && in_array($next2, ['#', '*', '†', '‡', '§'])) { // 扩展符号支持
|
||||
$processed .= $char;
|
||||
$i += 2;
|
||||
$processed .= $next2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$processed .= $char;
|
||||
}
|
||||
$str = $processed;
|
||||
|
||||
// 合并连续空格
|
||||
$len = mb_strlen($str);
|
||||
$processed = '';
|
||||
$prevSpace = false;
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$char = mb_substr($str, $i, 1);
|
||||
if ($char === ' ') {
|
||||
if (!$prevSpace) {
|
||||
$processed .= $char;
|
||||
$prevSpace = true;
|
||||
}
|
||||
} else {
|
||||
$processed .= $char;
|
||||
$prevSpace = false;
|
||||
}
|
||||
}
|
||||
$str = trim($processed);
|
||||
|
||||
// 作者处理
|
||||
$authors = [];
|
||||
$currentName = '';
|
||||
$currentSuperscript = '';
|
||||
$inName = true;
|
||||
$len = mb_strlen($str);
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$char = mb_substr($str, $i, 1);
|
||||
|
||||
// 处理作者分隔符:逗号+空格
|
||||
if ($char === ',' && $i + 1 < $len) {
|
||||
$nextChar = mb_substr($str, $i + 1, 1);
|
||||
if ($nextChar === ' ') {
|
||||
if (!empty($currentName)) {
|
||||
$currentSuperscript = rtrim($currentSuperscript, ',');
|
||||
$authors[] = [
|
||||
'name' => trim($currentName),
|
||||
'superscript' => trim($currentSuperscript)
|
||||
];
|
||||
}
|
||||
$currentName = '';
|
||||
$currentSuperscript = '';
|
||||
$inName = true;
|
||||
$i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 支持姓名中的点、连字符、特殊字母(如带重音的字母)
|
||||
if (ctype_alpha($char) || in_array($char, [' ', '.', '-', 'à', 'á', 'â', 'ã', 'ä', 'ç', 'è', 'é', 'ê', 'ë'])) {
|
||||
if ($inName) {
|
||||
$currentName .= $char;
|
||||
} else {
|
||||
$currentSuperscript = rtrim($currentSuperscript, ',');
|
||||
$authors[] = [
|
||||
'name' => trim($currentName),
|
||||
'superscript' => trim($currentSuperscript)
|
||||
];
|
||||
$currentName = $char;
|
||||
$currentSuperscript = '';
|
||||
$inName = true;
|
||||
}
|
||||
}
|
||||
// 解析上标(数字、逗号、#、*、†等)
|
||||
elseif ((ctype_digit($char) || is_numeric($char)) || in_array($char, ['#', '*', '†', ',', '‡', '§'])) {
|
||||
$inName = false;
|
||||
$currentSuperscript .= $char;
|
||||
}
|
||||
// 忽略其他字符
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理最后一个作者
|
||||
if (!empty($currentName)) {
|
||||
$currentSuperscript = rtrim($currentSuperscript, ',');
|
||||
$authors[] = [
|
||||
'name' => trim($currentName),
|
||||
'superscript' => trim($currentSuperscript)
|
||||
];
|
||||
}
|
||||
|
||||
// 提取机构编号为数组、判断通讯作者和第一作者
|
||||
foreach ($authors as $index => &$author) {
|
||||
// 提取机构编号(兼容多字节数字)
|
||||
$institutionIds = [];
|
||||
$superscript = $author['superscript'];
|
||||
$numStr = '';
|
||||
for ($i = 0; $i < mb_strlen($superscript); $i++) {
|
||||
$c = mb_substr($superscript, $i, 1);
|
||||
if (ctype_digit($c) || is_numeric($c)) { // 支持数字判断
|
||||
$numStr .= $c;
|
||||
} else {
|
||||
if (!empty($numStr)) {
|
||||
$institutionIds[] = (int)$numStr;
|
||||
$numStr = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($numStr)) {
|
||||
$institutionIds[] = (int)$numStr;
|
||||
}
|
||||
$institutionIds = array_values(array_unique($institutionIds));
|
||||
$author['company_id'] = $institutionIds;
|
||||
|
||||
// 判断第一作者(#标记)和通讯作者(*、†标记)
|
||||
$author['is_super'] = strpos($superscript, '#') !== false ? 1 : 0;
|
||||
$author['is_report'] = (strpos($superscript, '*') !== false || strpos($superscript, '†') !== false) ? 1 : 0;
|
||||
}
|
||||
unset($author); // 释放引用
|
||||
return $authors;
|
||||
}
|
||||
private function getAuthors($aParam = []) {
|
||||
$title = empty($aParam['title']) ? $this->getTitle() : $aParam['title'];
|
||||
$sAuthorContent = $this->getNextParagraphAfterText($title);
|
||||
@@ -291,95 +609,195 @@ class ArticleParserService
|
||||
$sAuthorContent = preg_replace('/\s+and\s+/i', ', ', $sAuthorContent); // and转逗号
|
||||
$sAuthorContent = preg_replace('/\s+/', ' ', $sAuthorContent); // 合并多余空格
|
||||
$sAuthorContent = trim($sAuthorContent);
|
||||
|
||||
// 处理作者
|
||||
$content = mb_convert_encoding($sAuthorContent, 'UTF-8', 'auto'); // 确保编码正确
|
||||
$content = str_replace("\xC2\xA0", ' ', $content); // 替换非-breaking空格为普通空格
|
||||
$content = preg_replace('/(\d+)\s*([*#†])/', '$1$2', $content); // 合并"1 *"为"1*"、"1 #"为"1#"
|
||||
$content = preg_replace('/,†/', ',†', $content); // 保留"1,†"格式(防止被拆分)
|
||||
//标记上标内的逗号+空格(多编号)
|
||||
$tempStr = preg_replace('/(\d+)\s*,\s*(\d+)/', '$1<SEP>$2', $content);
|
||||
// 原有步骤2:正则匹配(扩展上标符号支持,保持原有逻辑)
|
||||
$pattern = '/
|
||||
([A-Za-z\s\.\-]+?) # 姓名(支持缩写、空格)
|
||||
\s* # 姓名与上标间空格
|
||||
( # 上标组(扩展符号支持)
|
||||
\d+ # 起始数字
|
||||
(?:[†#*,]|<SEP>\d+)* # 允许:†#*符号、逗号、<SEP>+数字(兼容1,†、1,*等)
|
||||
)
|
||||
\s*,? # 作者间逗号(可选)
|
||||
(?=\s|$) # 确保后面是空格或结尾
|
||||
/ux';
|
||||
|
||||
preg_match_all($pattern, $tempStr, $matches);
|
||||
$authorList = [];
|
||||
if(!empty($matches[1])){
|
||||
foreach ($matches[1] as $i => $name) {
|
||||
$name = trim($name);
|
||||
$superscript = trim($matches[2][$i]);
|
||||
$superscript = str_replace('<SEP>', ',', $superscript); // 恢复多编号逗号
|
||||
$superscript = preg_replace('/,$/', '', $superscript); // 清理末尾逗号
|
||||
// 修复符号与数字间的空格(如原始"1 *"被误处理为"1*"的情况,保持原样)
|
||||
$superscript = preg_replace('/(\d)([*#†])/', '$1$2', $superscript);
|
||||
if (!empty($name)) {
|
||||
$authorList[] = [
|
||||
'name' => $name,
|
||||
'superscript' => $superscript
|
||||
];
|
||||
}
|
||||
}
|
||||
}else {
|
||||
// 按“两个或多个连续空格”拆分(姓名之间的分隔)
|
||||
$authorList = array_filter(
|
||||
array_map('trim',
|
||||
preg_split('/(,\p{Z}*|\p{Z}{2,})/u', $sAuthorContent)
|
||||
)
|
||||
);
|
||||
$aAuthor = $this->parseAuthorsWithoutRegex($sAuthorContent);
|
||||
if(empty($aAuthor)){
|
||||
return ['author' => [],'report' => []];
|
||||
}
|
||||
$aReport = $aAuthorData = [];
|
||||
|
||||
|
||||
// //处理作者
|
||||
$aAuthorData = [];
|
||||
$aReport = [];
|
||||
$namePattern = '/
|
||||
(?:[A-Za-z\s·\-\']+| # 英文姓名(支持空格、连字符)
|
||||
[\x{4e00}-\x{9fa5}]+| # 中文姓名
|
||||
[\x{1800}-\x{18AF}]+| # 蒙古文姓名
|
||||
[A-Z]\.) # 单字母缩写(如 J.)
|
||||
/ux';
|
||||
|
||||
foreach ($authorList as $authorStr){
|
||||
if (empty($authorStr)) continue;
|
||||
|
||||
//获取下标
|
||||
$superscript = empty($authorStr['superscript']) ? $authorStr : $authorStr['superscript'];
|
||||
$nameStr = empty($authorStr['name']) ? $authorStr : $authorStr['name'];
|
||||
|
||||
$companyId = [];
|
||||
$isSuper = 0;
|
||||
$isReport = 0;
|
||||
if (!empty($superscript)) {
|
||||
// 提取机构编号(忽略上标中的逗号,如1,† → 提取1)
|
||||
preg_match_all('/\d+/', $superscript, $numMatch);
|
||||
// 识别特殊符号(#为超级作者,*†为通讯作者)
|
||||
$isSuper = strpos($superscript, '#') !== false ? 1 : 0;
|
||||
$isReport = (strpos($superscript, '*') !== false || strpos($superscript, '†') !== false) ? 1 : 0;
|
||||
foreach ($aAuthor as $key => $value) {
|
||||
if(empty($value['name']) && empty($value['superscript'])){
|
||||
continue;
|
||||
}
|
||||
if (preg_match("/^([A-Za-z\s'\.-]+)/u", $nameStr, $match)) {
|
||||
$nameStr = trim($match[1]);
|
||||
if(!mb_check_encoding($value['name'], 'UTF-8')){
|
||||
$value['name'] = mb_convert_encoding($value['name'], 'UTF-8', 'GBK');
|
||||
}
|
||||
$aAuthorData[] = [
|
||||
'name' => $nameStr,
|
||||
'company_id' => empty($numMatch[0]) ? [] : $numMatch[0],
|
||||
'is_super' => $isSuper,
|
||||
'is_report' => $isReport
|
||||
];
|
||||
if ($isReport) {
|
||||
$aReport[] = $nameStr;
|
||||
if(!empty($value['name']) && !empty($value['is_report']) && $value['is_report'] == 1){
|
||||
$aReport[] = $value['name'];
|
||||
}
|
||||
$aAuthorData[] = $value;
|
||||
}
|
||||
return ['author' => $aAuthorData,'report' => array_unique($aReport)];
|
||||
}
|
||||
// private function getAuthors($aParam = []) {
|
||||
// $title = empty($aParam['title']) ? $this->getTitle() : $aParam['title'];
|
||||
// $sAuthorContent = $this->getNextParagraphAfterText($title);
|
||||
// if (empty($sAuthorContent)) {
|
||||
// return ['author' => [], 'report' => []];
|
||||
// }
|
||||
|
||||
// //编码修复
|
||||
// $possibleEncodings = [
|
||||
// 'Windows-1252', 'UTF-8', 'GBK', 'GB2312',
|
||||
// 'Latin-1', 'ISO-8859-1', 'CP1252'
|
||||
// ];
|
||||
// $encodedContent = @mb_convert_encoding($sAuthorContent, 'UTF-8', implode(',', $possibleEncodings));
|
||||
// $sAuthorContent = $encodedContent ?: $sAuthorContent;
|
||||
|
||||
// //清理不可见字符
|
||||
// $sAuthorContent = preg_replace('/[\x00-\x1F\x7F\x{200B}-\x{200F}]/u', '', $sAuthorContent);
|
||||
|
||||
// //修复特殊符号乱码
|
||||
// $symbolMap = [
|
||||
// '†' => '†', 'â ' => '†', 'â' => '†', '?†' => '†',
|
||||
// ':' => ':', ',' => ',', '—' => '-',
|
||||
// '啊' => '' // 针对性移除异常字符“啊”(若为固定乱码)
|
||||
// ];
|
||||
// $sAuthorContent = strtr($sAuthorContent, $symbolMap);
|
||||
|
||||
// //格式标准化
|
||||
// $sAuthorContent = str_replace([',', ';', ';', '、'], ',', $sAuthorContent); // 统一分隔符
|
||||
// $sAuthorContent = preg_replace('/\s+and\s+/i', ', ', $sAuthorContent); // and转逗号
|
||||
// $sAuthorContent = preg_replace('/\s+/', ' ', $sAuthorContent); // 合并多余空格
|
||||
// $sAuthorContent = trim($sAuthorContent);
|
||||
// var_dump($this->parseAuthorsWithoutRegex($sAuthorContent));exit;
|
||||
// // 关键预处理:兼容"and"分隔符、清理乱码、统一空格
|
||||
// $content = mb_convert_encoding($sAuthorContent, 'UTF-8', 'auto');
|
||||
// $content = str_replace(["\xC2\xA0", 'ï¼', '�', ','], ' ', $content); // 清理乱码和全角符号
|
||||
// $content = preg_replace('/\band\b/i', ',', $content); // 将 "and" 转为逗号(统一分隔符)
|
||||
// $content = preg_replace('/(\d+)\s*([*#†])/', '$1$2', $content); // 合并数字与符号间的空格(如"1 *"→"1*")
|
||||
// $content = trim(preg_replace('/\s+/', ' ', $content)); // 合并连续空格
|
||||
|
||||
// // 标记上标内的逗号(多编号处理)
|
||||
// $tempStr = preg_replace('/(\d+)\s*,\s*(\d+)/', '$1<SEP>$2', $content);
|
||||
|
||||
// // 核心正则(保持原有结构,扩展符号支持)
|
||||
// $pattern = '/
|
||||
// ([A-Za-z\s\.\-]+?) # 姓名(支持缩写、空格、连字符)
|
||||
// \s* # 姓名与上标间的空格(允许0或多个)
|
||||
// ( # 上标组(扩展兼容所有符号)
|
||||
// \d+ # 起始数字(至少1个数字)
|
||||
// (?:[†#*,]|<SEP>\d+)* # 允许:符号(†#*)、逗号、<SEP>+数字(多编号)
|
||||
// )
|
||||
// \s*,? # 作者间的逗号(可选,允许逗号前有空格)
|
||||
// (?=\s|$) # 确保后面是空格或字符串结尾(避免跨作者匹配)
|
||||
// /ux';
|
||||
|
||||
// preg_match_all($pattern, $tempStr, $matches);
|
||||
|
||||
// // 解析结果并格式化
|
||||
// $authorList = [];
|
||||
// if (!empty($matches[1])) {
|
||||
// foreach ($matches[1] as $i => $name) {
|
||||
// $name = trim($name);
|
||||
// $superscript = trim($matches[2][$i]);
|
||||
// $superscript = str_replace('<SEP>', ',', $superscript); // 恢复多编号逗号
|
||||
// $superscript = preg_replace('/,$/', '', $superscript); // 清理末尾多余逗号
|
||||
// if (!empty($name)) {
|
||||
// $authorList[] = [
|
||||
// 'name' => $name,
|
||||
// 'superscript' => $superscript
|
||||
// ];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 输出结果
|
||||
// echo "<pre>";
|
||||
// print_r($authorList);
|
||||
// echo "</pre>";
|
||||
// exit;
|
||||
|
||||
// // 处理作者
|
||||
// $content = mb_convert_encoding($sAuthorContent, 'UTF-8', 'auto'); // 确保编码正确
|
||||
// $content = str_replace("\xC2\xA0", ' ', $content); // 替换非-breaking空格为普通空格
|
||||
// $content = preg_replace('/(\d+)\s*([*#†])/', '$1$2', $content); // 合并"1 *"为"1*"、"1 #"为"1#"
|
||||
// $content = preg_replace('/,†/', ',†', $content); // 保留"1,†"格式(防止被拆分)
|
||||
|
||||
// //标记上标内的逗号+空格(多编号)
|
||||
// $tempStr = preg_replace('/(\d+)\s*,\s*(\d+)/', '$1<SEP>$2', $content);
|
||||
// // 原有步骤2:正则匹配(扩展上标符号支持,保持原有逻辑)
|
||||
// $pattern = '/
|
||||
// ([A-Za-z\s\.\-]+?) # 姓名(支持缩写、空格)
|
||||
// \s* # 姓名与上标间空格
|
||||
// ( # 上标组(扩展符号支持)
|
||||
// \d+ # 起始数字
|
||||
// (?:[†#*,]|<SEP>\d+)* # 允许:†#*符号、逗号、<SEP>+数字(兼容1,†、1,*等)
|
||||
// )
|
||||
// \s*,? # 作者间逗号(可选)
|
||||
// (?=\s|$) # 确保后面是空格或结尾
|
||||
// /ux';
|
||||
|
||||
// preg_match_all($pattern, $tempStr, $matches);
|
||||
// var_dump($matches);exit;
|
||||
// $authorList = [];
|
||||
// if(!empty($matches[1])){
|
||||
// foreach ($matches[1] as $i => $name) {
|
||||
// $name = trim($name);
|
||||
// $superscript = trim($matches[2][$i]);
|
||||
// $superscript = str_replace('<SEP>', ',', $superscript); // 恢复多编号逗号
|
||||
// $superscript = preg_replace('/,$/', '', $superscript); // 清理末尾逗号
|
||||
// // 修复符号与数字间的空格(如原始"1 *"被误处理为"1*"的情况,保持原样)
|
||||
// $superscript = preg_replace('/(\d)([*#†])/', '$1$2', $superscript);
|
||||
// if (!empty($name)) {
|
||||
// $authorList[] = [
|
||||
// 'name' => $name,
|
||||
// 'superscript' => $superscript
|
||||
// ];
|
||||
// }
|
||||
// }
|
||||
// }else {
|
||||
// // 按“两个或多个连续空格”拆分(姓名之间的分隔)
|
||||
// $authorList = array_filter(
|
||||
// array_map('trim',
|
||||
// preg_split('/(,\p{Z}*|\p{Z}{2,})/u', $sAuthorContent)
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
|
||||
|
||||
// // //处理作者
|
||||
// $aAuthorData = [];
|
||||
// $aReport = [];
|
||||
// $namePattern = '/
|
||||
// (?:[A-Za-z\s·\-\']+| # 英文姓名(支持空格、连字符)
|
||||
// [\x{4e00}-\x{9fa5}]+| # 中文姓名
|
||||
// [\x{1800}-\x{18AF}]+| # 蒙古文姓名
|
||||
// [A-Z]\.) # 单字母缩写(如 J.)
|
||||
// /ux';
|
||||
|
||||
// foreach ($authorList as $authorStr){
|
||||
// if (empty($authorStr)) continue;
|
||||
|
||||
// //获取下标
|
||||
// $superscript = empty($authorStr['superscript']) ? $authorStr : $authorStr['superscript'];
|
||||
// $nameStr = empty($authorStr['name']) ? $authorStr : $authorStr['name'];
|
||||
|
||||
// $companyId = [];
|
||||
// $isSuper = 0;
|
||||
// $isReport = 0;
|
||||
// if (!empty($superscript)) {
|
||||
// // 提取机构编号(忽略上标中的逗号,如1,† → 提取1)
|
||||
// preg_match_all('/\d+/', $superscript, $numMatch);
|
||||
// // 识别特殊符号(#为超级作者,*†为通讯作者)
|
||||
// $isSuper = strpos($superscript, '#') !== false ? 1 : 0;
|
||||
// $isReport = (strpos($superscript, '*') !== false || strpos($superscript, '†') !== false) ? 1 : 0;
|
||||
// }
|
||||
// if (preg_match("/^([A-Za-z\s'\.-]+)/u", $nameStr, $match)) {
|
||||
// $nameStr = trim($match[1]);
|
||||
// }
|
||||
// $aAuthorData[] = [
|
||||
// 'name' => $nameStr,
|
||||
// 'company_id' => empty($numMatch[0]) ? [] : $numMatch[0],
|
||||
// 'is_super' => $isSuper,
|
||||
// 'is_report' => $isReport
|
||||
// ];
|
||||
// if ($isReport) {
|
||||
// $aReport[] = $nameStr;
|
||||
// }
|
||||
// }
|
||||
// return ['author' => $aAuthorData,'report' => array_unique($aReport)];
|
||||
// }
|
||||
|
||||
// 获取机构
|
||||
private function getCompany($aParam = []){
|
||||
@@ -388,32 +806,68 @@ class ArticleParserService
|
||||
//获取标题下的作者
|
||||
$sAuthorContent = empty($aParam['authors']) ? $this->getNextParagraphAfterText($title) : $aParam['authors'];
|
||||
//获取作者结构
|
||||
$sCompany = $this->getContentAfterText($sAuthorContent);
|
||||
if(empty($sCompany)){
|
||||
$allLines = $this->getContentAfterText($sAuthorContent,1);
|
||||
if(empty($allLines)){
|
||||
return [];
|
||||
}
|
||||
//编码修复
|
||||
// 2. 按序号分组,合并同一序号的多行内容
|
||||
$grouped = [];
|
||||
$currentNumber = null; // 当前序号
|
||||
foreach ($allLines as $line) {
|
||||
$line = trim($line);
|
||||
if (empty($line)) continue;
|
||||
|
||||
// 判断是否是新条目的开头:行首为数字(后续可接任意字符或直接接内容)
|
||||
$number = '';
|
||||
$i = 0;
|
||||
$lineLen = strlen($line);
|
||||
// 提取行首的连续数字(作为序号)
|
||||
while ($i < $lineLen && ctype_digit($line[$i])) {
|
||||
$number .= $line[$i];
|
||||
$i++;
|
||||
}
|
||||
|
||||
// 若行首有数字,则视为新条目
|
||||
if (!empty($number)) {
|
||||
$currentNumber = $number;
|
||||
// 提取序号后的内容(跳过数字后的符号/空格,保留核心内容)
|
||||
// 从数字后的位置开始,跳过可能的符号(./*)或空格
|
||||
while ($i < $lineLen && (in_array($line[$i], ['.', '*', ' ']))) {
|
||||
$i++;
|
||||
}
|
||||
$content = trim(substr($line, $i)); // 序号后的内容
|
||||
$grouped[$currentNumber] = $content;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 非新条目,合并到当前序号的内容中
|
||||
if ($currentNumber !== null) {
|
||||
$grouped[$currentNumber] .= ' ' . $line;
|
||||
}
|
||||
}
|
||||
|
||||
//清理结果
|
||||
$possibleEncodings = [
|
||||
'Windows-1252', 'UTF-8', 'GBK', 'GB2312',
|
||||
'Latin-1', 'ISO-8859-1', 'CP1252'
|
||||
];
|
||||
$encodedContent = @mb_convert_encoding($sCompany, 'UTF-8', implode(',', $possibleEncodings));
|
||||
$sCompany = $encodedContent ?: $sCompany;
|
||||
//按行拆分,保留数字开头的行
|
||||
$sCompany = str_replace(["\r\n", "\r"], "\n", $sCompany);
|
||||
$aCompanyLines = explode("\n", $sCompany);
|
||||
$aCompanyLines = array_filter(array_map('trim', $aCompanyLines), function($line) {
|
||||
return preg_match('/^\d+/', $line); // 仅保留数字开头的行
|
||||
});
|
||||
|
||||
$aCompany = [];
|
||||
foreach ($aCompanyLines as $line) {
|
||||
if (preg_match('/^(\d+)\s*(.+)$/', $line, $match)) {
|
||||
if(empty($match[1]) || empty($match[2])){
|
||||
continue;
|
||||
}
|
||||
$aCompany[$match[1]] = ltrim(trim(ltrim($match[2]),'.'),' ');
|
||||
foreach ($grouped as $number => $institution) {
|
||||
$encodedContent = @mb_convert_encoding($institution, 'UTF-8', implode(',', $possibleEncodings));
|
||||
$sCompany = $encodedContent ?: $sCompany;
|
||||
$institution = preg_replace('/\s+/', ' ', $institution); // 合并多余空格
|
||||
$institution = rtrim($institution, '.');
|
||||
$institution = preg_replace('/^\d+\s+/', '', $institution);
|
||||
$institution = trim($institution); // 清理首尾空格
|
||||
preg_match('/(.*?, [A-Za-z]+ \d+, [A-Za-z]+)/', $institution, $institutionmatches);;
|
||||
$institution = trim($institutionmatches[1] ?? $institution);
|
||||
if (preg_match('/^(.*?)(?=\s*\*Email)/', $institution, $matches)) {
|
||||
$institution = trim($matches[1]); // trim() 去除内容前后多余空格
|
||||
}
|
||||
if(!empty($institution) && !mb_check_encoding($institution, 'UTF-8')){
|
||||
$institution = mb_convert_encoding($institution, 'UTF-8', 'GBK');
|
||||
}
|
||||
$aCompany[$number] = $institution;
|
||||
}
|
||||
return $aCompany;
|
||||
}
|
||||
@@ -451,7 +905,6 @@ class ArticleParserService
|
||||
$corrText = str_replace([':', '@'], [':', '@'], $corrText);
|
||||
$corrText = preg_replace('/\s+/', ' ', $corrText); // 统一空格
|
||||
$corrText = str_replace(' ', ' ', $corrText); // 去除多余空格
|
||||
|
||||
//按"*"分割通讯作者
|
||||
$corrBlocks = preg_split('/\s*\*\s*/', $corrText);
|
||||
$corrBlocks = array_filter(array_map('trim', $corrBlocks));
|
||||
@@ -466,7 +919,6 @@ class ArticleParserService
|
||||
preg_match('/(E[\s-]*mail|邮箱)[\s:]*([^\s]+@[^\s]+)/i', $block, $email);
|
||||
preg_match('/(Postal[\s-]*address|地址)[\s:]*([^,;]+)/i', $block, $address);
|
||||
preg_match('/(Tel|电话)[\s:]*([^\s]+)/i', $block, $tel);
|
||||
|
||||
$aCorresponding[] = [
|
||||
'name' => $sName,
|
||||
'email' => isset($email[2]) ? trim($email[2]) : '',
|
||||
@@ -474,6 +926,24 @@ class ArticleParserService
|
||||
'tel' => isset($tel[2]) ? trim($tel[2]) : ''
|
||||
];
|
||||
}
|
||||
if(empty($aCorresponding)){
|
||||
$pattern = '/Corresponding Authors: (.*?)(?=$|;)/s';
|
||||
preg_match($pattern, $corrText, $match);
|
||||
if (!empty($match[1])) {
|
||||
$corrContent = $match[1];
|
||||
// 提取每个作者的名称和邮箱(优化正则,支持更多字符)
|
||||
$authorPattern = '/([A-Za-z\s]+?),\s*E-mail:\s*([\w@\.\-]+)/';
|
||||
preg_match_all($authorPattern, $corrContent, $authors);
|
||||
if(!empty($authors[1])){
|
||||
for ($i = 0; $i < count($authors[1]); $i++) {
|
||||
$aCorresponding[] = [
|
||||
'name' => empty($authors[1][$i]) ? '' : trim($authors[1][$i]),
|
||||
'email' => empty($authors[2][$i]) ? '' : trim($authors[2][$i])
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aCorresponding;
|
||||
}
|
||||
|
||||
@@ -518,10 +988,10 @@ class ArticleParserService
|
||||
}
|
||||
|
||||
// 获取目标文本后的所有内容
|
||||
private function getContentAfterText($targetText){
|
||||
private function getContentAfterText($targetText,$return_type = 2){
|
||||
$found = false;
|
||||
$content = [];
|
||||
$stopKeywords = ['关键词', 'Key words', '摘要', 'Abstract'];
|
||||
$stopKeywords = ['关键词', 'Key words', '摘要', 'Abstract','ABSTRACT'];
|
||||
$maxLines = 200;
|
||||
$lineNumber = 0;
|
||||
foreach ($this->sections as $section) {
|
||||
@@ -559,7 +1029,14 @@ class ArticleParserService
|
||||
}
|
||||
if (count($content) >= $maxLines || (isset($shouldStop) && $shouldStop)) break;
|
||||
}
|
||||
return implode("\n", $content);
|
||||
if($return_type == 1){
|
||||
return $content;
|
||||
}
|
||||
$content = implode("\n", $content);
|
||||
if(!empty($content) && !mb_check_encoding($content, 'UTF-8')){
|
||||
$content = mb_convert_encoding($content, 'UTF-8', 'GBK');
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
// 统一提取元素文本
|
||||
@@ -635,7 +1112,9 @@ class ArticleParserService
|
||||
$text = preg_replace('/[\x00-\x1F\x7F-\x9F]/', ' ', $text); // 移除控制字符
|
||||
$text = str_replace(["\t", "\r", "\n"], ' ', $text); // 统一空白字符
|
||||
$text = preg_replace('/\s+/', ' ', $text); // 合并多个空格
|
||||
|
||||
if(!empty($text) && !mb_check_encoding($text, 'UTF-8')){
|
||||
$text = mb_convert_encoding($text, 'UTF-8', 'GBK');
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
@@ -676,13 +1155,17 @@ class ArticleParserService
|
||||
$sContent .= "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($sContent) && !mb_check_encoding($sContent, 'UTF-8')){
|
||||
$sContent = mb_convert_encoding($sContent, 'UTF-8', 'GBK');
|
||||
}
|
||||
// 2. 基础文本清理(合并多余空格,保留有效换行)
|
||||
$textContent = preg_replace('/(\S)\s+/', '$1 ', $sContent);
|
||||
$textContent = trim($textContent);
|
||||
|
||||
// 3. 提取摘要
|
||||
$abstract = '';
|
||||
$abstractPattern = '/Abstract\s*([\s\S]*?)(?=Keywords:|$)/i';
|
||||
$abstractPattern = '/Abstract\s*([\s\S]*?)(?=Keywords|$)/i';
|
||||
if (preg_match($abstractPattern, $textContent, $abstractMatches)) {
|
||||
$abstract = trim($abstractMatches[1]);
|
||||
$abstract = preg_replace('/\n+/', ' ', $abstract);
|
||||
@@ -690,7 +1173,8 @@ class ArticleParserService
|
||||
// 4. 提取关键词(核心:仅保留两种强制匹配逻辑)
|
||||
$keywords = [];
|
||||
// $keywordPattern = '/Keywords:\s*([\s\S]*?)(?=\s*\d+\.|[;,]\s*[\r\n]+\s*[\r\n]+|(?i)\bintroduction|abbreviations\b|$)/i';
|
||||
$keywordPattern = '/Keywords:\s*(.*?)\s*Keywords-End-Flag/s';
|
||||
$keywordPattern = '/Keywords\s*(.*?)\s*Keywords-End-Flag/s';
|
||||
|
||||
if (preg_match($keywordPattern, $textContent, $keywordMatches)) {
|
||||
$keywordStr = trim($keywordMatches[1]);
|
||||
|
||||
@@ -705,6 +1189,22 @@ class ArticleParserService
|
||||
return !empty($item) && !ctype_space($item);
|
||||
});
|
||||
}
|
||||
if(empty($keywords)){
|
||||
$keywordPattern = '/Keywords\s*([\s\S]*?)(?=Introduction|$)/i';
|
||||
if (preg_match($keywordPattern, $textContent, $keywordMatches)) {
|
||||
$keywordStr = trim($keywordMatches[1]);
|
||||
// 清理关键词列表格式(去除换行、末尾多余符号)
|
||||
$keywordStr = preg_replace('/\n+/', ' ', $keywordStr);
|
||||
$keywordStr = rtrim($keywordStr, ';,. '); // 去除末尾分号、逗号等
|
||||
$keywordStr = trim($keywordStr);
|
||||
|
||||
// 分割并过滤有效关键词
|
||||
$keywords = preg_split('/[,;]\s*/', $keywordStr);
|
||||
$keywords = array_filter(array_map('trim', $keywords), function($item) {
|
||||
return !empty($item) && !ctype_space($item);
|
||||
});
|
||||
}
|
||||
}
|
||||
return [
|
||||
'status' => 1,
|
||||
'msg' => '提取成功',
|
||||
|
||||
@@ -301,7 +301,8 @@ class ProofReadService
|
||||
|
||||
// 3. 核心优先级:运算符规则(精准匹配,排除No.编号干扰)
|
||||
[
|
||||
'pattern' => '~(\S)\s*([<>!]=|===|!==)\s*(\S)~u',
|
||||
// 'pattern' => '~(\S)\s*([<>!]=|===|!==)\s*(\S)~u',
|
||||
'pattern' => '~(?<!</[a-z]+>)\s*(\S)\s*([<>!]=|===|!==)\s*(\S)(?!<[a-z]+>)~u',
|
||||
'replacement' => '$1 $2 $3',
|
||||
'verbatim_texts' => '复合运算符前后空格不规范',
|
||||
'explanation' => '复合运算符[>=、<=、==、!=、===、!==]前后应各留一个空格',
|
||||
|
||||
Reference in New Issue
Block a user