参考文献格式

This commit is contained in:
wangjinlei
2026-08-05 18:36:17 +08:00
parent 2db6f170fe
commit d72b16d9e8
7 changed files with 563 additions and 112 deletions

View File

@@ -3,7 +3,6 @@
namespace app\common;
use think\Db;
use think\Env;
use think\Queue;
/**
@@ -19,9 +18,13 @@ class ReferenceDispatchService
/** @var ReferenceTypeClassifier */
private $classifier;
/** @var ReferenceMetadataService */
private $metadata;
public function __construct()
{
$this->classifier = new ReferenceTypeClassifier(['use_llm' => true]);
$this->metadata = new ReferenceMetadataService();
}
/**
@@ -72,23 +75,23 @@ class ReferenceDispatchService
return;
}
$crossref = new CrossrefService([
'mailto' => trim((string)Env::get('crossref_mailto', '')),
]);
$summary = null;
$crossrefType = '';
$meta = null;
$typeHint = '';
if (trim((string)$refer['refer_doi']) !== '') {
$doiNorm = $this->normalizeDoi($refer['refer_doi']);
if ($doiNorm !== '') {
$summary = $crossref->fetchWorkSummary($doiNorm);
if ($summary && !empty($summary['raw']['type'])) {
$crossrefType = (string)$summary['raw']['type'];
$meta = $this->metadata->fetchByDoi($doiNorm);
if (is_array($meta)) {
$typeHint = trim((string)$meta['crossref_type']);
// Crossref 无 type 但 PubMed 收录时,给分类器一个等价的 Crossref type
if ($typeHint === '' && $meta['type'] === ReferenceTypeClassifier::TYPE_JOURNAL) {
$typeHint = 'journal-article';
}
}
}
}
$typeInfo = $this->classifier->classify((string)$refer['refer_content'], $crossrefType);
$typeInfo = $this->classifier->classify((string)$refer['refer_content'], $typeHint);
$dispatchType = $this->classifier->normalizeDispatchType($typeInfo['type']);
Db::name('production_article_refer')->where('p_refer_id', $refer['p_refer_id'])->update([
@@ -99,7 +102,7 @@ class ReferenceDispatchService
switch ($dispatchType) {
case ReferenceTypeClassifier::TYPE_BOOK:
$this->processBookRefer($refer, $summary, $crossref);
$this->processBookRefer($refer, $meta);
break;
case ReferenceTypeClassifier::TYPE_OTHER:
$this->processOtherRefer($refer);
@@ -161,7 +164,7 @@ class ReferenceDispatchService
/**
* book结构化字段DOI 仅用于补数据
*/
private function processBookRefer(array $refer, $summary, CrossrefService $crossref)
private function processBookRefer(array $refer, $meta)
{
$pReferId = intval($refer['p_refer_id']);
$content = (string)$refer['refer_content'];
@@ -171,14 +174,18 @@ class ReferenceDispatchService
'update_time' => time(),
];
if (is_array($summary) && !empty($summary['raw'])) {
$raw = $summary['raw'];
$authorCitation = $crossref->getAuthorsCitation($raw, 3);
$summary = is_array($meta) ? $meta['crossref_summary'] : null;
$raw = is_array($summary) ? ($summary['raw'] ?? []) : [];
$hasMeta = is_array($meta)
&& (trim((string)$meta['title']) !== '' || trim((string)$meta['author']) !== '');
if ($hasMeta) {
$authorCitation = trim((string)$meta['author']);
$update['author'] = $authorCitation !== '' ? rtrim($authorCitation, '.') . '.' : '';
$update['title'] = trim((string)($summary['title'] ?? ''));
$update['joura'] = $this->extractBookPublisher($raw, $summary);
$update['dateno'] = $this->extractBookDateno($raw);
$isbn = $this->extractIsbnFromRaw($raw);
$update['title'] = trim((string)$meta['title']);
$update['joura'] = !empty($raw) ? $this->extractBookPublisher($raw, $summary) : '';
$update['dateno'] = !empty($raw) ? $this->extractBookDateno($raw) : '';
$isbn = !empty($raw) ? $this->extractIsbnFromRaw($raw) : '';
if ($isbn === '' && !empty($refer['refer_doi'])) {
$doi = $this->normalizeDoi($refer['refer_doi']);
$isbn = $doi !== '' ? 'https://doi.org/' . $doi : '';