参考文献作者堆叠

参考文献相关性检测
作者ai写作辅助检测工作
This commit is contained in:
wyn
2026-07-15 10:49:05 +08:00
parent da71dfc04e
commit 8785610e6d
27 changed files with 10008 additions and 204 deletions

View File

@@ -2345,7 +2345,7 @@ class ReferenceCheckService
}
$slice = $this->buildCitationContextText($raw, $extendedStart, $textEnd);
$slice = ltrim($slice, ". \t\n\r");
$slice = ltrim($slice, "., \t\n\r");
if (trim($slice) === '') {
return $fallback;
}
@@ -3894,9 +3894,13 @@ class ReferenceCheckService
$hasPriorCiteInParagraph = ($prevTagEnd > $paragraphStart);
$sentenceStart = $this->findSentenceStart($content, $tagStart);
// 段内首个引用:整段到标签前;后续引用:取「本句」起点(可早于上一标签),避免只剩 “and external environment” 再误用标签后文本
// 段内首个引用:整段到标签前;后续引用:不早于上一标签结束,并可向前扩展若干句覆盖紧邻 claim
if ($hasPriorCiteInParagraph) {
$localStart = max($paragraphStart, $sentenceStart);
$anchor = max($prevTagEnd, $sentenceStart);
$localStart = $this->extendContextStartBackward($content, $anchor, $prevTagEnd, 2);
if ($localStart >= $prevTagEnd) {
$localStart = $this->advancePastPriorCitationBoundary($content, $localStart);
}
} else {
$localStart = $this->capContextStartBeforeTag($content, $tagStart, $paragraphStart);
}
@@ -3904,19 +3908,34 @@ class ReferenceCheckService
// 默认:引用标签前的论述
$localEnd = $tagStart;
$originalText = $this->buildCitationContextText($content, $localStart, $localEnd);
$before = $originalText;
$isAuthorOnly = $this->isAuthorOnlyLeadIn($before);
// 仅段内首个引用、且标签前极短(如句末 ICU nurses [14])时,才改用标签后片段;同段多引禁止标签后截取(会错取下一句)
$allowTrailing = !$hasPriorCiteInParagraph;
if ($allowTrailing && (
!$this->isMeaningfulCitationContext($originalText)
|| $this->shouldUseTrailingCitationContext($content, $localStart, $tagStart, $tagEnd)
)) {
// 作者缩写引用Chen [33]、Zou [24] found that...):向前扩展到段落/句群,必要时并入标签后叙述
if ($isAuthorOnly) {
$localStart = $this->capContextStartBeforeTag($content, $tagStart, $paragraphStart);
$trailEnd = ($nextTagStart < $sentenceEnd) ? $nextTagStart : $sentenceEnd;
$trailText = $this->buildCitationContextText($content, $tagEnd, $trailEnd);
if ($this->isMeaningfulCitationContext($trailText)) {
$localStart = $tagEnd;
$localEnd = $trailEnd;
$originalText = $trailText;
} else {
$localEnd = $tagStart;
}
$originalText = $this->buildCitationContextText($content, $localStart, $localEnd);
} else {
// 仅段内首个引用、且标签前极短时,才改用标签后片段;同段多引禁止(会错取下一句)
$allowTrailing = !$hasPriorCiteInParagraph;
if ($allowTrailing && (
!$this->isMeaningfulCitationContext($originalText)
|| $this->shouldUseTrailingCitationContext($content, $localStart, $tagStart, $tagEnd)
)) {
$trailEnd = ($nextTagStart < $sentenceEnd) ? $nextTagStart : $sentenceEnd;
$trailText = $this->buildCitationContextText($content, $tagEnd, $trailEnd);
if ($this->isMeaningfulCitationContext($trailText)) {
$localStart = $tagEnd;
$localEnd = $trailEnd;
$originalText = $trailText;
}
}
}
@@ -3934,6 +3953,22 @@ class ReferenceCheckService
return [$localStart, $localEnd, $originalText];
}
/**
* 标签前仅有作者姓氏/缩写(如 Chen、Zou时视为作者引导引用需扩展上下文。
*/
private function isAuthorOnlyLeadIn($text)
{
$text = trim((string)$text);
if ($text === '') {
return false;
}
if (mb_strlen($text) < 25) {
return true;
}
return preg_match('/^[A-Z][a-zA-Z\'\-]{0,24}\.?$/u', $text) === 1;
}
/**
* 标签前仅有作者缩写等极短片段时,改用标签后上下文
*/
@@ -4097,6 +4132,27 @@ class ReferenceCheckService
return $start;
}
/**
* 上一引用标签结束后,跳过空白及紧随其后的句末/分句标点(如 "[1]. And"、"[2], accounting"
*/
private function advancePastPriorCitationBoundary($content, $pos)
{
$pos = intval($pos);
$len = strlen($content);
while ($pos < $len) {
while ($pos < $len && ($content[$pos] === ' ' || $content[$pos] === "\t" || $content[$pos] === "\n" || $content[$pos] === "\r")) {
$pos++;
}
if ($pos < $len && ($content[$pos] === '.' || $content[$pos] === ',')) {
$pos++;
continue;
}
break;
}
return $pos;
}
/**
* 过滤仅标点、过短或无字母/汉字的上下文(如去掉标签后只剩 "."
*/