diff --git a/application/api/controller/Article.php b/application/api/controller/Article.php index f221c49..308fc5f 100644 --- a/application/api/controller/Article.php +++ b/application/api/controller/Article.php @@ -1577,7 +1577,6 @@ class Article extends Base $update_data['rstime'] = time(); } $this->article_obj->where($where_article)->update($update_data); - //拒稿或者录用 - 发送审稿意见 if ($article_info['journal_id'] == 1 && ($data['state'] == 3 || $data['state'] == 5)) { $this->sendEmailToReviewer($data['articleId'], $data['state']); @@ -6241,4 +6240,92 @@ class Article extends Base } return ['status' => 1,'msg' => 'success']; } + + /** + * 添加图片版权声明文件-编辑 + */ + public function addFigureCopyrightForEditor($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 the article']); + } + //用户ID + $iUserId = empty($aParam['user_id']) ? '' : $aParam['user_id']; + if(empty($iUserId)){ + return json_encode(['status' => 2,'msg' => 'Please select author']); + } + // //是否上传文件 + // $is_figure_copyright = empty($aParam['is_figure_copyright']) ? 3 : $aParam['is_figure_copyright']; + // if($is_figure_copyright == 3){ + // return json_encode(['status' => 3,'msg' => 'Please check whether to upload the figure copyright statement']); + // } + + //获取操作人信息 + $aWhere = ['user_id' => $iUserId,'state' => 0]; + $aUser = Db::name('user')->field('account')->where($aWhere)->find(); + if(empty($aUser)){ + return json_encode(['status' => 5,'msg' => 'No operator information found']); + } + //获取文章信息 + $aWhere = ['article_id' => $iArticleId]; + $aArticle = Db::name('article')->field('article_id,state,editor_id,journal_id')->where($aWhere)->find(); + if(empty($aArticle)){ + return json_encode(['status' => 6,'msg' => 'The article does not exist']); + } + //判断是否有权限操作 + if($iUserId != $aArticle['editor_id']){ + return json_encode(['status' => 7,'msg' => 'Unauthorized operation']); + } + //查询期刊负责编辑 + $aWhere = ['journal_id' => $aArticle['journal_id'],'state' => 0]; + $aJournal = Db::name('journal')->field('editor_id')->where($aWhere)->find(); + if(empty($aJournal)){ + return json_encode(['status' => 7,'msg' => 'No article or journal information found']); + } + if($iUserId != $aJournal['editor_id']){ + return json_encode(['status' => 7,'msg' => 'No operation permission']); + } + //图片路径 + // if($is_figure_copyright == 1){ + //文件地址 + $sUrl = empty($aParam['url']) ? '' : $aParam['url']; + if(empty($sUrl)){ + return json_encode(['status' => 4,'msg' => 'Please choose to upload the file']); + } + // } + + //文件类型 + $sTypeName = 'figurecopyright'; + $sUserAccount = empty($aUser['account']) ? '' : $aUser['account']; + Db::startTrans(); + if(!empty($sUrl)){ + //验证文件是否上传 + $aWhere = ['file_url' => $sUrl,'state' => 0,'article_id' => $iArticleId,'type_name' => $sTypeName]; + $result = Db::name('article_file')->where($aWhere)->find(); + if(empty($result)){ + $aInsert['article_id'] = $iArticleId; + $aInsert['user_id'] = $iUserId; + $aInsert['username'] = $sUserAccount; + $aInsert['file_url'] = $sUrl; + $aInsert['type_name'] = $sTypeName; + $aInsert['ctime'] = time(); + $result = Db::name('article_file')->insertGetId($aInsert); + } + } + // //更新文章内容 + // $aArticleUpdate = ['is_figure_copyright' => $is_figure_copyright]; + // if(!empty($aArticleUpdate)){ + // $aWhere = ['article_id' => $iArticleId]; + // $update_result = Db::name('article')->where($aWhere)->limit(1)->update($aArticleUpdate); + // } + //操作日志 + $aLog = ['article_id' => $iArticleId,'user_id' => $iUserId,'type' => 7,'create_time' => time(),'content' => $sUserAccount . ':Operating the article copyright statement','is_view' => 1]; + Db::name('user_act_log')->insert($aLog); + Db::commit(); + return json_encode(['status' => 1,'msg' => 'success']); + } } diff --git a/application/common/LatexContent.php b/application/common/LatexContent.php index 3df09b1..d1d00f4 100644 --- a/application/common/LatexContent.php +++ b/application/common/LatexContent.php @@ -37,7 +37,7 @@ year={{stage_year}},%年 volume={{stage_vol}},%卷 no={{stage_no}},%期 page={{stage_page}},%号 -]{tmr-tex} +]{../tmr-tex} \doi{{{doi}}} \journalweb{{{website}}} @@ -49,18 +49,15 @@ page={{stage_page}},%号 \usepackage[nopatch]{microtype} \usepackage{booktabs} \usepackage[backend=biber]{biblatex} -\usepackage{xcolor} % 蓝色字体(参考文献) -\usepackage{multirow} % 单元格合并(必选) -\usepackage{array} % 列格式居中(必选) -\usepackage{geometry} % 页面适配,避免内容溢出 -\addbibresource{example.bib} +\usepackage{xcolor} +\usepackage{tabularray} +\addbibresource{references_{{p_article_id}}.bib} +\definecolor{evenRowColor}{RGB}{250,231,232} \title{{{article_title}}} {{author_info}} -\addbibresource{example.bib} - {{correspondence_info}} @@ -87,6 +84,8 @@ page={{stage_page}},%号 \twocolumn {{tmr_highlight}} {{article_main}} + \nocite{*} + \printbibliography[title={References}] \end{document}'; /** * 生成初稿-基本内容 @@ -211,6 +210,7 @@ page={{stage_page}},%号 $aSearch['{{article_icon}}'] = $sIcon; $aSearch['{{keywords}}'] = $sKeywords; $aSearch['{{CLSFILEURL}}'] = ROOT_PATH.'public/latex/cls'; + $aSearch['{{p_article_id}}'] = $aProductionArticle['p_article_id']; //模版内容替换 $sTemplateInfo = str_replace(array_keys($aSearch), array_values($aSearch), $sTemplateInfo); //返回内容 @@ -220,8 +220,11 @@ page={{stage_page}},%号 * 生成初稿-主内容 * @param article_id 文章ID */ - public function buildMain($aProductionArticle = []){ - + public function buildMain($aParam = []){ + //生产环境文章信息 + $aProductionArticle = empty($aParam['production_article']) ? [] : $aParam['production_article']; + //参考文献信息 + $aReferences = empty($aParam['references']) ? [] : $aParam['references']; //获取模版 $sTemplateInfo = $this->sMain; @@ -256,17 +259,14 @@ page={{stage_page}},%号 $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; + //字符串处理 + $oProduction = new \app\api\controller\Production; foreach ($aArticleMain as $key => $value) { if(empty($iStart)){ if($value['is_h1'] == 0){ @@ -296,7 +296,7 @@ page={{stage_page}},%号 } if($value['is_h1'] == 0 && $value['is_h2'] == 0 && $value['is_h3'] == 0){ if($value['type'] == 0 ){ - $sMain .= $this->dealContent($value['content'])."\\par\n"; + $sMain .= $this->dealContent($value['content'],$aReferences)."\\par\n"; } if($value['type'] == 1 ){//图片 $aImageInfo = empty($aArticleMainImage[$value['ami_id']]) ? [] : $aArticleMainImage[$value['ami_id']]; @@ -321,8 +321,11 @@ page={{stage_page}},%号 $sMain .= $sImageTempalteInfo."\\par\n"; } if($value['type'] == 2 ){//表格 - continue; + $sTableInfo = $oProduction->tableCovertLatex($value['amt_id'],$aReferences); + var_dump($sTableInfo); + $sMain .= $sTableInfo."\\par\n"; } + } } } @@ -533,43 +536,72 @@ page={{stage_page}},%号 } return trim($dateStr); } - /** - * 内容处理 - */ - private function dealContent($content = '', $target = 'latex',$iIsDeal = 1) { + private function dealContent($content = '',$aReferences = []) { // 空值直接返回 - if (empty($content)) { + 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{-}', // 短横线强制保留形态 - ':' => ':', // 冒号无需转义(占位,便于统一维护) + + //字符串处理 + $oProduction = new \app\api\controller\Production; + $sContent = $oProduction->convertToLatex($content,$aReferences); + $content = $this->htmlToLaTeX($content); + return $sContent; + } + private function htmlToLaTeX($text = ''){ + if(empty($text)){ + return ''; + } + $replaceMap = [ + // 基础标签转换 + '' => '\textit{', + '' => '}', + '' => '\textit{', + '' => '}', + '' => '\textbf{', + '' => '}', + '' => '\textcolor{blue}{', + '' => '}', + '

