This commit is contained in:
wyn
2026-07-15 10:53:40 +08:00
8 changed files with 823 additions and 51 deletions

View File

@@ -54,7 +54,7 @@ class ProductionArticleRefer
return json_encode(['status' => 1,'msg' => 'Add to reference processing queue']);
}
/**
* 处理参考文献
* 处理参考文献(单个)
*
* @return void
*/
@@ -71,10 +71,17 @@ class ProductionArticleRefer
}
//查询未处理过的数据
$aWhere = ['p_refer_id' => $iPReferId,'p_article_id' => $iPArticleId,'state' => 0];
$aRefer = Db::name('production_article_refer')->field('refer_doi,refer_content')->where($aWhere)->find();
$aRefer = Db::name('production_article_refer')->field('refer_doi,refer_content,refer_type')->where($aWhere)->find();
if(empty($aRefer)){
return json_encode(array('status' => 2,'msg' => 'No reference records found'.json_encode($aParam)));
}
// 非期刊类型已在分流阶段处理,队列不再走期刊解析
$referType = strtolower(trim((string)($aRefer['refer_type'] ?? 'journal')));
if (in_array($referType, ['book', 'other'], true)) {
return json_encode(['status' => 1, 'msg' => 'Skipped non-journal reference']);
}
if(empty($aRefer['refer_doi'])){
return json_encode(['status' => 4,'msg' => 'Reference DOI is empty'.json_encode($aParam)]);
}
@@ -89,40 +96,48 @@ class ProductionArticleRefer
]);
$summary = $svc->fetchWorkSummary($doiNorm);
if ($summary !== null && !empty($summary['doi'])) {
$update_a = [];
$title = trim((string)($summary['title'] ?? ''));
$jouraRaw = trim((string)($summary['joura'] ?? ''));
// 姓全写 + 名首字母,超过 3 个作者取前 3 个 + et al
$authorCitation = $svc->getAuthorsCitation($summary['raw'] ?? [], 3);
$dateno = trim((string)($summary['dateno'] ?? ''));
$doilink = trim((string)($summary['doilink'] ?? ''));
$update_a['title'] = $title;
$update_a['author'] = $authorCitation !== '' ? $authorCitation . '.' : '';
$update_a['joura'] = $jouraRaw;
$update_a['dateno'] = $dateno;
$update_a['refer_type'] = "journal";
$update_a['is_ja'] = 1;
$update_a['doilink'] = $doilink;
$update_a['cs'] = 1;
$update_a['update_time'] = time();
$update_a['is_deal'] = 1;
try {
(new ReferenceReferAuthorService())->syncFromWorkSummary(
$iPReferId,
$iPArticleId,
$doiNorm,
$summary
);
} catch (\Throwable $e) {
\think\Log::error(
'ProductionArticleRefer sync refer authors failed p_refer_id='
. $iPReferId . ' ' . $e->getMessage()
);
// 英文优先兜底:若 CrossRef 结果的标题/期刊/作者仍含中日韩字符,
// 说明该 DOI 元数据是中文,放弃 CrossRef 路径,改走下方 citation.doi.org(lang=en-US)
$hasCjk = $svc->hasCjk($title) || $svc->hasCjk($jouraRaw) || $svc->hasCjk($authorCitation);
if (!$hasCjk) {
$update_a = [];
$dateno = trim((string)($summary['dateno'] ?? ''));
$doilink = trim((string)($summary['doilink'] ?? ''));
$update_a['title'] = $title;
$update_a['author'] = $authorCitation !== '' ? $authorCitation . '.' : '';
$update_a['joura'] = $jouraRaw;
$update_a['dateno'] = $dateno;
// CrossRef 的 type 最权威,据此确定参考文献类型,未命中回退 journal
$crossrefType = isset($summary['raw']['type']) ? $summary['raw']['type'] : '';
$mappedType = (new ReferenceTypeClassifier())->mapCrossrefType($crossrefType);
$update_a['refer_type'] = $mappedType !== '' ? $mappedType : "journal";
$update_a['is_ja'] = 1;
$update_a['doilink'] = $doilink;
$update_a['cs'] = 1;
$update_a['update_time'] = time();
$update_a['is_deal'] = 1;
try {
(new ReferenceReferAuthorService())->syncFromWorkSummary(
$iPReferId,
$iPArticleId,
$doiNorm,
$summary
);
} catch (\Throwable $e) {
\think\Log::error(
'ProductionArticleRefer sync refer authors failed p_refer_id='
. $iPReferId . ' ' . $e->getMessage()
);
}
Db::name('production_article_refer')->where(['p_refer_id' => $iPReferId])->limit(1)->update($update_a);
return json_encode(['status' => 1,'msg' => 'Update successful']);
}
Db::name('production_article_refer')->where(['p_refer_id' => $iPReferId])->limit(1)->update($update_a);
return json_encode(['status' => 1,'msg' => 'Update successful']);
}
//结束---用crossref接口的方式处理数据
@@ -135,7 +150,13 @@ class ProductionArticleRefer
$res = myGet($url);
$frag = trim(substr($res, strpos($res, '.') + 1));
if(empty($frag)){
$aUpdate = ['refer_frag' => $aRefer['refer_content'],'refer_type' => 'other','is_deal' => 1,'update_time' => time()];
// 依据作者原文识别类型;仅在识别出具体非期刊类型时覆盖,否则保持 other
$referType = 'other';
$typeInfo = (new ReferenceTypeClassifier())->classify((string)$aRefer['refer_content']);
if (in_array($typeInfo['type'], ['book','conference','thesis','web'], true)) {
$referType = $typeInfo['type'];
}
$aUpdate = ['refer_frag' => $aRefer['refer_content'],'refer_type' => $referType,'is_deal' => 1,'update_time' => time()];
$aWhere = ['p_refer_id' => $iPReferId];
$result = Db::name('production_article_refer')->where($aWhere)->limit(1)->update($aUpdate);
//写入通过AI获取参考文献详情队列
@@ -148,6 +169,11 @@ class ProductionArticleRefer
if (mb_substr_count($frag, '.') != 3){
$f = $frag . " Available at: " . PHP_EOL . "https://doi.org/" . $aRefer['refer_doi'];
$update['refer_type'] = "other";
// 依据作者原文识别类型;仅在识别出具体非期刊类型时覆盖
$typeInfo = (new ReferenceTypeClassifier())->classify((string)$aRefer['refer_content']);
if (in_array($typeInfo['type'], ['book','conference','thesis','web'], true)) {
$update['refer_type'] = $typeInfo['type'];
}
$update['refer_frag'] = $f;
$update['cs'] = 1;
//写入通过AI获取参考文献详情队列
@@ -164,6 +190,11 @@ class ProductionArticleRefer
if ($joura == trim($bj[0])) {
}
$update['refer_type'] = "journal";
// 依据作者原文的强特征识别更精确的类型(禁用 LLM仅规则强命中才覆盖
$ruleType = (new ReferenceTypeClassifier(['use_llm' => false]))->classifyByRule((string)$aRefer['refer_content']);
if ($ruleType['confidence'] >= 0.8 && !in_array($ruleType['type'], ['journal','other'], true)) {
$update['refer_type'] = $ruleType['type'];
}
$update['is_ja'] = $joura == trim($bj[0]) ? 0 : 1;
$update['dateno'] = str_replace(' ', '', str_replace('-', '', trim($bj[1])));
//新增处理 期卷页码 20251127 start