Compare commits
2 Commits
b217ab03fd
...
f31b75c85c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f31b75c85c | ||
|
|
67dc74575d |
@@ -789,6 +789,9 @@ class Production extends Base
|
||||
if ($p_info['file_sub2'] != '') {
|
||||
$pra['file_sub2'] = $p_info['file_sub2'];
|
||||
}
|
||||
if($p_info['file_sub_table'] != ''){
|
||||
$pra['file_sub_table'] = $p_info['file_sub_table'];
|
||||
}
|
||||
if ($p_info['file_cdf'] != '') {
|
||||
$pra['file_cdf'] = $p_info['file_cdf'];
|
||||
}
|
||||
@@ -2150,6 +2153,9 @@ class Production extends Base
|
||||
$latexLines[] = " \\centering";
|
||||
$latexLines[] = " \\includegraphics[width=0.9\\textwidth]{" . $fileName . "}";
|
||||
}
|
||||
//添加图片的label
|
||||
$latexLines[] = " \\label{fig:" . $ami_id . "}";
|
||||
|
||||
|
||||
if(!empty($ami_info['title'])&&!empty($ami_info['note'])){
|
||||
$escapedTitle = '{\fontspec{Calibri}\footnotesize\bfseries\color{figerTitleColor} '.$this->convertToLatex(preg_replace('/^Figure\s+\d+\s*/i', '', $ami_info['title']),[]).'}\\\\';
|
||||
@@ -2239,7 +2245,7 @@ class Production extends Base
|
||||
|
||||
|
||||
|
||||
public function convertToLatex($content,$references) {
|
||||
public function convertToLatex($content,$references,$check_refer = true) {
|
||||
// 空内容直接返回
|
||||
if (empty(trim($content))) {
|
||||
return '';
|
||||
@@ -2271,7 +2277,7 @@ class Production extends Base
|
||||
$content = $this->removeIgnoredTags($content);
|
||||
|
||||
// 步骤2:解析剩余标签并生成LaTeX内容
|
||||
$latexContent = $this->textRenderCreate($content,$refArray);
|
||||
$latexContent = $this->textRenderCreate($content,$refArray,$check_refer);
|
||||
// $latexContent = $this->convertReferencesToLatex($content, $refArray);
|
||||
|
||||
return $latexContent;
|
||||
@@ -2296,7 +2302,7 @@ class Production extends Base
|
||||
* @param string $content 待解析的内容
|
||||
* @return string 解析后的LaTeX内容
|
||||
*/
|
||||
private function textRenderCreate($content,$references) {
|
||||
private function textRenderCreate($content,$references,$check_refer) {
|
||||
$latex = '';
|
||||
while (!empty($content)) {
|
||||
$nextTag = $this->determineNextTag($content);
|
||||
@@ -2332,7 +2338,7 @@ class Production extends Base
|
||||
|
||||
|
||||
//这里处理引用
|
||||
if (preg_match('/(?:<blue>)?\[(\d+(?:[-,]\d+)*)\](?:<\/blue>)?/', $tagWrappedContent, $matches)) {
|
||||
if ($check_refer&&preg_match('/(?:<blue>)?\[(\d+(?:[-,]\d+)*)\](?:<\/blue>)?/', $tagWrappedContent, $matches)) {
|
||||
// 去除匹配中的 <blue> 和 </blue>
|
||||
$cleanedMatch = str_replace(['<blue>', '</blue>'], '', $matches[0]);
|
||||
// 提取引用编号部分(去掉方括号)
|
||||
@@ -2473,6 +2479,39 @@ class Production extends Base
|
||||
$styledContent = $this->applyStyleToContent($latexContent, $style);
|
||||
$textRenderData[] = $styledContent;
|
||||
}
|
||||
}elseif ($tag === 'myfigure'){//对图片的正文处理
|
||||
$pattern = '/data-id=["\'](\d+)["\']/';
|
||||
if (preg_match($pattern, $now, $matches)) {
|
||||
$figureId = $matches[1];
|
||||
//处理查找到id之后的逻辑
|
||||
$textRenderData[] = "\\ref{fig:".$figureId."}";
|
||||
}
|
||||
}elseif ($tag === 'mytable'){//对表格的正文处理
|
||||
$pattern = '/data-id=["\'](\d+)["\']/';
|
||||
if (preg_match($pattern, $now, $matches)) {
|
||||
$tableId = $matches[1];
|
||||
$cache_table = $this->article_main_table_obj->where("amt_id",$tableId)->find();
|
||||
if(!$cache_table){
|
||||
return ;
|
||||
}
|
||||
$cache_list = $this->article_main_obj
|
||||
->join("t_article_main_table","t_article_main_table.amt_id=t_article_main.amt_id","left")
|
||||
->where("t_article_main.article_id",$cache_table['article_id'])
|
||||
->where("t_article_main.type",2)
|
||||
->where("CHAR_LENGTH(t_article_main_table.table_data)",">",6000)
|
||||
->order("t_article_main.sort")->select();
|
||||
$key_num = 0;
|
||||
foreach ($cache_list as $cache_key =>$cache_list_item){
|
||||
if($cache_list_item['amt_id']==$tableId){
|
||||
$key_num = $cache_key+1;
|
||||
}
|
||||
}
|
||||
if(strlen($cache_table['table_data'])>6000){
|
||||
$textRenderData[] = "\\textcolor[HTML]{".$this->colorMap['blue']."}{Supplementary Table ".$key_num."}}";
|
||||
}else{
|
||||
$textRenderData[] = "\\ref{tab:".$tableId."}";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// 应用当前标签的样式
|
||||
$this->addStyle($style, $tag);
|
||||
@@ -3330,10 +3369,323 @@ class Production extends Base
|
||||
}
|
||||
|
||||
|
||||
public function mytestlongtable(){
|
||||
$data = $this->request->post();
|
||||
$rule = new Validate([
|
||||
"table_id"=>"require"
|
||||
]);
|
||||
if(!$rule->check($data)){
|
||||
return jsonError($rule->getError());
|
||||
}
|
||||
$res = $this->longTablePdfCreate([$data['table_id'], $data['table_id']+1]);
|
||||
return json($res);
|
||||
}
|
||||
|
||||
public function longTablePdfCreate(array $table_ids)
|
||||
{
|
||||
|
||||
// 获取表格数据
|
||||
$table_info_f = $this->article_main_table_obj->where("amt_id", $table_ids[0])->find();
|
||||
if (!$table_info_f) {
|
||||
return jsonError("Table not found");
|
||||
}
|
||||
$article_id = $table_info_f['article_id'];
|
||||
$production_info = $this->production_article_obj->where("article_id", $article_id)->find();
|
||||
if (!$production_info) {
|
||||
return jsonError("Production not found");
|
||||
}
|
||||
$references = $this->production_article_refer_obj->where("p_article_id", $production_info['p_article_id'])->select();
|
||||
// 解析表格数据
|
||||
// $tableData = json_decode($table_info['table_data'], true);
|
||||
// if (!$tableData) {
|
||||
// return jsonError("Invalid table data");
|
||||
// }
|
||||
|
||||
// $latex = [];
|
||||
$tex_content = "\\documentclass[8pt]{article}\n";
|
||||
$tex_content .= "\\usepackage[UTF8]{ctex} % 设置字体\n";
|
||||
$tex_content .= "\\usepackage{tabularray} % longtblr核心宏包\n";
|
||||
$tex_content .= "\\usepackage{xcolor} % 颜色支持\n\n";
|
||||
$tex_content .= "\\usepackage{geometry} \n";
|
||||
$tex_content .= "\\usepackage{textcomp} \n";
|
||||
$tex_content .= "\\usepackage[english]{babel} \n";
|
||||
$tex_content .= "\\geometry{
|
||||
a4paper, % A4纸张
|
||||
left=1.5cm, % 左页边距
|
||||
right=1.5cm, % 右页边距
|
||||
top=2cm, % 上页边距
|
||||
bottom=2cm, % 下页边距
|
||||
}";
|
||||
$tex_content .= "\\linespread{1.05}";
|
||||
$tex_content .= "\\definecolor{tablegray}{RGB}{250,231,232}\n\n";
|
||||
$tex_content .= "\\begin{document}\n\n";
|
||||
foreach ($table_ids as $value){
|
||||
$latex = [];
|
||||
$table_info = $this->article_main_table_obj->where("amt_id", $value)->find();
|
||||
$tableData = json_decode($table_info['table_data'], true);
|
||||
if (!$tableData) {
|
||||
continue;
|
||||
}
|
||||
$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);
|
||||
}
|
||||
// 整理title信息
|
||||
$title = strip_tags($table_info['title']);
|
||||
$label = "tab-".$table_info['amt_id'];
|
||||
// 开始构建LaTeX代码
|
||||
// $latex = [];
|
||||
|
||||
// 遍历表格数据,生成每一行
|
||||
$table = [];
|
||||
foreach ($tableData as $rowIndex => $row) {
|
||||
$table[$rowIndex] = [];
|
||||
$currentCol = 0; // 记录当前处理到的列位置
|
||||
|
||||
// 处理当前行的每个单元格
|
||||
foreach ($row as $cell) {
|
||||
while (isset($table[$rowIndex][$currentCol])){
|
||||
$currentCol += 1;
|
||||
}
|
||||
// 处理单元格文本:移除HTML标签,替换为LaTeX粗体
|
||||
$text = $this->convertToLatex($cell['text'], $references,false);
|
||||
|
||||
// 处理合并单元格:跨列(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}";
|
||||
$table[$rowIndex][$currentCol] = $cellContent;
|
||||
for($n_c=1;$n_c<$colspan;$n_c++){
|
||||
$table[$rowIndex][$currentCol+$n_c] = "";
|
||||
}
|
||||
for ($a_r=1;$a_r<$rowspan;$a_r++){
|
||||
for ($a_c=0;$a_c<$colspan;$a_c++){
|
||||
$table[$rowIndex+$a_r][$currentCol+$a_c] = "";
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ($colspan > 1) {
|
||||
// 仅跨列
|
||||
$cellContent = "\\SetCell[c={$colspan}]{l,bg=white} {$cellContent}";
|
||||
$table[$rowIndex][$currentCol] = $cellContent;
|
||||
for($n_c=1;$n_c<$colspan;$n_c++){
|
||||
$table[$rowIndex][$currentCol+$n_c] = "";
|
||||
}
|
||||
} elseif ($rowspan > 1) {
|
||||
// 仅跨行
|
||||
$cellContent = "\\SetCell[r={$rowspan}]{l,bg=white} {$cellContent}";
|
||||
$table[$rowIndex][$currentCol] = $cellContent;
|
||||
for ($a_r=1;$a_r<$rowspan;$a_r++){
|
||||
$table[$rowIndex+$a_r][$currentCol] = "";
|
||||
}
|
||||
}else{
|
||||
$table[$rowIndex][$currentCol] = $cellContent;
|
||||
}
|
||||
// 如果是跨列单元格,跳过后续的colspan-1个位置
|
||||
$currentCol += $colspan;
|
||||
}
|
||||
}
|
||||
foreach ($table as $row){
|
||||
$rowContent = implode(' & ', $row) . " \\\\";
|
||||
$latex[] = " {$rowContent}";
|
||||
}
|
||||
$tex_content .= "\t\\begin{longtblr}[\n";
|
||||
$tex_content .= "\t\tcaption = {" . $title . "},\n";
|
||||
$tex_content .= "\t\tlabel = {" . $label . "},\n";
|
||||
$tex_content .= "\t\t]{\n";
|
||||
$tex_content .= "\t\t\t% 你指定的列格式:自定义宽度比例 + 左对齐 + 防止文字溢出\n";
|
||||
$tex_content .= "\t\t\tcolspec={" . $columnSpec . "},\n";
|
||||
$tex_content .= "\t\t\twidth = \\textwidth, % 表格宽度占满行宽(配合X列生效)\n";
|
||||
$tex_content .= "\t\t\trowhead = 1, % 表头跨页重复\n";
|
||||
$tex_content .= "\t\t\t% 三线表核心配置\n";
|
||||
$tex_content .= "\t\t\thline{1} = {1pt}, % 顶线(粗)\n";
|
||||
$tex_content .= "\t\t\thline{2} = {0.5pt}, % 表头分隔线(细)\n";
|
||||
$tex_content .= "\t\t\thline{Z} = {1pt}, % 底线(粗)\n";
|
||||
$tex_content .= "\t\t\t% 隔行变色 + 样式优化\n";
|
||||
$tex_content .= "\t\t\trow{1} = {bg=gray!30, font=\\bfseries, abovesep=5pt, belowsep=5pt}, % 表头样式\n";
|
||||
$tex_content .= "\t\t\trow{even} = {bg=tablegray}, % 偶数行浅灰\n";
|
||||
$tex_content .= "\t\t\trow{odd} = {bg=white}, % 奇数行白色\n";
|
||||
$tex_content .= "\t\t\trowsep = 4pt, % 行间距\n";
|
||||
$tex_content .= "\t\t}\n";
|
||||
$tex_content .= "\t\t% 表头\n";
|
||||
$tex_content .= implode("\n", $latex);
|
||||
$tex_content .= "\n\t\\end{longtblr}\n\n";
|
||||
}
|
||||
$tex_content .= "\\end{document}";
|
||||
|
||||
|
||||
// echo $tex_content;
|
||||
|
||||
|
||||
// 创建输出目录
|
||||
$outputPath = ROOT_PATH . 'public' . DS . 'latex' . DS . 'tex_'.$article_id;
|
||||
if (!file_exists($outputPath)) {
|
||||
mkdir($outputPath, 0755, true);
|
||||
}
|
||||
|
||||
// 生成tex文件
|
||||
$tex_file = $outputPath . DS . 'table.tex';
|
||||
file_put_contents($tex_file, $tex_content);
|
||||
|
||||
$pdfFilePath = $outputPath . DS . 'table.pdf';
|
||||
|
||||
$success = $this->generatePdfFromTex($tex_file, $pdfFilePath);
|
||||
|
||||
if($success){
|
||||
$this->production_article_obj->where("p_article_id",$production_info['p_article_id'])->update(['file_sub_table'=>'tex_'.$article_id.DS."table.pdf"]);
|
||||
}
|
||||
$frag['success'] = $success;
|
||||
$frag['file'] = $pdfFilePath;
|
||||
return $frag;
|
||||
|
||||
// if ($success) {
|
||||
// return jsonSuccess([
|
||||
// 'pdf_file' => $pdfFilePath,
|
||||
// 'message' => 'PDF生成成功'
|
||||
// ]);
|
||||
// } else {
|
||||
// return jsonError('PDF生成失败');
|
||||
// }
|
||||
|
||||
// return $tex_file;
|
||||
// 返回文件路径
|
||||
// return jsonSuccess([
|
||||
// 'file' => $tex_file,
|
||||
// 'url' => '/public/latex/table_tex/table_' . $table_id . '.tex'
|
||||
// ]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 根据tex文件生成对应的pdf文件
|
||||
* @param string $texFilePath .tex文件路径
|
||||
* @param string $pdfFilePath 输出PDF文件路径
|
||||
* @return bool 是否生成成功
|
||||
*/
|
||||
public function generatePdfFromTex($texFilePath, $pdfFilePath)
|
||||
{
|
||||
try {
|
||||
// 检查.tex文件是否存在
|
||||
if (!file_exists($texFilePath)) {
|
||||
throw new Exception("LaTeX文件不存在: " . $texFilePath);
|
||||
}
|
||||
|
||||
// 确保输出目录存在
|
||||
$pdfDir = dirname($pdfFilePath);
|
||||
if (!is_dir($pdfDir)) {
|
||||
mkdir($pdfDir, 0755, true);
|
||||
}
|
||||
|
||||
// 方法1: 使用pdflatex命令(推荐)
|
||||
$command = "pdflatex -include-directory=" . dirname($texFilePath) .
|
||||
" -output-directory=" . $pdfDir . " " . escapeshellarg($texFilePath);
|
||||
|
||||
$output = [];
|
||||
$returnVar = 0;
|
||||
exec($command, $output, $returnVar);
|
||||
|
||||
// 检查命令执行结果
|
||||
if ($returnVar !== 0) {
|
||||
error_log("LaTeX to PDF conversion failed: " . implode("\n", $output));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查PDF文件是否生成成功
|
||||
if (!file_exists($pdfFilePath)) {
|
||||
error_log("PDF文件未生成: " . $pdfFilePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("生成PDF失败: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function escapeLatexSpecialCharsArr($text) {
|
||||
if (is_null($text) || $text === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$text = strval($text);
|
||||
|
||||
// 转义LaTeX特殊字符
|
||||
$search = ['\\', '&', '%', '$', '#', '_', '{', '}', '~', '^'];
|
||||
$replace = ['\\textbackslash{}', '\\&', '\\%', '\\$', '\\#', '\\_', '\\{', '\\}', '\\textasciitilde{}', '\\textasciicircum{}'];
|
||||
|
||||
$text = str_replace($search, $replace, $text);
|
||||
|
||||
// 处理换行符
|
||||
$text = str_replace(["\r\n", "\r", "\n"], ' ', $text);
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function myTableTest(){
|
||||
$references = $this->production_article_refer_obj->where("p_article_id",3328)->where("state",0)->order("index asc")->select();
|
||||
$res = $this->tableCovertLatex(1052,$references);
|
||||
$res = $this->tableCovertLatex(1047,$references);
|
||||
|
||||
echo $res;
|
||||
}
|
||||
@@ -3352,9 +3704,9 @@ class Production extends Base
|
||||
if (json_last_error() !== JSON_ERROR_NONE || !is_array($tableData) || empty($tableData)) {
|
||||
return "% 无效的JSON数据";
|
||||
}
|
||||
// if(strlen($table_info['table_data'])>6000){
|
||||
// return "执行附表程序";
|
||||
// }
|
||||
if(strlen($table_info['table_data'])>6000){
|
||||
return "执行附表程序";
|
||||
}
|
||||
|
||||
// 获取表格最大列数(遍历所有行,找到列数最大值,处理合并后列数变化的情况)
|
||||
$maxColCount = 0;
|
||||
@@ -3417,7 +3769,7 @@ class Production extends Base
|
||||
|
||||
// 整理title信息
|
||||
$title = strip_tags($table_info['title']);
|
||||
$label = "tab-".$table_info['amt_id'];
|
||||
$label = "tab:".$table_info['amt_id'];
|
||||
|
||||
$notes = $this->escapeLatexSpecialChars(trim(strip_tags($table_info['note']),"*. \t\n\r\0\x0B"));
|
||||
|
||||
@@ -3533,6 +3885,47 @@ class Production extends Base
|
||||
return trim($pureTitle);
|
||||
}
|
||||
|
||||
/**解决附加内容的表格内容
|
||||
* @return void
|
||||
*/
|
||||
private function tableForComp($table_data,$references){
|
||||
// 解码表格数据
|
||||
$tableData = json_decode($table_data, true);
|
||||
if (!$tableData || !isset($tableData['rows']) || !is_array($tableData['rows'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$latexLines = [];
|
||||
|
||||
// 开始longtblr环境
|
||||
$latexLines[] = "\\begin{longtblr}[";
|
||||
|
||||
// 设置表格基本属性
|
||||
$columns = count($tableData['rows'][0] ?? []);
|
||||
$colSpec = str_repeat('X[c]', $columns); // 默认居中列
|
||||
|
||||
$latexLines[] = " colspec={{$colSpec}},";
|
||||
$latexLines[] = " width=\\textwidth,";
|
||||
$latexLines[] = " hlines,";
|
||||
$latexLines[] = " vlines,";
|
||||
$latexLines[] = " rowhead=1,"; // 如果第一行是表头
|
||||
$latexLines[] = "]";
|
||||
|
||||
// 处理表格行
|
||||
foreach ($tableData['rows'] as $rowIndex => $row) {
|
||||
$rowCells = [];
|
||||
foreach ($row as $cell) {
|
||||
// 转换单元格内容中的特殊标签
|
||||
$convertedCell = $this->convertToLatex($cell, $references);
|
||||
$rowCells[] = $convertedCell;
|
||||
}
|
||||
$latexLines[] = " " . implode(" & ", $rowCells) . " \\\\";
|
||||
}
|
||||
|
||||
$latexLines[] = "\\end{longtblr}";
|
||||
|
||||
return implode("\n", $latexLines);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user