' => '', + '

' => '', + '' => '$_{', + '' => '}$', + '' => '$^{', + '' => '}$', + '~' => '--', // 波浪号→范围符 + '(' => '(', // 全角左括号→半角 + ')' => ')', // 全角右括号→半角 + '((' => '(', // 重复括号去重 + '))' => ')', + + // ========== 新增: 标签处理 ========== + // 场景1:纯空 标签(无属性)→ 直接删除,保留内容 + '' => '', + '' => '', + // 场景2:带蓝色样式的 → 转为 LaTeX 蓝色命令 + '' => '\textcolor{blue}{', + '' => '\textcolor{blue}{', // 兼容大小写/空格 + '' => '\textcolor{red}{', // 扩展:红色 + '' => '}', // 所有 span 闭标签统一转为 }(匹配开标签的 LaTeX 命令) + + // 扩展:其他常用 span 样式(按需添加) + '' => '\textbf{', + '' => '\textit{', ]; - //执行批量替换 - $content = strtr($content, $replaceRules); - //清理多余空格/换行 - $content = preg_replace('/\s+/u', ' ', trim($content)); - return $content; + // 第一步:替换所有标签(优先处理带属性的 span,再处理空 span) + $text = strtr($text, $replaceMap); + + // 第二步:清理残留的特殊 span 标签(如未匹配的属性,直接删除标签保留内容) + // 匹配 形式的标签(任意属性),仅删除标签,保留内容 + $text = preg_replace('/]*?)?>/i', '', $text); + $text = preg_replace('/<\/span>/i', '', $text); + + return $text; } /** * @title curl 请求获取图片保存到本地