table latex create

This commit is contained in:
wangjinlei
2025-12-29 16:08:36 +08:00
parent 16f58319ba
commit c59d60e146

View File

@@ -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忽略并移除<tr>、</tr>和<nbsp/>标签
$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');
// 移除<tr>和</tr>(不区分大小写,处理可能的空格)
$content = preg_replace('/<\/?tr\s*>/i', '', $content);
// 移除<nbsp/>
@@ -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('/(?:<blue>)?\[(\d+(?:[-,]\d+)*)\](?:<\/blue>)?/', $content, $matches)) {
// 去除匹配中的 <blue> 和 </blue>
$cleanedMatch = str_replace(['<blue>', '</blue>'], '', $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();