参考文献作者堆叠

参考文献相关性检测
作者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

@@ -13,6 +13,8 @@ use think\Env;
use think\Queue;
use app\common\ReferenceCheckService;
use app\common\ReferenceRelevanceCheckService;
use app\common\ReferenceStackingStatsService;
use app\common\ReferenceReferAuthorService;
use app\common\DbReconnectHelper;
/**
* @title 参考文献
@@ -1818,5 +1820,117 @@ class References extends Base
return $frag;
}
/**
* 参考文献引用堆叠统计(同作者>15%、同刊>20%、自引>10%,实时计算)
*
* POST/GET: p_article_id必填
*/
public function referenceStackingStats()
{
$aParam = $this->request->post();
if (empty($aParam)) {
$aParam = $this->request->param();
}
$iPArticleId = empty($aParam['p_article_id']) ? 0 : intval($aParam['p_article_id']);
if ($iPArticleId <= 0) {
return json_encode(array('status' => 2, 'msg' => 'Please select an article'));
}
try {
$svc = new ReferenceStackingStatsService();
$result = $svc->getThresholdStackingByPArticleId($iPArticleId);
return jsonSuccess($result);
} catch (\Exception $e) {
return jsonError($e->getMessage());
}
}
/**
* 测试:同步参考文献作者明细到 t_production_article_refer_author
* POST/GET: p_article_id必填, p_refer_id可选仅同步单条, include_authors可选默认 01 返回作者明细), sleep_ms可选默认 120
*/
public function referenceReferAuthorSyncTest()
{
$aParam = $this->request->post();
if (empty($aParam)) {
$aParam = $this->request->param();
}
$iPArticleId = empty($aParam['p_article_id']) ? 0 : intval($aParam['p_article_id']);
if ($iPArticleId <= 0) {
return json_encode(array('status' => 2, 'msg' => 'Please select an article'));
}
$iPReferId = empty($aParam['p_refer_id']) ? 0 : intval($aParam['p_refer_id']);
$includeAuthors = !empty($aParam['include_authors']) && intval($aParam['include_authors']) === 1;
$sleepMs = isset($aParam['sleep_ms']) ? max(0, intval($aParam['sleep_ms'])) : 120;
try {
$svc = new ReferenceReferAuthorService();
if ($iPReferId > 0) {
$refer = Db::name('production_article_refer')
->where('p_refer_id', $iPReferId)
->where('p_article_id', $iPArticleId)
->where('state', 0)
->find();
if (empty($refer)) {
return jsonError('Reference not found');
}
$refUtil = new ReferenceCheckService();
$doi = $refUtil->extractDoiFromRefer($refer);
$count = 0;
if ($doi !== '') {
$crossref = new CrossrefService([
'mailto' => trim((string)Env::get('crossref_mailto', '')),
]);
$summary = $crossref->fetchWorkSummary($doi);
if ($summary === null || empty($summary['doi'])) {
$summary = ['doi' => $doi, 'raw' => []];
}
$count = $svc->syncFromWorkSummary($iPReferId, $iPArticleId, $doi, $summary);
}
if ($count <= 0) {
$count = $svc->syncFromReferAuthorField($iPReferId, $iPArticleId, (string)($refer['author'] ?? ''));
}
$result = [
'p_article_id' => $iPArticleId,
'p_refer_id' => $iPReferId,
'reference_no' => intval($refer['index']) + 1,
'doi' => $doi,
'authors' => $count,
'synced' => $count > 0 ? 1 : 0,
'failed' => $count > 0 ? 0 : 1,
];
} else {
$result = $svc->syncByPArticleId($iPArticleId, ['sleep_ms' => $sleepMs]);
}
if ($includeAuthors) {
$query = Db::name('production_article_refer_author')
->alias('a')
->join('production_article_refer r', 'r.p_refer_id = a.p_refer_id', 'LEFT')
->field('a.p_refer_id,r.index,a.author_seq,a.display_name,a.citation_name,a.orcid,a.openalex_id,a.identity_source')
->where('a.p_article_id', $iPArticleId);
if ($iPReferId > 0) {
$query->where('a.p_refer_id', $iPReferId);
}
$rows = $query->order('r.index asc, a.author_seq asc')->select();
foreach ($rows as &$row) {
$row['reference_no'] = intval($row['index']) + 1;
unset($row['index']);
}
unset($row);
$result['author_rows'] = $rows;
}
return jsonSuccess($result);
} catch (\Exception $e) {
return jsonError($e->getMessage());
}
}
}