自动查重

This commit is contained in:
wangjinlei
2026-05-20 14:46:58 +08:00
parent cfa3f791f4
commit 4940db73fe
5 changed files with 290 additions and 88 deletions

View File

@@ -291,25 +291,90 @@ class TurnitinService
*
* 返回 viewer_url数小时有效
*
* @param array $viewer 可选 viewer 设置 e.g. ['viewer_default_permission_set' => 'INSTRUCTOR']
* TCA 要求 default_mode 为小写(如 match_overviewsave_changes 等 LTI 字段会导致 400。
* Crossref 通道常用 ADMINISTRATOR/USER非 INSTRUCTOR。可在 .env 配置:
* turnitin.viewer_permission_set=ADMINISTRATOR
*
* @param array $viewer 可选,覆盖默认 viewer 请求体字段
*/
public function getViewerUrl($submissionId, $viewer = [])
{
$body = array_merge([
'viewer_default_permission_set' => 'INSTRUCTOR',
'similarity' => [
'default_mode' => 'MATCH_OVERVIEW',
'view_settings' => ['save_changes' => true],
'modes' => ['match_overview' => true, 'all_sources' => true],
],
'locale' => 'en-US',
], $viewer);
$submissionId = trim((string) $submissionId);
if ($submissionId === '') {
throw new Exception('submissionId required for viewer-url');
}
return $this->request(
'POST',
'/submissions/' . urlencode($submissionId) . '/viewer-url',
$body
);
$path = '/submissions/' . rawurlencode($submissionId) . '/viewer-url';
$lastError = null;
foreach ($this->buildViewerUrlBodies($viewer) as $body) {
try {
return $this->request('POST', $path, $body);
} catch (Exception $e) {
$lastError = $e;
if (strpos($e->getMessage(), 'HTTP 400') === false) {
throw $e;
}
}
}
throw $lastError ?: new Exception('viewer-url failed');
}
/**
* 按优先级生成若干合法请求体(前者失败且为 400 时尝试后者)。
*
* @return array<int,array>
*/
private function buildViewerUrlBodies(array $viewerOverrides)
{
if (!empty($viewerOverrides)) {
return [$viewerOverrides];
}
$locale = trim((string) Env::get('turnitin.viewer_locale', 'en-US')) ?: 'en-US';
$configured = trim((string) Env::get('turnitin.viewer_permission_set', ''));
$permissionSets = $configured !== ''
? array_map('trim', explode(',', $configured))
: $this->defaultViewerPermissionSets();
$bodies = [];
foreach ($permissionSets as $perm) {
if ($perm === '') {
continue;
}
$bodies[] = [
'viewer_default_permission_set' => $perm,
'locale' => $locale,
'similarity' => [
'default_mode' => 'match_overview',
'modes' => [
'match_overview' => true,
'all_sources' => true,
],
],
];
// 最简请求体(部分 Crossref 租户只接受 permission + locale
$bodies[] = [
'viewer_default_permission_set' => $perm,
'locale' => $locale,
];
}
return $bodies;
}
/**
* Crossref Similarity Check 通常不用 INSTRUCTOR按常见可用角色排序尝试。
*
* @return array<int,string>
*/
private function defaultViewerPermissionSets()
{
if (stripos($this->baseUrl, 'crossref') !== false) {
return ['ADMINISTRATOR', 'USER', 'EDITOR', 'INSTRUCTOR'];
}
return ['INSTRUCTOR', 'ADMINISTRATOR', 'USER'];
}
/**