From c59d60e146c956f104d75bbd30492475579d48d0 Mon Sep 17 00:00:00 2001
From: wangjinlei <751475802@qq.com>
Date: Mon, 29 Dec 2025 16:08:36 +0800
Subject: [PATCH] table latex create
---
application/api/controller/Production.php | 222 +++++++++++++++++++++-
1 file changed, 213 insertions(+), 9 deletions(-)
diff --git a/application/api/controller/Production.php b/application/api/controller/Production.php
index ecfe9d9..398a5b5 100644
--- a/application/api/controller/Production.php
+++ b/application/api/controller/Production.php
@@ -2059,7 +2059,7 @@ class Production extends Base
}elseif ($article_main_info['type']==1){//处理图片
}else{//处理表格
-
+ $fragContentList[] = $this->tableCovertLatex($article_main_info['amt_id'],$references);
}
}
//实际生成tex
@@ -2097,13 +2097,12 @@ class Production extends Base
$content = str_replace("–","-",$content);
- $content = $this->convertReferencesToLatex($content, $refArray);
-
// 步骤1:忽略并移除
、
和标签
$content = $this->removeIgnoredTags($content);
// 步骤2:解析剩余标签并生成LaTeX内容
- $latexContent = $this->textRenderCreate($content);
+ $latexContent = $this->textRenderCreate($content,$refArray);
+// $latexContent = $this->convertReferencesToLatex($content, $refArray);
return $latexContent;
}
@@ -2114,6 +2113,7 @@ class Production extends Base
* @return string 处理后的内容
*/
private function removeIgnoredTags($content) {
+ $content = html_entity_decode($content, ENT_QUOTES, 'UTF-8');
// 移除和
(不区分大小写,处理可能的空格)
$content = preg_replace('/<\/?tr\s*>/i', '', $content);
// 移除
@@ -2126,8 +2126,50 @@ class Production extends Base
* @param string $content 待解析的内容
* @return string 解析后的LaTeX内容
*/
- private function textRenderCreate($content) {
+ private function textRenderCreate($content,$references) {
$latex = '';
+
+
+ if (preg_match('/(?:)?\[(\d+(?:[-,]\d+)*)\](?:<\/blue>)?/', $content, $matches)) {
+ // 去除匹配中的 和
+ $cleanedMatch = str_replace(['', ''], '', $matches[0]);
+ // 提取引用编号部分(去掉方括号)
+ $referencePart = trim($cleanedMatch, '[]');
+
+ // 分割逗号分隔的不同引用项
+ $parts = explode(',', $referencePart);
+ $latexRefs = [];
+
+ foreach ($parts as $part) {
+ // 判断是否是范围形式如 3-5
+ if (strpos($part, '-') !== false) {
+ list($start, $end) = explode('-', $part);
+ $start = intval($start);
+ $end = intval($end);
+
+ // 展开范围并逐个查找 ref_id
+ for ($i = $start; $i <= $end; $i++) {
+ $arrayIndex = $i;
+ if (isset($references[$arrayIndex]) && !empty($references[$arrayIndex]['p_refer_id'])) {
+ $latexRefs[] = 'ref_' . $references[$arrayIndex]['p_refer_id'];
+ } else {
+ $latexRefs[] = $i;
+ }
+ }
+ } else {
+ // 单个引用编号处理
+ $index = intval($part);
+ $arrayIndex = $index;
+ if (isset($references[$arrayIndex]) && !empty($references[$arrayIndex]['p_refer_id'])) {
+ $latexRefs[] = 'ref_' . $references[$arrayIndex]['p_refer_id'];
+ } else {
+ $latexRefs[] = $index;
+ }
+ }
+ }
+ return '\parencite{' . implode(',', $latexRefs) . '}';
+ }
+
while (!empty($content)) {
$nextTag = $this->determineNextTag($content);
if ($nextTag === 'no') {
@@ -2407,14 +2449,14 @@ class Production extends Base
*/
private function escapeLatexSpecialChars($text) {
$specialChars = [
-// '\\' => '\\textbackslash',
-// '{' => '\\{',
-// '}' => '\\}',
+ '\\' => '\\textbackslash',
+ '{' => '\\{',
+ '}' => '\\}',
'$' => '\\$',
'%' => '\\%',
'#' => '\\#',
'&' => '\\&',
-// '_' => '\\_',
+ '_' => '\\_',
'^' => '\\textasciicircum',
'~' => '\\textasciitilde',
];
@@ -3066,6 +3108,168 @@ class Production extends Base
}
}
+
+
+ public function myTableTest(){
+ $references = $this->production_article_refer_obj->where("p_article_id",3401)->where("state",0)->order("index asc")->select();
+ $res = $this->tableCovertLatex(1089,$references);
+
+ echo $res;
+ }
+
+ private function tableCovertLatex($amt_id, $references)
+ {
+ $table_info = $this->article_main_table_obj->where('amt_id', $amt_id)->find();
+ $tableData = json_decode($table_info['table_data'], true);
+
+ // 检查JSON解码是否成功
+ if (json_last_error() !== JSON_ERROR_NONE || !is_array($tableData) || empty($tableData)) {
+ return "% 无效的JSON数据";
+ }
+
+ // 获取表格最大列数(遍历所有行,找到列数最大值,处理合并后列数变化的情况)
+ $maxColCount = 0;
+ $str_list = [];
+ foreach ($tableData as $row) {
+ $colCount = 0;
+ foreach ($row as $cell) {
+ $colCount += $cell['colspan']; // 跨列会占用多个列位置
+ if($cell['colspan']==1){
+ $colIndex = $colCount; // 当前列的索引
+
+ // 计算当前单元格的字符数
+ $cellTextLength = strlen(strip_tags($cell['text'])); // 或者使用 mb_strlen($cell['text'], 'UTF-8') 来处理多字节字符
+
+ if(isset($str_list[$colIndex])){
+ $str_list[$colIndex] = max($cellTextLength, $str_list[$colIndex]);
+ } else {
+ $str_list[$colIndex] = $cellTextLength;
+ }
+ }
+ }
+ if ($colCount > $maxColCount) {
+ $maxColCount = $colCount;
+ }
+ }
+
+ // 根据 $str_list 计算列宽比例(比例范围:0.2-1)
+ $columnSpec = '';
+ if (!empty($str_list)) {
+ // 找到最大字符数,用于比例计算
+ $maxTextLength = max($str_list);
+
+ if ($maxTextLength > 0) {
+ // 为每一列计算相对宽度(比例范围:0.2-1)
+ for ($i = 1; $i <= $maxColCount; $i++) {
+ if (isset($str_list[$i]) && $str_list[$i] > 0) {
+ // 计算当前列的相对比例(0-1之间)
+ $relativeRatio = round($str_list[$i] / $maxTextLength, 1);
+ // 将比例调整到0.2-1范围内
+ $adjustedRatio = max(0.3, min(1, $relativeRatio));
+ // 转换为整数(乘以10便于处理小数)
+// $widthValue = round($adjustedRatio * 10);
+ $columnSpec .= "X[$adjustedRatio] ";
+ } else {
+ // 如果某列没有数据,给一个默认最小宽度(对应0.2比例)
+ $columnSpec .= "X[0.3] "; // 0.2 * 10 = 2
+ }
+ }
+ } else {
+ // 如果没有有效数据,使用平均分配
+ $columnSpec = str_repeat('X[1] ', $maxColCount);
+ }
+ } else {
+ // 如果 $str_list 为空,使用平均分配
+ $columnSpec = str_repeat('X[1] ', $maxColCount);
+ }
+ // 计算列宽比例(简单平均分配,可根据需要调整)
+// $columnSpec = str_repeat('X[1] ', $maxColCount);
+ $columnSpec = rtrim($columnSpec);
+
+ // 整理title信息
+ $title = strip_tags($table_info['title']);
+ $label = "tab-".$table_info['amt_id'];
+
+ $notes = strip_tags($table_info['note']);
+
+
+ //确定是单栏还是双栏的表格
+ $oneRowString = 0;
+ foreach ($str_list as $v){
+ $oneRowString += $v;
+ }
+ $table_ss = $oneRowString < 50 ? "tmrtable" : "tmrtable*";
+
+
+ // 开始构建LaTeX代码
+ $latex = [];
+ $latex[] = "\\begin{".$table_ss."}{".$this->convertToLatex($title,$references)."}{".$label."}{".$columnSpec."}{1}{".$notes."}";
+
+ // 遍历表格数据,生成每一行
+ foreach ($tableData as $rowIndex => $row) {
+ $cells = [];
+ $currentCol = 0; // 记录当前处理到的列位置
+
+ // 处理当前行的每个单元格
+ foreach ($row as $cell) {
+ // 处理单元格文本:移除HTML标签,替换为LaTeX粗体
+ $text = $this->convertToLatex($cell['text'], $references);
+
+ // 处理合并单元格:跨列(colspan)和跨行(rowspan)
+ $colspan = $cell['colspan'] ?? 1;
+ $rowspan = $cell['rowspan'] ?? 1;
+
+ $cellContent = $text;
+
+ // 处理跨列(使用tabularray的c选项,跨多列)
+ if ($colspan > 1 && $rowspan > 1) {
+ // 跨行跨列
+ $cellContent = "\\SetCell[c={$colspan},r={$rowspan}]{l,bg=white} {$cellContent}";
+ } elseif ($colspan > 1) {
+ // 仅跨列
+ $cellContent = "\\SetCell[c={$colspan}]{l,bg=white} {$cellContent}";
+ } elseif ($rowspan > 1) {
+ // 仅跨行
+ $cellContent = "\\SetCell[r={$rowspan}]{l,bg=white} {$cellContent}";
+ }
+
+ $cells[] = $cellContent;
+
+ // 如果是跨列单元格,跳过后续的colspan-1个位置
+ $currentCol += $colspan;
+ }
+
+ // 拼接单元格,行尾用\\
+ $rowContent = implode(' & ', $cells) . " \\\\";
+ $latex[] = " {$rowContent}";
+ }
+
+ $latex[] = "\\end{".$table_ss."}";
+
+ // 拼接所有行,返回LaTeX代码
+ return implode("\n", $latex);
+ }
+
+
+ function extractPureTitle(string $title): string
+ {
+ // 正则表达式说明:
+ // ^Table\s+ :匹配以Table开头(不区分大小写),后跟一个或多个空格
+ // [\d.]+ :匹配一个或多个数字或小数点(支持1、1.2、2.3.4等编号)
+ // \s* :匹配零个或多个空格(处理编号后的空格)
+ // i :不区分大小写匹配
+ $pattern = '/^Table\s+[\d.]+\s*/i';
+
+ // 替换匹配的前缀为空字符串
+ $pureTitle = preg_replace($pattern, '', $title);
+
+ // 去除首尾多余的空格(处理边界情况)
+ return trim($pureTitle);
+ }
+
+
+
+
private function authorFormate($p_article_id)
{
// $authors = $this->article_author_obj->where('article_id', $article_id)->where('state', 0)->select();