队列调整

This commit is contained in:
chengxl
2025-10-14 14:55:44 +08:00
parent 24ca5df1e3
commit b3ee7de7ba

View File

@@ -82,15 +82,15 @@ class ProofReadService
if ($converted === false) { if ($converted === false) {
$posStart = 0; $posStart = 0;
$posEnd = min(20, strlen($originalContent)); $posEnd = min(20, strlen($originalContent));
$errors[] = $this->createError( // $errors[] = $this->createError(
'编码转换失败', // '编码转换失败',
'保留原始编码内容', // '保留原始编码内容',
"从[{$originalEncoding}]转换为UTF-8失败保留原始内容", // "从[{$originalEncoding}]转换为UTF-8失败保留原始内容",
$originalContent, // $originalContent,
$corrected, // $corrected,
$posStart, // $posStart,
$posEnd // $posEnd
); // );
} }
} }
@@ -213,7 +213,8 @@ class ProofReadService
$originalContent, $originalContent,
$currentCorrected, $currentCorrected,
$posStart, $posStart,
$posEnd $posEnd,
empty($rule['error_type']) ? '' : $rule['error_type']
); );
$processedHashes[$hash] = true; $processedHashes[$hash] = true;
$corrected = $currentCorrected; $corrected = $currentCorrected;
@@ -264,25 +265,30 @@ class ProofReadService
'pattern' => '~(\[\s*[-]?\d+\s*)\x{2014}\s*(\d+\s*\])~u', // 匹配长划线(—) 'pattern' => '~(\[\s*[-]?\d+\s*)\x{2014}\s*(\d+\s*\])~u', // 匹配长划线(—)
'replacement' => '$1-$2', // 替换为短划线(- 'replacement' => '$1-$2', // 替换为短划线(-
'verbatim_texts' => '带括号数字范围使用长划线(—)不规范', 'verbatim_texts' => '带括号数字范围使用长划线(—)不规范',
'explanation' => '带括号的数字范围应使用短划线-),如 [1-5]' 'explanation' => '带括号的数字范围应使用短划线[-]',
'error_type' => 'en-dash'
], ],
[ [
'pattern' => '~(\[\s*[-]?\d+\s*)-\s*(\d+\s*\])~u', // 匹配连接符(-)及可能的空格 'pattern' => '~(\[\s*[-]?\d+\s*)-\s*(\d+\s*\])~u', // 匹配连接符(-)及可能的空格
'replacement' => '$1-$2', // 统一为无空格短划线(- 'replacement' => '$1-$2', // 统一为无空格短划线(-
'verbatim_texts' => '带括号数字范围使用连接符(-)格式不规范', 'verbatim_texts' => '带括号数字范围使用连接符(-)格式不规范',
'explanation' => '带括号的数字范围应使用短划线-且前后无空格,如 [2-5]' 'explanation' => '带括号的数字范围应使用短划线[-]且前后无空格',
'error_type' => 'en-dash'
], ],
[ [
'pattern' => '~(\[\s*[-]?\d+)\s+-\s*(\d+\s*\])~u', // 短划线前多余空格 'pattern' => '~(\[\s*[-]?\d+)\s+-\s*(\d+\s*\])~u', // 短划线前多余空格
'replacement' => '$1-$2', // 移除前导空格 'replacement' => '$1-$2', // 移除前导空格
'verbatim_texts' => '数字范围短划线前有多余空格', 'verbatim_texts' => '数字范围短划线前有多余空格',
'explanation' => '带括号数字范围的短划线-前不应留空格,如 [3-5]' 'explanation' => '带括号数字范围的短划线[-]前不应留空格',
'error_type' => 'en-dash'
], ],
[ [
'pattern' => '~(\[\s*[-]?\d+)\s*-\s+(\d+\s*\])~u', // 短划线后多余空格 'pattern' => '~(\[\s*[-]?\d+)\s*-\s+(\d+\s*\])~u', // 短划线后多余空格
'replacement' => '$1-$2', // 移除后导空格 'replacement' => '$1-$2', // 移除后导空格
'verbatim_texts' => '数字范围短划线后有多余空格', 'verbatim_texts' => '数字范围短划线后有多余空格',
'explanation' => '带括号数字范围的短划线-后不应留空格,如 [4-5]' 'explanation' => '带括号数字范围的短划线[-]后不应留空格',
'error_type' => 'en-dash'
], ],
// ====================== 2. 无括号数字范围规则(次高优先级,避免与减号运算规则冲突) ====================== // ====================== 2. 无括号数字范围规则(次高优先级,避免与减号运算规则冲突) ======================
@@ -290,13 +296,15 @@ class ProofReadService
'pattern' => '~(\b\d+)\s*—\s*(\d+\b)~u', // 匹配长划线(—) 'pattern' => '~(\b\d+)\s*—\s*(\d+\b)~u', // 匹配长划线(—)
'replacement' => '$1-$2', // 替换为短划线(- 'replacement' => '$1-$2', // 替换为短划线(-
'verbatim_texts' => '无括号数字范围使用长划线(—)不规范', 'verbatim_texts' => '无括号数字范围使用长划线(—)不规范',
'explanation' => '无括号的数字范围应使用短划线-),如 5-6' 'explanation' => '无括号的数字范围应使用短划线[-]',
'error_type' => 'bracket_en-dash'
], ],
[ [
'pattern' => '~(\b\d+)\s*-\s*(\d+\b)~u', // 匹配连接符(-)及可能的空格 'pattern' => '~(\b\d+)\s*-\s*(\d+\b)~u', // 匹配连接符(-)及可能的空格
'replacement' => '$1-$2', // 统一为无空格短划线(- 'replacement' => '$1-$2', // 统一为无空格短划线(-
'verbatim_texts' => '无括号数字范围使用连接符(-)格式不规范', 'verbatim_texts' => '无括号数字范围使用连接符(-)格式不规范',
'explanation' => '无括号的数字范围应使用短划线-且前后无空格,如 5-7' 'explanation' => '无括号的数字范围应使用短划线[-]且前后无空格',
'error_type' => 'bracket_en-dash'
], ],
// ====================== 3. 运算符空格规则(按「复合→独立」顺序,避免冲突) ====================== // ====================== 3. 运算符空格规则(按「复合→独立」顺序,避免冲突) ======================
@@ -304,7 +312,8 @@ class ProofReadService
'pattern' => '~(\S)\s*([<>!]=|===|!==)\s*(\S)~u', // 复合运算符(>=、<=、==、!=、===、!== 'pattern' => '~(\S)\s*([<>!]=|===|!==)\s*(\S)~u', // 复合运算符(>=、<=、==、!=、===、!==
'replacement' => '$1 $2 $3', 'replacement' => '$1 $2 $3',
'verbatim_texts' => '复合运算符前后空格不规范', 'verbatim_texts' => '复合运算符前后空格不规范',
'explanation' => '复合运算符>=、<=、==、!=、===、!==前后应各留一个空格,如 x >= 5' 'explanation' => '复合运算符[>=、<=、==、!=、===、!==]前后应各留一个空格',
'error_type' => 'composite_operator'
], ],
[ [
'pattern' => '~(?<!=|<|>|\*|\+|-|/)(\S+?)\s*=\s*(\S+?)(?!=|<|>|\*|\+|-|/)~u', 'pattern' => '~(?<!=|<|>|\*|\+|-|/)(\S+?)\s*=\s*(\S+?)(?!=|<|>|\*|\+|-|/)~u',
@@ -314,25 +323,29 @@ class ProofReadService
// 前后否定断言:排除与其他运算符(如+=、*=)的冲突 // 前后否定断言:排除与其他运算符(如+=、*=)的冲突
'replacement' => '$1 = $2', // 正确拼接“前内容 + 规范等号 + 后内容” 'replacement' => '$1 = $2', // 正确拼接“前内容 + 规范等号 + 后内容”
'verbatim_texts' => '等号前后空格不规范', 'verbatim_texts' => '等号前后空格不规范',
'explanation' => '独立等号=前后应各留一个空格,如 a = 3' // 移除无效的$1/$2 'explanation' => '独立等号[=]前后应各留一个空格',
'error_type' => 'equal'
], ],
[ [
'pattern' => '~(\d+)\s*\+\s*(\d+)~u', // 加法运算符(+ 'pattern' => '~(\d+)\s*\+\s*(\d+)~u', // 加法运算符(+
'replacement' => '$1 + $2', 'replacement' => '$1 + $2',
'verbatim_texts' => '加法运算符前后空格不规范', 'verbatim_texts' => '加法运算符前后空格不规范',
'explanation' => '加法运算符+前后应各留一个空格,如 2 + 3' 'explanation' => '加法运算符[+]前后应各留一个空格',
'error_type' => 'plus'
], ],
[ [
'pattern' => '~(\d+)\s*\*\s*(\d+)~u', // 乘法运算符(* 'pattern' => '~(\d+)\s*\*\s*(\d+)~u', // 乘法运算符(*
'replacement' => '$1 * $2', 'replacement' => '$1 * $2',
'verbatim_texts' => '乘法运算符前后空格不规范', 'verbatim_texts' => '乘法运算符前后空格不规范',
'explanation' => '乘法运算符*前后应各留一个空格,如 3 * 4' 'explanation' => '乘法运算符[*]前后应各留一个空格',
'error_type' => 'ride'
], ],
[ [
'pattern' => '~(\d+)\s*/\s*(\d+)~u', // 除法运算符(/ 'pattern' => '~(\d+)\s*/\s*(\d+)~u', // 除法运算符(/
'replacement' => '$1 / $2', 'replacement' => '$1 / $2',
'verbatim_texts' => '除法运算符前后空格不规范', 'verbatim_texts' => '除法运算符前后空格不规范',
'explanation' => '除法运算符/前后应各留一个空格,如 8 / 2' 'explanation' => '除法运算符[/]前后应各留一个空格',
'error_type' => 'except'
], ],
[ [
'pattern' => '~ 'pattern' => '~
@@ -347,7 +360,8 @@ class ProofReadService
~ux', // 减法运算符(-,仅处理纯数字减法,排除文献引用等场景) ~ux', // 减法运算符(-,仅处理纯数字减法,排除文献引用等场景)
'replacement' => '$1 - $2', 'replacement' => '$1 - $2',
'verbatim_texts' => '减法运算符前后空格不规范', 'verbatim_texts' => '减法运算符前后空格不规范',
'explanation' => '减法运算符-前后应各留一个空格非数字范围场景),如 5 - 3' 'explanation' => '减法运算符[-]前后应各留一个空格(非数字范围场景)',
'error_type' => 'reduce'
], ],
// ====================== 4. 特殊符号规则(低优先级,避免干扰核心格式) ====================== // ====================== 4. 特殊符号规则(低优先级,避免干扰核心格式) ======================
@@ -355,31 +369,38 @@ class ProofReadService
'pattern' => '~(\d+)\s+%~u', // 数字与百分号 'pattern' => '~(\d+)\s+%~u', // 数字与百分号
'replacement' => '$1%', 'replacement' => '$1%',
'verbatim_texts' => '数字与百分号之间有多余空格', 'verbatim_texts' => '数字与百分号之间有多余空格',
'explanation' => '数字与百分号%)之间不应留空格,如 50%' 'explanation' => '数字与百分号[%]之间有多余空格',
'error_type' => 'number_percentage'
], ],
[ [
'pattern' => '~(\(\s*\d+)\s+×\s+(\d+\s*\))~u', // 先匹配「(数字 × 数字)」场景(带括号) 'pattern' => '~(\(\s*\d+)\s+×\s+(\d+\s*\))~u', // 先匹配「(数字 × 数字)」场景(带括号)
'replacement' => '$1×$2', // 修正为「(数字×数字)」,如 (40×33) 'replacement' => '$1×$2', // 修正为「(数字×数字)」,如 (40×33)
'verbatim_texts' => '带括号的乘号表示倍数时前后有多余空格', 'verbatim_texts' => '带括号的乘号表示倍数时前后有多余空格',
'explanation' => '带括号的乘号×表示倍数关系时前后不应留空格,如 (3×5)' 'explanation' => '带括号的乘号[×]表示倍数关系时前后有多余空格',
'error_type' => 'multiple'
], ],
[ [
'pattern' => '~(\d+)\s+×\s+(\d+)~u', // 再匹配「数字 × 数字」场景(无括号) 'pattern' => '~(\d+)\s+×\s+(\d+)~u', // 再匹配「数字 × 数字」场景(无括号)
'replacement' => '$1×$2', 'replacement' => '$1×$2',
'verbatim_texts' => '乘号表示倍数时前后有多余空格', 'verbatim_texts' => '乘号表示倍数时前后有多余空格',
'explanation' => '乘号×表示倍数关系时前后不应留空格,如 3×5' 'explanation' => '乘号[×]表示倍数关系时前后不应留空格',
'error_type' => 'multiple'
], ],
[ [
'pattern' => '~(\d+)\s*\*\s*(\d+)~u', // 星号(*)转乘号(×) 'pattern' => '~(\d+)\s*\*\s*(\d+)~u', // 星号(*)转乘号(×)
'replacement' => '$1 × $2', 'replacement' => '$1 × $2',
'verbatim_texts' => '使用星号(*)作为乘法运算符不规范', 'verbatim_texts' => '使用星号(*)作为乘法运算符不规范',
'explanation' => '乘法运算应使用标准乘号(×)替代星号(*),并前后留空格,如 3 × 5' // 'explanation' => '乘法运算应使用标准乘号(×)替代星号(*),并前后留空格,如 3 × 5'
'explanation' => '乘法运算应使用标准乘号[×]替代星号[*]',
'error_type' => 'ride'
], ],
[ [
'pattern' => '~(\d+)\s+:\s+(\d+)~u', // 比值符号(: 'pattern' => '~(\d+)\s+:\s+(\d+)~u', // 比值符号(:
'replacement' => '$1:$2', 'replacement' => '$1:$2',
'verbatim_texts' => '比值符号前后有多余空格', 'verbatim_texts' => '比值符号前后有多余空格',
'explanation' => '比值符号:)前后不应留空格,如 1:2' 'explanation' => '比值符号[:]前后有多余空格',
'error_type' => 'biliel'
] ]
]; ];
} }
@@ -452,7 +473,7 @@ class ProofReadService
if (preg_match($decimalZeroPattern, $number, $numMatch)) { if (preg_match($decimalZeroPattern, $number, $numMatch)) {
$integerPart = $numMatch[1]; $integerPart = $numMatch[1];
$corrected = $integerPart; $corrected = $integerPart;
$errorType = 'invalid_zero';
if (!isset($replacements[$number])) { if (!isset($replacements[$number])) {
$replacements[$number] = $corrected; $replacements[$number] = $corrected;
@@ -465,11 +486,12 @@ class ProofReadService
$errors[] = $this->createError( $errors[] = $this->createError(
$number, $number,
$corrected, $corrected,
"删除小数点后无效零(原始:{$number} → 修正:{$corrected}", "删除小数点后无效零",
$originalContent, $originalContent,
$currentCorrected, $currentCorrected,
$posStart, $posStart,
$posEnd $posEnd,
$errorType
); );
} }
} }
@@ -489,15 +511,15 @@ class ProofReadService
); );
if (@preg_match($thousandPattern, '') === false) { if (@preg_match($thousandPattern, '') === false) {
$errors[] = $this->createError( // $errors[] = $this->createError(
'千分位正则错误', // '千分位正则错误',
'跳过千分位处理', // '跳过千分位处理',
"千分位正则错误: {$thousandPattern}", // "千分位正则错误: {$thousandPattern}",
$originalContent, // $originalContent,
$correctedContent, // $correctedContent,
-1, // -1,
-1 // -1
); // );
} else { } else {
$correctedContent = preg_replace_callback( $correctedContent = preg_replace_callback(
$thousandPattern, $thousandPattern,
@@ -516,6 +538,7 @@ class ProofReadService
$searchOffset = ($posEnd !== -1) ? $posEnd : $searchOffset + strlen($original); $searchOffset = ($posEnd !== -1) ? $posEnd : $searchOffset + strlen($original);
$currentCorrected = strtr($originalContent, $replacements); $currentCorrected = strtr($originalContent, $replacements);
$errorType = 'thousandth_separator';
$errors[] = $this->createError( $errors[] = $this->createError(
$original, $original,
$formatted, $formatted,
@@ -523,7 +546,9 @@ class ProofReadService
$originalContent, $originalContent,
$currentCorrected, $currentCorrected,
$posStart, $posStart,
$posEnd $posEnd,
$errorType
); );
return $formatted; return $formatted;
}, },
@@ -547,15 +572,15 @@ class ProofReadService
$searchOffset = ($posEnd !== -1) ? $posEnd : $searchOffset + strlen($marker); $searchOffset = ($posEnd !== -1) ? $posEnd : $searchOffset + strlen($marker);
$correctedContent = str_replace($marker, $original, $correctedContent); $correctedContent = str_replace($marker, $original, $correctedContent);
$errors[] = $this->createError( // $errors[] = $this->createError(
"残留URL/DOI占位符: {$marker}", // "残留URL/DOI占位符: {$marker}",
"已恢复为原始内容", // "已恢复为原始内容",
"URL/DOI恢复不完全已强制恢复", // "URL/DOI恢复不完全已强制恢复",
$originalContent, // $originalContent,
$correctedContent, // $correctedContent,
$posStart, // $posStart,
$posEnd // $posEnd
); // );
} }
} }
} }
@@ -655,15 +680,17 @@ class ProofReadService
// 错误信息去重(基于原始内容+修正内容哈希) // 错误信息去重(基于原始内容+修正内容哈希)
$errorHash = md5($original . $fixed); $errorHash = md5($original . $fixed);
$errorType = empty( $unit['full']) ? '' : $unit['full'];
if (!isset($errors[$errorHash])) { if (!isset($errors[$errorHash])) {
$errors[$errorHash] = $this->createError( $errors[$errorHash] = $this->createError(
$original, $original,
$fixed, $fixed,
"{$unit['description']}单位格式不规范{$errorReason}正确格式为'数字{$unit['abbr']}'", "{$unit['description']}单位格式不规范:{$errorReason},正确格式为[数字{$unit['abbr']}]",
$originalContent, $originalContent,
strtr($originalContent, $replaceMap + [$original => $fixed]), strtr($originalContent, $replaceMap + [$original => $fixed]),
$posStart, $posStart,
$posEnd $posEnd,
$errorType
); );
} }
@@ -726,7 +753,7 @@ class ProofReadService
// 标准毫升单位格式L大写 // 标准毫升单位格式L大写
$fixedFull = "{$prefix}mL"; $fixedFull = "{$prefix}mL";
$errorType = 'mL';
// 仅处理与标准格式不一致的场景 // 仅处理与标准格式不一致的场景
if ($originalFull !== $fixedFull) { if ($originalFull !== $fixedFull) {
// 计算错误内容在原始文本中的位置 // 计算错误内容在原始文本中的位置
@@ -740,11 +767,12 @@ class ProofReadService
$errors[$errorHash] = $this->createError( $errors[$errorHash] = $this->createError(
$originalFull, $originalFull,
$fixedFull, $fixedFull,
'毫升单位格式不规范标准写法为"mL"', '毫升单位格式不规范,标准写法为[mL]',
$originalContent, $originalContent,
strtr($originalContent, $replaceMap + [$originalFull => $fixedFull]), strtr($originalContent, $replaceMap + [$originalFull => $fixedFull]),
$posStart, $posStart,
$posEnd $posEnd,
$errorType
); );
} }
@@ -815,15 +843,17 @@ class ProofReadService
// 错误去重(哈希机制) // 错误去重(哈希机制)
$errorHash = md5($original . $fixed); $errorHash = md5($original . $fixed);
$errorType = 'P';
if (!isset($errors[$errorHash])) { if (!isset($errors[$errorHash])) {
$errors[$errorHash] = $this->createError( $errors[$errorHash] = $this->createError(
$original, $original,
$fixed, $fixed,
'显著性P值格式不规范P/p应使用斜体', '显著性P值格式不规范,P/p应使用斜体',
$originalContent, $originalContent,
strtr($originalContent, $replaceMap + [$original => $fixed]), strtr($originalContent, $replaceMap + [$original => $fixed]),
$posStart, $posStart,
$posEnd $posEnd,
$errorType
); );
} }
@@ -912,15 +942,18 @@ class ProofReadService
// 错误信息去重(基于单个错误片段的原始值+修正值哈希,避免重复记录) // 错误信息去重(基于单个错误片段的原始值+修正值哈希,避免重复记录)
$errorHash = md5($originalFull . $fixedFull); $errorHash = md5($originalFull . $fixedFull);
$errorType = 'No.';
if (!isset($errors[$errorHash])) { if (!isset($errors[$errorHash])) {
$errors[$errorHash] = $this->createError( $errors[$errorHash] = $this->createError(
$originalFull, // verbatim_texts具体错误片段 $originalFull, // verbatim_texts具体错误片段
$fixedFull, // revised_content错误片段的修正结果 $fixedFull, // revised_content错误片段的修正结果
'No. 格式不规范' . implode('', $errorReasons) . '正确格式为「No. 数字」', // explanation错误说明 'No. 格式不规范,正确格式为「No. 数字」', // explanation错误说明
// 'No. 格式不规范:' . implode('', $errorReasons) . '正确格式为「No. 数字」', // explanation错误说明
$originalContent, // original完整原始内容整个输入文本 $originalContent, // original完整原始内容整个输入文本
strtr($originalContent, $replaceMap), // corrected完整修正内容基于当前替换映射生成 strtr($originalContent, $replaceMap), // corrected完整修正内容基于当前替换映射生成
$posStart, // position_start错误起始位置 $posStart, // position_start错误起始位置
$posEnd // position_end错误结束位置 $posEnd, // position_end错误结束位置
$errorType //错误类型
); );
} }
} }
@@ -981,19 +1014,19 @@ class ProofReadService
switch (strtolower($abbrBase)) { switch (strtolower($abbrBase)) {
case 'fig': case 'fig':
$fullName = 'Figure'; $fullName = 'Figure';
$errorDesc = '图表标题使用缩写"Fig",应改为全称"Figure"'; $errorDesc = '图表标题使用缩写"Fig",正确:"Figure"';
break; break;
case 'figs': case 'figs':
$fullName = 'Figures'; $fullName = 'Figures';
$errorDesc = '图表标题复数使用缩写"Figs",应改为全称"Figures"'; $errorDesc = '图表标题复数使用缩写"Figs",正确:"Figures"';
break; break;
case 'tab': case 'tab':
$fullName = 'Table'; $fullName = 'Table';
$errorDesc = '表格标题使用缩写"Tab",应改为全称"Table"'; $errorDesc = '表格标题使用缩写"Tab",正确:"Table"';
break; break;
case 'tabs': case 'tabs':
$fullName = 'Tables'; $fullName = 'Tables';
$errorDesc = '表格标题复数使用缩写"Tabs",应改为全称"Tables"'; $errorDesc = '表格标题复数使用缩写"Tabs",正确:"Tables"';
break; break;
default: default:
$fullName = ''; $fullName = '';
@@ -1026,7 +1059,8 @@ class ProofReadService
$originalContent, $originalContent,
$currentCorrected, $currentCorrected,
$posStart, $posStart,
$posEnd $posEnd,
$fullName
); );
} }
@@ -1094,15 +1128,16 @@ class ProofReadService
/** /**
* 创建标准化错误信息 * 创建标准化错误信息
*/ */
private function createError($verbatim, $revised, $explanation,$original,$corrected, $position_start=-1, $position_end=-1) { private function createError($verbatim='', $revised='', $explanation='',$original='',$corrected='', $position_start=-1, $position_end=-1,$error_type='') {
return [ return [
'verbatim_texts' => $verbatim, 'verbatim_texts' => $verbatim,
'revised_content' => $revised, 'revised_content' => $revised,
'explanation' => $explanation, 'explanation' => $explanation,
'original' => $original, 'original' => $original,
'corrected' => $corrected, 'corrected' => $corrected,
'position_start' => $position_start, // 错误起始位置 'position_start' => $position_start,
'position_end' => $position_end // 错误结束位置 'position_end' => $position_end,
'error_type' => $error_type
]; ];
} }
/** /**