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();