From 838e25028f43a646430f9e80f7a705481a443ace Mon Sep 17 00:00:00 2001 From: chengxl Date: Wed, 31 Dec 2025 16:06:35 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=9F=E6=88=90pdf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/common/LatexContent.php | 199 ++++++++++++++++++++++------ 1 file changed, 157 insertions(+), 42 deletions(-) diff --git a/application/common/LatexContent.php b/application/common/LatexContent.php index 3df09b1..3e269ae 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,19 @@ 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'); + // //查询表格 + // $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 +301,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 +326,20 @@ 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"; + // $aTableInfo = empty($aArticleMainTable[$value['amt_id']]) ? [] : $aArticleMainTable[$value['amt_id']]; + // if(empty($aTableInfo['table_data'])){ + // continue; + // } + // $aTableResult = $oLatexTable->generateTable($aTableInfo); + // var_dump($aTableResult);exit; + // if(empty($aTableResult['data'])){ + // continue; + // } } + } } } @@ -536,40 +553,138 @@ page={{stage_page}},%号 /** * 内容处理 */ - private function dealContent($content = '', $target = 'latex',$iIsDeal = 1) { + // 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)); + // if($iIsDeal == 1){ + // $content = $this->htmlToLaTeX($content); + // } + // return $content; + // } + 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; + // //整合所有替换规则(按优先级排序:先处理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)); + // if($iIsDeal == 1){ + // $content = $this->htmlToLaTeX($content); + // } + // return $content; + } + 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 请求获取图片保存到本地