debug
This commit is contained in:
2
code/.gitignore
vendored
2
code/.gitignore
vendored
@@ -18,5 +18,7 @@ public/static/css/compiled/*
|
|||||||
public/static/js/compiled/*
|
public/static/js/compiled/*
|
||||||
public/static/favicon/generated/*
|
public/static/favicon/generated/*
|
||||||
/public/_seo_copy_release/*
|
/public/_seo_copy_release/*
|
||||||
|
/app/public/_admin_templates/video-metadata-missing-task-pool/*
|
||||||
|
/app/public/_admin_templates/video-metadata-missing-workbench/*
|
||||||
/data/seo_copy_published/*
|
/data/seo_copy_published/*
|
||||||
/storage/*
|
/storage/*
|
||||||
|
|||||||
@@ -1057,7 +1057,7 @@ class Site extends BaseController
|
|||||||
|
|
||||||
protected function domainExternalSeoSummaryRoot(): string
|
protected function domainExternalSeoSummaryRoot(): string
|
||||||
{
|
{
|
||||||
return $this->bootstrapCodeRoot() . '/public/_admin_templates/domain-seo-external/latest';
|
return $this->bootstrapCodeRoot() . '/storage/external-seo/latest';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function domainExternalSeoManualImportRoot(): string
|
protected function domainExternalSeoManualImportRoot(): string
|
||||||
@@ -1067,12 +1067,12 @@ class Site extends BaseController
|
|||||||
|
|
||||||
protected function domainExternalSeoSnapshotRunRoot(): string
|
protected function domainExternalSeoSnapshotRunRoot(): string
|
||||||
{
|
{
|
||||||
return $this->bootstrapCodeRoot() . '/public/_admin_templates/domain-seo-external/snapshot-runs';
|
return $this->bootstrapCodeRoot() . '/storage/external-seo/snapshot-runs';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function domainExternalSeoSnapshotValidateRunRoot(): string
|
protected function domainExternalSeoSnapshotValidateRunRoot(): string
|
||||||
{
|
{
|
||||||
return $this->bootstrapCodeRoot() . '/public/_admin_templates/domain-seo-external/snapshot-validate-runs';
|
return $this->bootstrapCodeRoot() . '/storage/external-seo/snapshot-validate-runs';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function domainExternalSeoStorageRoot(): string
|
protected function domainExternalSeoStorageRoot(): string
|
||||||
@@ -1122,6 +1122,18 @@ class Site extends BaseController
|
|||||||
return $strPath;
|
return $strPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function storageRelativePath(string $strPath): string
|
||||||
|
{
|
||||||
|
$strStorageRoot = rtrim($this->bootstrapCodeRoot() . '/storage/', '/');
|
||||||
|
$strPath = str_replace('\\', '/', $strPath);
|
||||||
|
$strStorageRoot = str_replace('\\', '/', $strStorageRoot);
|
||||||
|
if (str_starts_with($strPath, $strStorageRoot . '/')) {
|
||||||
|
return substr($strPath, strlen($strStorageRoot . '/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $strPath;
|
||||||
|
}
|
||||||
|
|
||||||
protected function bootstrapTemplateKey(?string $strTemplate): string
|
protected function bootstrapTemplateKey(?string $strTemplate): string
|
||||||
{
|
{
|
||||||
$strTemplate = strtolower(trim((string)$strTemplate));
|
$strTemplate = strtolower(trim((string)$strTemplate));
|
||||||
@@ -2180,8 +2192,8 @@ class Site extends BaseController
|
|||||||
$intLimit
|
$intLimit
|
||||||
);
|
);
|
||||||
$arrSummary = DomainExternalSeoSummaryHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
$arrSummary = DomainExternalSeoSummaryHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
||||||
$arrSummary['summary_json_path'] = $this->publicRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
$arrSummary['summary_json_path'] = $this->storageRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
||||||
$arrSummary['summary_html_path'] = $this->publicRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
$arrSummary['summary_html_path'] = $this->storageRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
||||||
|
|
||||||
return $this->success($arrSummary);
|
return $this->success($arrSummary);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
@@ -2215,8 +2227,8 @@ class Site extends BaseController
|
|||||||
$intLimit
|
$intLimit
|
||||||
);
|
);
|
||||||
$arrSummary = DomainExternalSeoTrendHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
$arrSummary = DomainExternalSeoTrendHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
||||||
$arrSummary['summary_json_path'] = $this->publicRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
$arrSummary['summary_json_path'] = $this->storageRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
||||||
$arrSummary['summary_html_path'] = $this->publicRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
$arrSummary['summary_html_path'] = $this->storageRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
||||||
|
|
||||||
return $this->success($arrSummary);
|
return $this->success($arrSummary);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
@@ -2334,8 +2346,8 @@ class Site extends BaseController
|
|||||||
'mapped_hosts_count' => (int)($arrResult['mapped_hosts_count'] ?? 0),
|
'mapped_hosts_count' => (int)($arrResult['mapped_hosts_count'] ?? 0),
|
||||||
'provider_summary' => $arrProviderSummary,
|
'provider_summary' => $arrProviderSummary,
|
||||||
'real_summary_status' => (string)($arrRealSummary['status'] ?? ''),
|
'real_summary_status' => (string)($arrRealSummary['status'] ?? ''),
|
||||||
'summary_json_path' => $this->publicRelativePath((string)($arrRealSummary['summary_json_path'] ?? '')),
|
'summary_json_path' => $this->storageRelativePath((string)($arrRealSummary['summary_json_path'] ?? '')),
|
||||||
'summary_html_path' => $this->publicRelativePath((string)($arrRealSummary['summary_html_path'] ?? '')),
|
'summary_html_path' => $this->storageRelativePath((string)($arrRealSummary['summary_html_path'] ?? '')),
|
||||||
]);
|
]);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '上传 Search Console property map 失败:' . $Throwable->getMessage());
|
return $this->error('9999', '上传 Search Console property map 失败:' . $Throwable->getMessage());
|
||||||
@@ -2348,8 +2360,8 @@ class Site extends BaseController
|
|||||||
$intDays = max(1, min(30, (int)$Request->get('days', 7)));
|
$intDays = max(1, min(30, (int)$Request->get('days', 7)));
|
||||||
$arrSummary = DomainExternalSeoSearchConsoleProviderPlanHelper::buildSummary($this->bootstrapCodeRoot(), $intDays);
|
$arrSummary = DomainExternalSeoSearchConsoleProviderPlanHelper::buildSummary($this->bootstrapCodeRoot(), $intDays);
|
||||||
$arrSummary = DomainExternalSeoSearchConsoleProviderPlanHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
$arrSummary = DomainExternalSeoSearchConsoleProviderPlanHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
||||||
$arrSummary['summary_json_path'] = $this->publicRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
$arrSummary['summary_json_path'] = $this->storageRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
||||||
$arrSummary['summary_html_path'] = $this->publicRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
$arrSummary['summary_html_path'] = $this->storageRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
||||||
return $this->success($arrSummary);
|
return $this->success($arrSummary);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '读取 Search Console provider 计划失败:' . $Throwable->getMessage());
|
return $this->error('9999', '读取 Search Console provider 计划失败:' . $Throwable->getMessage());
|
||||||
@@ -2362,8 +2374,8 @@ class Site extends BaseController
|
|||||||
$intDays = max(1, min(30, (int)$Request->get('days', 7)));
|
$intDays = max(1, min(30, (int)$Request->get('days', 7)));
|
||||||
$arrSummary = DomainExternalSeoSearchConsoleFetchHelper::buildSummary($this->bootstrapCodeRoot(), $intDays);
|
$arrSummary = DomainExternalSeoSearchConsoleFetchHelper::buildSummary($this->bootstrapCodeRoot(), $intDays);
|
||||||
$arrSummary = DomainExternalSeoSearchConsoleFetchHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
$arrSummary = DomainExternalSeoSearchConsoleFetchHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
||||||
$arrSummary['summary_json_path'] = $this->publicRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
$arrSummary['summary_json_path'] = $this->storageRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
||||||
$arrSummary['summary_html_path'] = $this->publicRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
$arrSummary['summary_html_path'] = $this->storageRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
||||||
return $this->success($arrSummary);
|
return $this->success($arrSummary);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '读取 Search Console fetch 摘要失败:' . $Throwable->getMessage());
|
return $this->error('9999', '读取 Search Console fetch 摘要失败:' . $Throwable->getMessage());
|
||||||
@@ -2375,8 +2387,8 @@ class Site extends BaseController
|
|||||||
try {
|
try {
|
||||||
$arrSummary = DomainExternalSeoBaiduProviderPlanHelper::buildSummary($this->bootstrapCodeRoot());
|
$arrSummary = DomainExternalSeoBaiduProviderPlanHelper::buildSummary($this->bootstrapCodeRoot());
|
||||||
$arrSummary = DomainExternalSeoBaiduProviderPlanHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
$arrSummary = DomainExternalSeoBaiduProviderPlanHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
||||||
$arrSummary['summary_json_path'] = $this->publicRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
$arrSummary['summary_json_path'] = $this->storageRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
||||||
$arrSummary['summary_html_path'] = $this->publicRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
$arrSummary['summary_html_path'] = $this->storageRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
||||||
return $this->success($arrSummary);
|
return $this->success($arrSummary);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '读取百度 provider 计划失败:' . $Throwable->getMessage());
|
return $this->error('9999', '读取百度 provider 计划失败:' . $Throwable->getMessage());
|
||||||
@@ -2389,8 +2401,8 @@ class Site extends BaseController
|
|||||||
$intLimit = max(1, min(200, (int)$Request->get('limit', 50)));
|
$intLimit = max(1, min(200, (int)$Request->get('limit', 50)));
|
||||||
$arrSummary = DomainExternalSeoBaiduPushSummaryHelper::buildSummary($this->bootstrapCodeRoot(), $intLimit);
|
$arrSummary = DomainExternalSeoBaiduPushSummaryHelper::buildSummary($this->bootstrapCodeRoot(), $intLimit);
|
||||||
$arrSummary = DomainExternalSeoBaiduPushSummaryHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
$arrSummary = DomainExternalSeoBaiduPushSummaryHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
||||||
$arrSummary['summary_json_path'] = $this->publicRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
$arrSummary['summary_json_path'] = $this->storageRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
||||||
$arrSummary['summary_html_path'] = $this->publicRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
$arrSummary['summary_html_path'] = $this->storageRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
||||||
return $this->success($arrSummary);
|
return $this->success($arrSummary);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '读取百度推送观察摘要失败:' . $Throwable->getMessage());
|
return $this->error('9999', '读取百度推送观察摘要失败:' . $Throwable->getMessage());
|
||||||
@@ -2439,8 +2451,8 @@ class Site extends BaseController
|
|||||||
$intLimit = max(1, min(300, (int)$Request->get('limit', 100)));
|
$intLimit = max(1, min(300, (int)$Request->get('limit', 100)));
|
||||||
$arrQueue = DomainExternalSeoBaiduPushAttentionQueueHelper::buildQueue($this->bootstrapCodeRoot(), $intLimit);
|
$arrQueue = DomainExternalSeoBaiduPushAttentionQueueHelper::buildQueue($this->bootstrapCodeRoot(), $intLimit);
|
||||||
$arrQueue = DomainExternalSeoBaiduPushAttentionQueueHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrQueue);
|
$arrQueue = DomainExternalSeoBaiduPushAttentionQueueHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrQueue);
|
||||||
$arrQueue['summary_json_path'] = $this->publicRelativePath((string)($arrQueue['summary_json_path'] ?? ''));
|
$arrQueue['summary_json_path'] = $this->storageRelativePath((string)($arrQueue['summary_json_path'] ?? ''));
|
||||||
$arrQueue['summary_html_path'] = $this->publicRelativePath((string)($arrQueue['summary_html_path'] ?? ''));
|
$arrQueue['summary_html_path'] = $this->storageRelativePath((string)($arrQueue['summary_html_path'] ?? ''));
|
||||||
return $this->success($arrQueue);
|
return $this->success($arrQueue);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '读取百度推送异常队列失败:' . $Throwable->getMessage());
|
return $this->error('9999', '读取百度推送异常队列失败:' . $Throwable->getMessage());
|
||||||
@@ -2453,8 +2465,8 @@ class Site extends BaseController
|
|||||||
$intLimit = max(1, min(100, (int)$Request->get('limit', 20)));
|
$intLimit = max(1, min(100, (int)$Request->get('limit', 20)));
|
||||||
$arrSummary = DomainExternalSeoBaiduPushTrendHelper::buildSummary($this->bootstrapCodeRoot(), $intLimit);
|
$arrSummary = DomainExternalSeoBaiduPushTrendHelper::buildSummary($this->bootstrapCodeRoot(), $intLimit);
|
||||||
$arrSummary = DomainExternalSeoBaiduPushTrendHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
$arrSummary = DomainExternalSeoBaiduPushTrendHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
||||||
$arrSummary['summary_json_path'] = $this->publicRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
$arrSummary['summary_json_path'] = $this->storageRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
||||||
$arrSummary['summary_html_path'] = $this->publicRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
$arrSummary['summary_html_path'] = $this->storageRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
||||||
return $this->success($arrSummary);
|
return $this->success($arrSummary);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '读取百度推送趋势摘要失败:' . $Throwable->getMessage());
|
return $this->error('9999', '读取百度推送趋势摘要失败:' . $Throwable->getMessage());
|
||||||
@@ -2467,8 +2479,8 @@ class Site extends BaseController
|
|||||||
$intLimit = max(1, min(100, (int)$Request->get('limit', 20)));
|
$intLimit = max(1, min(100, (int)$Request->get('limit', 20)));
|
||||||
$arrSummary = DomainExternalSeoBaiduFeedbackSummaryHelper::buildSummary($this->bootstrapCodeRoot(), $intLimit);
|
$arrSummary = DomainExternalSeoBaiduFeedbackSummaryHelper::buildSummary($this->bootstrapCodeRoot(), $intLimit);
|
||||||
$arrSummary = DomainExternalSeoBaiduFeedbackSummaryHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
$arrSummary = DomainExternalSeoBaiduFeedbackSummaryHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
||||||
$arrSummary['summary_json_path'] = $this->publicRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
$arrSummary['summary_json_path'] = $this->storageRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
||||||
$arrSummary['summary_html_path'] = $this->publicRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
$arrSummary['summary_html_path'] = $this->storageRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
||||||
return $this->success($arrSummary);
|
return $this->success($arrSummary);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '读取百度反馈摘要失败:' . $Throwable->getMessage());
|
return $this->error('9999', '读取百度反馈摘要失败:' . $Throwable->getMessage());
|
||||||
@@ -2481,8 +2493,8 @@ class Site extends BaseController
|
|||||||
$intLimit = max(1, min(100, (int)$Request->get('limit', 20)));
|
$intLimit = max(1, min(100, (int)$Request->get('limit', 20)));
|
||||||
$arrSummary = DomainExternalSeoSiteQueryProbeHelper::buildSummary($this->bootstrapCodeRoot(), $intLimit);
|
$arrSummary = DomainExternalSeoSiteQueryProbeHelper::buildSummary($this->bootstrapCodeRoot(), $intLimit);
|
||||||
$arrSummary = DomainExternalSeoSiteQueryProbeHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
$arrSummary = DomainExternalSeoSiteQueryProbeHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
||||||
$arrSummary['summary_json_path'] = $this->publicRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
$arrSummary['summary_json_path'] = $this->storageRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
||||||
$arrSummary['summary_html_path'] = $this->publicRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
$arrSummary['summary_html_path'] = $this->storageRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
||||||
return $this->success($arrSummary);
|
return $this->success($arrSummary);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '读取百度 site: 收录探测失败:' . $Throwable->getMessage());
|
return $this->error('9999', '读取百度 site: 收录探测失败:' . $Throwable->getMessage());
|
||||||
@@ -2509,8 +2521,8 @@ class Site extends BaseController
|
|||||||
$intLimit = max(1, min(300, (int)$Request->get('limit', 100)));
|
$intLimit = max(1, min(300, (int)$Request->get('limit', 100)));
|
||||||
$arrQueue = DomainExternalSeoAizhanKeywordAttentionQueueHelper::buildQueue($this->bootstrapCodeRoot(), $intLimit);
|
$arrQueue = DomainExternalSeoAizhanKeywordAttentionQueueHelper::buildQueue($this->bootstrapCodeRoot(), $intLimit);
|
||||||
$arrQueue = DomainExternalSeoAizhanKeywordAttentionQueueHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrQueue);
|
$arrQueue = DomainExternalSeoAizhanKeywordAttentionQueueHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrQueue);
|
||||||
$arrQueue['summary_json_path'] = $this->publicRelativePath((string)($arrQueue['summary_json_path'] ?? ''));
|
$arrQueue['summary_json_path'] = $this->storageRelativePath((string)($arrQueue['summary_json_path'] ?? ''));
|
||||||
$arrQueue['summary_html_path'] = $this->publicRelativePath((string)($arrQueue['summary_html_path'] ?? ''));
|
$arrQueue['summary_html_path'] = $this->storageRelativePath((string)($arrQueue['summary_html_path'] ?? ''));
|
||||||
return $this->success($arrQueue);
|
return $this->success($arrQueue);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '读取爱站关键词异常队列失败:' . $Throwable->getMessage());
|
return $this->error('9999', '读取爱站关键词异常队列失败:' . $Throwable->getMessage());
|
||||||
@@ -2523,8 +2535,8 @@ class Site extends BaseController
|
|||||||
$intLimit = max(1, min(100, (int)$Request->get('limit', 20)));
|
$intLimit = max(1, min(100, (int)$Request->get('limit', 20)));
|
||||||
$arrSummary = DomainExternalSeoAizhanKeywordTrendHelper::buildSummary($this->bootstrapCodeRoot(), $intLimit);
|
$arrSummary = DomainExternalSeoAizhanKeywordTrendHelper::buildSummary($this->bootstrapCodeRoot(), $intLimit);
|
||||||
$arrSummary = DomainExternalSeoAizhanKeywordTrendHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
$arrSummary = DomainExternalSeoAizhanKeywordTrendHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
||||||
$arrSummary['summary_json_path'] = $this->publicRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
$arrSummary['summary_json_path'] = $this->storageRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
||||||
$arrSummary['summary_html_path'] = $this->publicRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
$arrSummary['summary_html_path'] = $this->storageRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
||||||
return $this->success($arrSummary);
|
return $this->success($arrSummary);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '读取爱站关键词趋势摘要失败:' . $Throwable->getMessage());
|
return $this->error('9999', '读取爱站关键词趋势摘要失败:' . $Throwable->getMessage());
|
||||||
@@ -2568,40 +2580,40 @@ class Site extends BaseController
|
|||||||
$arrResult = DomainExternalSeoSnapshotHelper::ingestSnapshots((array)$arrSnapshots, $strSource);
|
$arrResult = DomainExternalSeoSnapshotHelper::ingestSnapshots((array)$arrSnapshots, $strSource);
|
||||||
$strRunRoot = DomainExternalSeoSnapshotRunHelper::createRunRoot($this->domainExternalSeoSnapshotRunRoot(), 'snapshot_push');
|
$strRunRoot = DomainExternalSeoSnapshotRunHelper::createRunRoot($this->domainExternalSeoSnapshotRunRoot(), 'snapshot_push');
|
||||||
$arrResult = DomainExternalSeoSnapshotRunHelper::writeRunArtifacts(
|
$arrResult = DomainExternalSeoSnapshotRunHelper::writeRunArtifacts(
|
||||||
$this->bootstrapCodeRoot() . '/public',
|
$this->bootstrapCodeRoot() . '/storage',
|
||||||
$strRunRoot,
|
$strRunRoot,
|
||||||
$arrResult,
|
$arrResult,
|
||||||
(array)$arrSnapshots
|
(array)$arrSnapshots
|
||||||
);
|
);
|
||||||
$arrResult['run_root'] = $this->publicRelativePath($strRunRoot);
|
$arrResult['run_root'] = $this->storageRelativePath($strRunRoot);
|
||||||
$arrResult['summary_json_path'] = $this->publicRelativePath((string)($arrResult['summary_json_path'] ?? ''));
|
$arrResult['summary_json_path'] = $this->storageRelativePath((string)($arrResult['summary_json_path'] ?? ''));
|
||||||
$arrResult['summary_html_path'] = $this->publicRelativePath((string)($arrResult['summary_html_path'] ?? ''));
|
$arrResult['summary_html_path'] = $this->storageRelativePath((string)($arrResult['summary_html_path'] ?? ''));
|
||||||
$arrResult['payload_json_path'] = $this->publicRelativePath((string)($arrResult['payload_json_path'] ?? ''));
|
$arrResult['payload_json_path'] = $this->storageRelativePath((string)($arrResult['payload_json_path'] ?? ''));
|
||||||
$arrOverview = DomainExternalSeoCnOverviewHelper::buildOverview(14, 10);
|
$arrOverview = DomainExternalSeoCnOverviewHelper::buildOverview(14, 10);
|
||||||
$arrOverview = DomainExternalSeoCnOverviewHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrOverview);
|
$arrOverview = DomainExternalSeoCnOverviewHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrOverview);
|
||||||
$arrOverview['summary_json_path'] = $this->publicRelativePath((string)($arrOverview['summary_json_path'] ?? ''));
|
$arrOverview['summary_json_path'] = $this->storageRelativePath((string)($arrOverview['summary_json_path'] ?? ''));
|
||||||
$arrOverview['summary_html_path'] = $this->publicRelativePath((string)($arrOverview['summary_html_path'] ?? ''));
|
$arrOverview['summary_html_path'] = $this->storageRelativePath((string)($arrOverview['summary_html_path'] ?? ''));
|
||||||
|
|
||||||
$arrSnapshotTrend = DomainExternalSeoSnapshotTrendHelper::buildSummary($this->domainExternalSeoSnapshotRunRoot(), 10);
|
$arrSnapshotTrend = DomainExternalSeoSnapshotTrendHelper::buildSummary($this->domainExternalSeoSnapshotRunRoot(), 10);
|
||||||
$arrSnapshotTrend = DomainExternalSeoSnapshotTrendHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSnapshotTrend);
|
$arrSnapshotTrend = DomainExternalSeoSnapshotTrendHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSnapshotTrend);
|
||||||
$arrSnapshotTrend['summary_json_path'] = $this->publicRelativePath((string)($arrSnapshotTrend['summary_json_path'] ?? ''));
|
$arrSnapshotTrend['summary_json_path'] = $this->storageRelativePath((string)($arrSnapshotTrend['summary_json_path'] ?? ''));
|
||||||
$arrSnapshotTrend['summary_html_path'] = $this->publicRelativePath((string)($arrSnapshotTrend['summary_html_path'] ?? ''));
|
$arrSnapshotTrend['summary_html_path'] = $this->storageRelativePath((string)($arrSnapshotTrend['summary_html_path'] ?? ''));
|
||||||
|
|
||||||
$arrResult['post_ingest_overview'] = $arrOverview;
|
$arrResult['post_ingest_overview'] = $arrOverview;
|
||||||
$arrResult['post_ingest_snapshot_trend'] = $arrSnapshotTrend;
|
$arrResult['post_ingest_snapshot_trend'] = $arrSnapshotTrend;
|
||||||
$arrResult = DomainExternalSeoSnapshotRunHelper::writeRunArtifacts(
|
$arrResult = DomainExternalSeoSnapshotRunHelper::writeRunArtifacts(
|
||||||
$this->bootstrapCodeRoot() . '/public',
|
$this->bootstrapCodeRoot() . '/storage',
|
||||||
$strRunRoot,
|
$strRunRoot,
|
||||||
$arrResult,
|
$arrResult,
|
||||||
(array)$arrSnapshots
|
(array)$arrSnapshots
|
||||||
);
|
);
|
||||||
$arrResult['summary_json_path'] = $this->publicRelativePath((string)($arrResult['summary_json_path'] ?? ''));
|
$arrResult['summary_json_path'] = $this->storageRelativePath((string)($arrResult['summary_json_path'] ?? ''));
|
||||||
$arrResult['summary_html_path'] = $this->publicRelativePath((string)($arrResult['summary_html_path'] ?? ''));
|
$arrResult['summary_html_path'] = $this->storageRelativePath((string)($arrResult['summary_html_path'] ?? ''));
|
||||||
$arrResult['payload_json_path'] = $this->publicRelativePath((string)($arrResult['payload_json_path'] ?? ''));
|
$arrResult['payload_json_path'] = $this->storageRelativePath((string)($arrResult['payload_json_path'] ?? ''));
|
||||||
$arrSnapshotTrend = DomainExternalSeoSnapshotTrendHelper::buildSummary($this->domainExternalSeoSnapshotRunRoot(), 10);
|
$arrSnapshotTrend = DomainExternalSeoSnapshotTrendHelper::buildSummary($this->domainExternalSeoSnapshotRunRoot(), 10);
|
||||||
$arrSnapshotTrend = DomainExternalSeoSnapshotTrendHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSnapshotTrend);
|
$arrSnapshotTrend = DomainExternalSeoSnapshotTrendHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSnapshotTrend);
|
||||||
$arrSnapshotTrend['summary_json_path'] = $this->publicRelativePath((string)($arrSnapshotTrend['summary_json_path'] ?? ''));
|
$arrSnapshotTrend['summary_json_path'] = $this->storageRelativePath((string)($arrSnapshotTrend['summary_json_path'] ?? ''));
|
||||||
$arrSnapshotTrend['summary_html_path'] = $this->publicRelativePath((string)($arrSnapshotTrend['summary_html_path'] ?? ''));
|
$arrSnapshotTrend['summary_html_path'] = $this->storageRelativePath((string)($arrSnapshotTrend['summary_html_path'] ?? ''));
|
||||||
$arrResult['post_ingest_snapshot_trend'] = $arrSnapshotTrend;
|
$arrResult['post_ingest_snapshot_trend'] = $arrSnapshotTrend;
|
||||||
return $this->success($arrResult);
|
return $this->success($arrResult);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
@@ -2651,15 +2663,15 @@ class Site extends BaseController
|
|||||||
$arrResult = DomainExternalSeoSnapshotSchemaHelper::validateSnapshots((array)$arrSnapshots);
|
$arrResult = DomainExternalSeoSnapshotSchemaHelper::validateSnapshots((array)$arrSnapshots);
|
||||||
$strRunRoot = DomainExternalSeoSnapshotValidateRunHelper::createRunRoot($this->domainExternalSeoSnapshotValidateRunRoot(), 'snapshot_validate');
|
$strRunRoot = DomainExternalSeoSnapshotValidateRunHelper::createRunRoot($this->domainExternalSeoSnapshotValidateRunRoot(), 'snapshot_validate');
|
||||||
$arrResult = DomainExternalSeoSnapshotValidateRunHelper::writeRunArtifacts(
|
$arrResult = DomainExternalSeoSnapshotValidateRunHelper::writeRunArtifacts(
|
||||||
$this->bootstrapCodeRoot() . '/public',
|
$this->bootstrapCodeRoot() . '/storage',
|
||||||
$strRunRoot,
|
$strRunRoot,
|
||||||
$arrResult,
|
$arrResult,
|
||||||
(array)$arrSnapshots
|
(array)$arrSnapshots
|
||||||
);
|
);
|
||||||
$arrResult['run_root'] = $this->publicRelativePath($strRunRoot);
|
$arrResult['run_root'] = $this->storageRelativePath($strRunRoot);
|
||||||
$arrResult['summary_json_path'] = $this->publicRelativePath((string)($arrResult['summary_json_path'] ?? ''));
|
$arrResult['summary_json_path'] = $this->storageRelativePath((string)($arrResult['summary_json_path'] ?? ''));
|
||||||
$arrResult['summary_html_path'] = $this->publicRelativePath((string)($arrResult['summary_html_path'] ?? ''));
|
$arrResult['summary_html_path'] = $this->storageRelativePath((string)($arrResult['summary_html_path'] ?? ''));
|
||||||
$arrResult['payload_json_path'] = $this->publicRelativePath((string)($arrResult['payload_json_path'] ?? ''));
|
$arrResult['payload_json_path'] = $this->storageRelativePath((string)($arrResult['payload_json_path'] ?? ''));
|
||||||
|
|
||||||
return $this->success($arrResult);
|
return $this->success($arrResult);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
@@ -2944,8 +2956,8 @@ class Site extends BaseController
|
|||||||
$intDays = max(1, min(30, (int)$Request->get('days', 7)));
|
$intDays = max(1, min(30, (int)$Request->get('days', 7)));
|
||||||
$arrSummary = DomainExternalSeoRealSummaryHelper::buildSummary($this->bootstrapCodeRoot(), $intDays);
|
$arrSummary = DomainExternalSeoRealSummaryHelper::buildSummary($this->bootstrapCodeRoot(), $intDays);
|
||||||
$arrSummary = DomainExternalSeoRealSummaryHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
$arrSummary = DomainExternalSeoRealSummaryHelper::writeArtifacts($this->domainExternalSeoSummaryRoot(), $arrSummary);
|
||||||
$arrSummary['summary_json_path'] = $this->publicRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
$arrSummary['summary_json_path'] = $this->storageRelativePath((string)($arrSummary['summary_json_path'] ?? ''));
|
||||||
$arrSummary['summary_html_path'] = $this->publicRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
$arrSummary['summary_html_path'] = $this->storageRelativePath((string)($arrSummary['summary_html_path'] ?? ''));
|
||||||
return $this->success($arrSummary);
|
return $this->success($arrSummary);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '读取真实站外 summary 骨架失败:' . $Throwable->getMessage());
|
return $this->error('9999', '读取真实站外 summary 骨架失败:' . $Throwable->getMessage());
|
||||||
@@ -3021,8 +3033,8 @@ class Site extends BaseController
|
|||||||
'real_metrics_available' => !empty($arrRealSummary['real_metrics_available']),
|
'real_metrics_available' => !empty($arrRealSummary['real_metrics_available']),
|
||||||
'real_summary_provider' => (string)($arrRealSummary['provider_key'] ?? ''),
|
'real_summary_provider' => (string)($arrRealSummary['provider_key'] ?? ''),
|
||||||
'metrics' => (array)($arrRealSummary['metrics'] ?? []),
|
'metrics' => (array)($arrRealSummary['metrics'] ?? []),
|
||||||
'summary_json_path' => $this->publicRelativePath((string)($arrRealSummary['summary_json_path'] ?? '')),
|
'summary_json_path' => $this->storageRelativePath((string)($arrRealSummary['summary_json_path'] ?? '')),
|
||||||
'summary_html_path' => $this->publicRelativePath((string)($arrRealSummary['summary_html_path'] ?? '')),
|
'summary_html_path' => $this->storageRelativePath((string)($arrRealSummary['summary_html_path'] ?? '')),
|
||||||
]);
|
]);
|
||||||
} catch (\Throwable $Throwable) {
|
} catch (\Throwable $Throwable) {
|
||||||
return $this->error('9999', '导入站外手工报表失败:' . $Throwable->getMessage());
|
return $this->error('9999', '导入站外手工报表失败:' . $Throwable->getMessage());
|
||||||
|
|||||||
@@ -35,17 +35,17 @@ class SeoCollector extends BaseController
|
|||||||
|
|
||||||
protected function summaryRoot(): string
|
protected function summaryRoot(): string
|
||||||
{
|
{
|
||||||
return $this->publicRoot() . '/_admin_templates/domain-seo-external/latest';
|
return $this->storageRoot() . '/external-seo/latest';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function snapshotRunRoot(): string
|
protected function snapshotRunRoot(): string
|
||||||
{
|
{
|
||||||
return $this->publicRoot() . '/_admin_templates/domain-seo-external/snapshot-runs';
|
return $this->storageRoot() . '/external-seo/snapshot-runs';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function snapshotValidateRunRoot(): string
|
protected function snapshotValidateRunRoot(): string
|
||||||
{
|
{
|
||||||
return $this->publicRoot() . '/_admin_templates/domain-seo-external/snapshot-validate-runs';
|
return $this->storageRoot() . '/external-seo/snapshot-validate-runs';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function spiderCrawlLatestRoot(): string
|
protected function spiderCrawlLatestRoot(): string
|
||||||
@@ -138,15 +138,15 @@ class SeoCollector extends BaseController
|
|||||||
$result = DomainExternalSeoSnapshotSchemaHelper::validateSnapshots((array)$snapshots);
|
$result = DomainExternalSeoSnapshotSchemaHelper::validateSnapshots((array)$snapshots);
|
||||||
$runRoot = DomainExternalSeoSnapshotValidateRunHelper::createRunRoot($this->snapshotValidateRunRoot(), 'snapshot_validate');
|
$runRoot = DomainExternalSeoSnapshotValidateRunHelper::createRunRoot($this->snapshotValidateRunRoot(), 'snapshot_validate');
|
||||||
$result = DomainExternalSeoSnapshotValidateRunHelper::writeRunArtifacts(
|
$result = DomainExternalSeoSnapshotValidateRunHelper::writeRunArtifacts(
|
||||||
$this->publicRoot(),
|
$this->storageRoot(),
|
||||||
$runRoot,
|
$runRoot,
|
||||||
$result,
|
$result,
|
||||||
(array)$snapshots
|
(array)$snapshots
|
||||||
);
|
);
|
||||||
$result['run_root'] = $this->publicRelativePath($runRoot);
|
$result['run_root'] = $this->storageRelativePath($runRoot);
|
||||||
$result['summary_json_path'] = $this->publicRelativePath((string)($result['summary_json_path'] ?? ''));
|
$result['summary_json_path'] = $this->storageRelativePath((string)($result['summary_json_path'] ?? ''));
|
||||||
$result['summary_html_path'] = $this->publicRelativePath((string)($result['summary_html_path'] ?? ''));
|
$result['summary_html_path'] = $this->storageRelativePath((string)($result['summary_html_path'] ?? ''));
|
||||||
$result['payload_json_path'] = $this->publicRelativePath((string)($result['payload_json_path'] ?? ''));
|
$result['payload_json_path'] = $this->storageRelativePath((string)($result['payload_json_path'] ?? ''));
|
||||||
|
|
||||||
return $this->success($result);
|
return $this->success($result);
|
||||||
} catch (\Throwable $throwable) {
|
} catch (\Throwable $throwable) {
|
||||||
@@ -166,37 +166,37 @@ class SeoCollector extends BaseController
|
|||||||
$result = DomainExternalSeoSnapshotHelper::ingestSnapshots((array)$snapshots, $source);
|
$result = DomainExternalSeoSnapshotHelper::ingestSnapshots((array)$snapshots, $source);
|
||||||
$runRoot = DomainExternalSeoSnapshotRunHelper::createRunRoot($this->snapshotRunRoot(), 'snapshot_push');
|
$runRoot = DomainExternalSeoSnapshotRunHelper::createRunRoot($this->snapshotRunRoot(), 'snapshot_push');
|
||||||
$result = DomainExternalSeoSnapshotRunHelper::writeRunArtifacts(
|
$result = DomainExternalSeoSnapshotRunHelper::writeRunArtifacts(
|
||||||
$this->publicRoot(),
|
$this->storageRoot(),
|
||||||
$runRoot,
|
$runRoot,
|
||||||
$result,
|
$result,
|
||||||
(array)$snapshots
|
(array)$snapshots
|
||||||
);
|
);
|
||||||
$result['run_root'] = $this->publicRelativePath($runRoot);
|
$result['run_root'] = $this->storageRelativePath($runRoot);
|
||||||
$result['summary_json_path'] = $this->publicRelativePath((string)($result['summary_json_path'] ?? ''));
|
$result['summary_json_path'] = $this->storageRelativePath((string)($result['summary_json_path'] ?? ''));
|
||||||
$result['summary_html_path'] = $this->publicRelativePath((string)($result['summary_html_path'] ?? ''));
|
$result['summary_html_path'] = $this->storageRelativePath((string)($result['summary_html_path'] ?? ''));
|
||||||
$result['payload_json_path'] = $this->publicRelativePath((string)($result['payload_json_path'] ?? ''));
|
$result['payload_json_path'] = $this->storageRelativePath((string)($result['payload_json_path'] ?? ''));
|
||||||
|
|
||||||
$overview = DomainExternalSeoCnOverviewHelper::buildOverview(14, 10);
|
$overview = DomainExternalSeoCnOverviewHelper::buildOverview(14, 10);
|
||||||
$overview = DomainExternalSeoCnOverviewHelper::writeArtifacts($this->summaryRoot(), $overview);
|
$overview = DomainExternalSeoCnOverviewHelper::writeArtifacts($this->summaryRoot(), $overview);
|
||||||
$overview['summary_json_path'] = $this->publicRelativePath((string)($overview['summary_json_path'] ?? ''));
|
$overview['summary_json_path'] = $this->storageRelativePath((string)($overview['summary_json_path'] ?? ''));
|
||||||
$overview['summary_html_path'] = $this->publicRelativePath((string)($overview['summary_html_path'] ?? ''));
|
$overview['summary_html_path'] = $this->storageRelativePath((string)($overview['summary_html_path'] ?? ''));
|
||||||
|
|
||||||
$snapshotTrend = DomainExternalSeoSnapshotTrendHelper::buildSummary($this->snapshotRunRoot(), 10);
|
$snapshotTrend = DomainExternalSeoSnapshotTrendHelper::buildSummary($this->snapshotRunRoot(), 10);
|
||||||
$snapshotTrend = DomainExternalSeoSnapshotTrendHelper::writeArtifacts($this->summaryRoot(), $snapshotTrend);
|
$snapshotTrend = DomainExternalSeoSnapshotTrendHelper::writeArtifacts($this->summaryRoot(), $snapshotTrend);
|
||||||
$snapshotTrend['summary_json_path'] = $this->publicRelativePath((string)($snapshotTrend['summary_json_path'] ?? ''));
|
$snapshotTrend['summary_json_path'] = $this->storageRelativePath((string)($snapshotTrend['summary_json_path'] ?? ''));
|
||||||
$snapshotTrend['summary_html_path'] = $this->publicRelativePath((string)($snapshotTrend['summary_html_path'] ?? ''));
|
$snapshotTrend['summary_html_path'] = $this->storageRelativePath((string)($snapshotTrend['summary_html_path'] ?? ''));
|
||||||
|
|
||||||
$result['post_ingest_overview'] = $overview;
|
$result['post_ingest_overview'] = $overview;
|
||||||
$result['post_ingest_snapshot_trend'] = $snapshotTrend;
|
$result['post_ingest_snapshot_trend'] = $snapshotTrend;
|
||||||
$result = DomainExternalSeoSnapshotRunHelper::writeRunArtifacts(
|
$result = DomainExternalSeoSnapshotRunHelper::writeRunArtifacts(
|
||||||
$this->publicRoot(),
|
$this->storageRoot(),
|
||||||
$runRoot,
|
$runRoot,
|
||||||
$result,
|
$result,
|
||||||
(array)$snapshots
|
(array)$snapshots
|
||||||
);
|
);
|
||||||
$result['summary_json_path'] = $this->publicRelativePath((string)($result['summary_json_path'] ?? ''));
|
$result['summary_json_path'] = $this->storageRelativePath((string)($result['summary_json_path'] ?? ''));
|
||||||
$result['summary_html_path'] = $this->publicRelativePath((string)($result['summary_html_path'] ?? ''));
|
$result['summary_html_path'] = $this->storageRelativePath((string)($result['summary_html_path'] ?? ''));
|
||||||
$result['payload_json_path'] = $this->publicRelativePath((string)($result['payload_json_path'] ?? ''));
|
$result['payload_json_path'] = $this->storageRelativePath((string)($result['payload_json_path'] ?? ''));
|
||||||
|
|
||||||
return $this->success($result);
|
return $this->success($result);
|
||||||
} catch (\Throwable $throwable) {
|
} catch (\Throwable $throwable) {
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ namespace app\common\helper;
|
|||||||
|
|
||||||
class DomainExternalSeoSnapshotRunIndexHelper
|
class DomainExternalSeoSnapshotRunIndexHelper
|
||||||
{
|
{
|
||||||
protected static function publicRelativePath(string $strPath): string
|
protected static function storageRelativePath(string $strPath): string
|
||||||
{
|
{
|
||||||
$strPublicRoot = str_replace('\\', '/', rtrim(dirname(__DIR__, 3) . '/public', '/'));
|
$strStorageRoot = str_replace('\\', '/', rtrim(dirname(__DIR__, 3) . '/storage', '/'));
|
||||||
$strPath = str_replace('\\', '/', $strPath);
|
$strPath = str_replace('\\', '/', $strPath);
|
||||||
if (str_starts_with($strPath, $strPublicRoot . '/')) {
|
if (str_starts_with($strPath, $strStorageRoot . '/')) {
|
||||||
return substr($strPath, strlen($strPublicRoot . '/'));
|
return substr($strPath, strlen($strStorageRoot . '/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $strPath;
|
return $strPath;
|
||||||
@@ -60,7 +60,7 @@ class DomainExternalSeoSnapshotRunIndexHelper
|
|||||||
|
|
||||||
$arrItems[] = [
|
$arrItems[] = [
|
||||||
'run_id' => basename($strRunRoot),
|
'run_id' => basename($strRunRoot),
|
||||||
'run_root_public' => self::publicRelativePath($strRunRoot),
|
'run_root_public' => self::storageRelativePath($strRunRoot),
|
||||||
'source' => (string)($arrSummary['source'] ?? ''),
|
'source' => (string)($arrSummary['source'] ?? ''),
|
||||||
'received_count' => $intReceivedCount,
|
'received_count' => $intReceivedCount,
|
||||||
'inserted_count' => (int)($arrSummary['inserted_count'] ?? 0),
|
'inserted_count' => (int)($arrSummary['inserted_count'] ?? 0),
|
||||||
@@ -82,9 +82,9 @@ class DomainExternalSeoSnapshotRunIndexHelper
|
|||||||
'post_ingest_snapshot_trend' => (array)($arrSummary['post_ingest_snapshot_trend'] ?? []),
|
'post_ingest_snapshot_trend' => (array)($arrSummary['post_ingest_snapshot_trend'] ?? []),
|
||||||
'post_ingest_health_label' => (string)(($arrSummary['post_ingest_overview']['health_label'] ?? '')),
|
'post_ingest_health_label' => (string)(($arrSummary['post_ingest_overview']['health_label'] ?? '')),
|
||||||
'post_ingest_trend_label' => (string)(($arrSummary['post_ingest_snapshot_trend']['success_trend']['label'] ?? '')),
|
'post_ingest_trend_label' => (string)(($arrSummary['post_ingest_snapshot_trend']['success_trend']['label'] ?? '')),
|
||||||
'summary_json_path' => self::publicRelativePath($strSummaryPath),
|
'summary_json_path' => self::storageRelativePath($strSummaryPath),
|
||||||
'summary_html_path' => self::publicRelativePath($strRunRoot . '/snapshot-ingest.summary.html'),
|
'summary_html_path' => self::storageRelativePath($strRunRoot . '/snapshot-ingest.summary.html'),
|
||||||
'payload_json_path' => self::publicRelativePath($strRunRoot . '/snapshots.payload.json'),
|
'payload_json_path' => self::storageRelativePath($strRunRoot . '/snapshots.payload.json'),
|
||||||
'updated_at' => date(DATE_ATOM, (int)(filemtime($strSummaryPath) ?: time())),
|
'updated_at' => date(DATE_ATOM, (int)(filemtime($strSummaryPath) ?: time())),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ namespace app\common\helper;
|
|||||||
|
|
||||||
class DomainExternalSeoSnapshotValidateRunIndexHelper
|
class DomainExternalSeoSnapshotValidateRunIndexHelper
|
||||||
{
|
{
|
||||||
protected static function publicRelativePath(string $strPath): string
|
protected static function storageRelativePath(string $strPath): string
|
||||||
{
|
{
|
||||||
$strPublicRoot = str_replace('\\', '/', rtrim(dirname(__DIR__, 3) . '/public', '/'));
|
$strStorageRoot = str_replace('\\', '/', rtrim(dirname(__DIR__, 3) . '/storage', '/'));
|
||||||
$strPath = str_replace('\\', '/', $strPath);
|
$strPath = str_replace('\\', '/', $strPath);
|
||||||
if (str_starts_with($strPath, $strPublicRoot . '/')) {
|
if (str_starts_with($strPath, $strStorageRoot . '/')) {
|
||||||
return substr($strPath, strlen($strPublicRoot . '/'));
|
return substr($strPath, strlen($strStorageRoot . '/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $strPath;
|
return $strPath;
|
||||||
@@ -50,7 +50,7 @@ class DomainExternalSeoSnapshotValidateRunIndexHelper
|
|||||||
|
|
||||||
$arrItems[] = [
|
$arrItems[] = [
|
||||||
'run_id' => basename($strRunRoot),
|
'run_id' => basename($strRunRoot),
|
||||||
'run_root_public' => self::publicRelativePath($strRunRoot),
|
'run_root_public' => self::storageRelativePath($strRunRoot),
|
||||||
'received_count' => $intReceivedCount,
|
'received_count' => $intReceivedCount,
|
||||||
'valid_count' => (int)($arrSummary['valid_count'] ?? 0),
|
'valid_count' => (int)($arrSummary['valid_count'] ?? 0),
|
||||||
'error_count' => $intErrorCount,
|
'error_count' => $intErrorCount,
|
||||||
@@ -63,9 +63,9 @@ class DomainExternalSeoSnapshotValidateRunIndexHelper
|
|||||||
'warnings' => (array)($arrSummary['warnings'] ?? []),
|
'warnings' => (array)($arrSummary['warnings'] ?? []),
|
||||||
'error_buckets' => (array)($arrSummary['error_buckets'] ?? []),
|
'error_buckets' => (array)($arrSummary['error_buckets'] ?? []),
|
||||||
'warning_buckets' => (array)($arrSummary['warning_buckets'] ?? []),
|
'warning_buckets' => (array)($arrSummary['warning_buckets'] ?? []),
|
||||||
'summary_json_path' => self::publicRelativePath($strSummaryPath),
|
'summary_json_path' => self::storageRelativePath($strSummaryPath),
|
||||||
'summary_html_path' => self::publicRelativePath($strRunRoot . '/snapshot-validate.summary.html'),
|
'summary_html_path' => self::storageRelativePath($strRunRoot . '/snapshot-validate.summary.html'),
|
||||||
'payload_json_path' => self::publicRelativePath($strRunRoot . '/snapshots.payload.json'),
|
'payload_json_path' => self::storageRelativePath($strRunRoot . '/snapshots.payload.json'),
|
||||||
'updated_at' => date(DATE_ATOM, (int)(filemtime($strSummaryPath) ?: time())),
|
'updated_at' => date(DATE_ATOM, (int)(filemtime($strSummaryPath) ?: time())),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1710,7 +1710,13 @@ class SiteStyle
|
|||||||
{
|
{
|
||||||
if (!$domainRow) return null;
|
if (!$domainRow) return null;
|
||||||
$raw = is_array($domainRow) ? ($domainRow['t_cfg'] ?? null) : ($domainRow->t_cfg ?? null);
|
$raw = is_array($domainRow) ? ($domainRow['t_cfg'] ?? null) : ($domainRow->t_cfg ?? null);
|
||||||
return $raw ? json_decode($raw, true) : null;
|
if (is_array($raw)) {
|
||||||
|
return $raw;
|
||||||
|
}
|
||||||
|
if (!is_string($raw) || trim($raw) === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return json_decode($raw, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function writeDbConfig($domainRow, array $cfg): void
|
private static function writeDbConfig($domainRow, array $cfg): void
|
||||||
|
|||||||
210
code/scripts/old_tmp_domain_daily_probe.php
Normal file
210
code/scripts/old_tmp_domain_daily_probe.php
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
use app\common\helper\DomainImportProbeRunHelper;
|
||||||
|
use app\model\DomainModel;
|
||||||
|
use think\App;
|
||||||
|
use think\facade\Db;
|
||||||
|
|
||||||
|
function printUsage(): void
|
||||||
|
{
|
||||||
|
echo "Usage:\n";
|
||||||
|
echo " php scripts/old_tmp_domain_daily_probe.php [--templates=1001,1002,1003,1004,1005] [--run-root=/abs/path] [--format=json|text]\n\n";
|
||||||
|
echo "Example:\n";
|
||||||
|
echo " php scripts/old_tmp_domain_daily_probe.php --format=text\n";
|
||||||
|
echo " php scripts/old_tmp_domain_daily_probe.php --templates=1002,1003 --format=json\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureAppInitialized(): void
|
||||||
|
{
|
||||||
|
static $initialized = false;
|
||||||
|
if ($initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(new App())->initialize();
|
||||||
|
$initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeTemplateIds(string $raw): array
|
||||||
|
{
|
||||||
|
$items = array_filter(array_map('trim', explode(',', $raw)), static fn(string $v): bool => $v !== '');
|
||||||
|
$ids = [];
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$ids[] = (int)$item;
|
||||||
|
}
|
||||||
|
$ids = array_values(array_unique(array_filter($ids, static fn(int $v): bool => $v > 0)));
|
||||||
|
sort($ids);
|
||||||
|
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadHosts(array $templateIds): array
|
||||||
|
{
|
||||||
|
ensureAppInitialized();
|
||||||
|
|
||||||
|
$rows = Db::name('domain')
|
||||||
|
->whereIn('t_id', $templateIds)
|
||||||
|
->field(['d_domain', 't_id'])
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
$hosts = [];
|
||||||
|
$templateBuckets = [];
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
if (!is_array($row)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$host = DomainModel::normalizeHost((string)($row['d_domain'] ?? ''));
|
||||||
|
$templateId = (int)($row['t_id'] ?? 0);
|
||||||
|
if ($host === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$hosts[] = $host;
|
||||||
|
if (!isset($templateBuckets[$templateId])) {
|
||||||
|
$templateBuckets[$templateId] = [];
|
||||||
|
}
|
||||||
|
$templateBuckets[$templateId][] = $host;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hosts = array_values(array_unique($hosts));
|
||||||
|
sort($hosts);
|
||||||
|
ksort($templateBuckets);
|
||||||
|
foreach ($templateBuckets as &$bucket) {
|
||||||
|
$bucket = array_values(array_unique($bucket));
|
||||||
|
sort($bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'hosts' => $hosts,
|
||||||
|
'template_buckets' => $templateBuckets,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderText(array $summary): string
|
||||||
|
{
|
||||||
|
$lines = [
|
||||||
|
'status: ' . (string)($summary['status'] ?? ''),
|
||||||
|
'processed_count: ' . (int)($summary['processed_count'] ?? 0),
|
||||||
|
'passed_count: ' . (int)($summary['passed_count'] ?? 0),
|
||||||
|
'failed_count: ' . (int)($summary['failed_count'] ?? 0),
|
||||||
|
'run_root: ' . (string)($summary['run_root'] ?? ''),
|
||||||
|
'summary_json_path: ' . (string)($summary['summary_json_path'] ?? ''),
|
||||||
|
'summary_html_path: ' . (string)($summary['summary_html_path'] ?? ''),
|
||||||
|
'template_ids: ' . implode(',', (array)($summary['meta']['template_ids'] ?? [])),
|
||||||
|
'hosts_count: ' . count((array)($summary['meta']['hosts'] ?? [])),
|
||||||
|
'failed_hosts:',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ((array)($summary['items'] ?? []) as $item) {
|
||||||
|
if (!empty($item['all_passed'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$lines[] = '- '
|
||||||
|
. (string)($item['host'] ?? '')
|
||||||
|
. ' | status=' . (string)($item['status'] ?? '')
|
||||||
|
. ' | failed_stage=' . (string)($item['failed_stage'] ?? '')
|
||||||
|
. ' | message=' . (string)($item['message'] ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(PHP_EOL, $lines) . PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
$args = $argv;
|
||||||
|
array_shift($args);
|
||||||
|
|
||||||
|
$templateIds = [1001, 1002, 1003, 1004, 1005];
|
||||||
|
$runRoot = dirname(__DIR__) . '/storage/domain-import-runs';
|
||||||
|
$format = 'json';
|
||||||
|
|
||||||
|
foreach ($args as $arg) {
|
||||||
|
if (str_starts_with($arg, '--templates=')) {
|
||||||
|
$parsed = normalizeTemplateIds(substr($arg, strlen('--templates=')));
|
||||||
|
if (!empty($parsed)) {
|
||||||
|
$templateIds = $parsed;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (str_starts_with($arg, '--run-root=')) {
|
||||||
|
$runRoot = rtrim(trim(substr($arg, strlen('--run-root='))), '/');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (str_starts_with($arg, '--format=')) {
|
||||||
|
$format = strtolower(trim(substr($arg, strlen('--format='))));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (in_array($arg, ['-h', '--help'], true)) {
|
||||||
|
printUsage();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_array($format, ['json', 'text'], true)) {
|
||||||
|
fwrite(STDERR, "Invalid format: {$format}\n");
|
||||||
|
printUsage();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$loaded = loadHosts($templateIds);
|
||||||
|
$hosts = (array)($loaded['hosts'] ?? []);
|
||||||
|
$templateBuckets = (array)($loaded['template_buckets'] ?? []);
|
||||||
|
|
||||||
|
if (empty($hosts)) {
|
||||||
|
$empty = [
|
||||||
|
'status' => 'empty',
|
||||||
|
'processed_count' => 0,
|
||||||
|
'passed_count' => 0,
|
||||||
|
'failed_count' => 0,
|
||||||
|
'items' => [],
|
||||||
|
'meta' => [
|
||||||
|
'template_ids' => $templateIds,
|
||||||
|
'hosts' => [],
|
||||||
|
'template_buckets' => $templateBuckets,
|
||||||
|
],
|
||||||
|
'generated_at' => date(DATE_ATOM),
|
||||||
|
];
|
||||||
|
echo $format === 'text'
|
||||||
|
? renderText($empty)
|
||||||
|
: json_encode($empty, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$probeRunRoot = DomainImportProbeRunHelper::createRunRoot($runRoot, 'old_tmp_daily_probe');
|
||||||
|
$summary = DomainImportProbeRunHelper::run($hosts, $probeRunRoot, [
|
||||||
|
'template_ids' => $templateIds,
|
||||||
|
'template_buckets' => $templateBuckets,
|
||||||
|
'hosts' => $hosts,
|
||||||
|
'scope' => 'old_tmp_daily_probe',
|
||||||
|
]);
|
||||||
|
$summary['run_root'] = $probeRunRoot;
|
||||||
|
|
||||||
|
echo $format === 'text'
|
||||||
|
? renderText($summary)
|
||||||
|
: json_encode($summary, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
|
||||||
|
} catch (Throwable $throwable) {
|
||||||
|
$error = [
|
||||||
|
'status' => 'script_failed',
|
||||||
|
'error_class' => get_class($throwable),
|
||||||
|
'message' => $throwable->getMessage(),
|
||||||
|
'file' => $throwable->getFile(),
|
||||||
|
'line' => $throwable->getLine(),
|
||||||
|
'trace' => $throwable->getTraceAsString(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($format === 'text') {
|
||||||
|
echo 'status: script_failed' . PHP_EOL;
|
||||||
|
echo 'error_class: ' . $error['error_class'] . PHP_EOL;
|
||||||
|
echo 'message: ' . $error['message'] . PHP_EOL;
|
||||||
|
echo 'file: ' . $error['file'] . PHP_EOL;
|
||||||
|
echo 'line: ' . $error['line'] . PHP_EOL;
|
||||||
|
echo 'trace:' . PHP_EOL . $error['trace'] . PHP_EOL;
|
||||||
|
} else {
|
||||||
|
echo json_encode($error, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
152
docs/2026-04-19-domain-seo-external-storage收口说明.md
Normal file
152
docs/2026-04-19-domain-seo-external-storage收口说明.md
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
# 2026-04-19 domain-seo-external storage 收口说明
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
`domain-seo-external` 这套后台摘要原先把最新运行产物持续写到:
|
||||||
|
|
||||||
|
- `code/public/_admin_templates/domain-seo-external/latest`
|
||||||
|
- `code/public/_admin_templates/domain-seo-external/snapshot-runs`
|
||||||
|
- `code/public/_admin_templates/domain-seo-external/snapshot-validate-runs`
|
||||||
|
|
||||||
|
这会带来两个直接问题:
|
||||||
|
|
||||||
|
1. 运行数据混进 `public`,容易污染 Git 待提交区
|
||||||
|
2. `latest/*.summary.json/html` 属于运行产物,不适合作为源码提交
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 本次收口目标
|
||||||
|
|
||||||
|
把 `domain-seo-external` 的最新摘要与快照运行产物统一切到:
|
||||||
|
|
||||||
|
- `code/storage/external-seo/latest`
|
||||||
|
- `code/storage/external-seo/snapshot-runs`
|
||||||
|
- `code/storage/external-seo/snapshot-validate-runs`
|
||||||
|
|
||||||
|
并确保管理端 / API 返回路径同步改成 `storage/...` 相对路径。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 本次实际修改
|
||||||
|
|
||||||
|
### 1. 管理端 root 改到 storage
|
||||||
|
|
||||||
|
文件:
|
||||||
|
|
||||||
|
- [Site.php](/www/wwwroot/VideoSource2/code/app/admin/controller/Site.php:1058)
|
||||||
|
|
||||||
|
调整:
|
||||||
|
|
||||||
|
1. `domainExternalSeoSummaryRoot()` 改到 `storage/external-seo/latest`
|
||||||
|
2. `domainExternalSeoSnapshotRunRoot()` 改到 `storage/external-seo/snapshot-runs`
|
||||||
|
3. `domainExternalSeoSnapshotValidateRunRoot()` 改到 `storage/external-seo/snapshot-validate-runs`
|
||||||
|
4. 新增 `storageRelativePath()`,供站外 SEO 这条链专门返回 `storage` 相对路径
|
||||||
|
|
||||||
|
### 2. 管理端站外 SEO 摘要返回值改走 storage 路径
|
||||||
|
|
||||||
|
文件:
|
||||||
|
|
||||||
|
- [Site.php](/www/wwwroot/VideoSource2/code/app/admin/controller/Site.php:2192)
|
||||||
|
|
||||||
|
覆盖范围:
|
||||||
|
|
||||||
|
1. `getDomainExternalSeoSummary`
|
||||||
|
2. `getDomainExternalSeoTrendSummary`
|
||||||
|
3. `getDomainExternalSeoRealSummary`
|
||||||
|
4. Search Console / 百度推送 / 爱站关键词 / site: probe 等摘要接口
|
||||||
|
5. `saveDomainExternalSeoSnapshots`
|
||||||
|
6. `validateDomainExternalSeoSnapshots`
|
||||||
|
7. 手工导入后返回的 `real_summary_*` 路径
|
||||||
|
|
||||||
|
结果:
|
||||||
|
|
||||||
|
这些接口现在返回的是:
|
||||||
|
|
||||||
|
- `external-seo/latest/...`
|
||||||
|
- `external-seo/snapshot-runs/...`
|
||||||
|
- `external-seo/snapshot-validate-runs/...`
|
||||||
|
|
||||||
|
而不是 `public/_admin_templates/...`
|
||||||
|
|
||||||
|
### 3. API 推送入口改到 storage
|
||||||
|
|
||||||
|
文件:
|
||||||
|
|
||||||
|
- [SeoCollector.php](/www/wwwroot/VideoSource2/code/app/api/controller/SeoCollector.php:35)
|
||||||
|
|
||||||
|
调整:
|
||||||
|
|
||||||
|
1. `summaryRoot()` 改到 `storage/external-seo/latest`
|
||||||
|
2. `snapshotRunRoot()` 改到 `storage/external-seo/snapshot-runs`
|
||||||
|
3. `snapshotValidateRunRoot()` 改到 `storage/external-seo/snapshot-validate-runs`
|
||||||
|
4. `saveSnapshots()` / `validateSnapshots()` 的返回路径统一改走 `storageRelativePath()`
|
||||||
|
|
||||||
|
### 4. snapshot run 索引 helper 也改走 storage
|
||||||
|
|
||||||
|
文件:
|
||||||
|
|
||||||
|
- [DomainExternalSeoSnapshotRunIndexHelper.php](/www/wwwroot/VideoSource2/code/app/common/helper/DomainExternalSeoSnapshotRunIndexHelper.php:7)
|
||||||
|
- [DomainExternalSeoSnapshotValidateRunIndexHelper.php](/www/wwwroot/VideoSource2/code/app/common/helper/DomainExternalSeoSnapshotValidateRunIndexHelper.php:7)
|
||||||
|
|
||||||
|
调整:
|
||||||
|
|
||||||
|
1. 原先 helper 内部只识别 `public`
|
||||||
|
2. 现在改为识别 `storage`
|
||||||
|
3. 避免列表接口继续吐绝对路径,或继续带旧 `public` 前缀
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 兼容处理
|
||||||
|
|
||||||
|
为了避免切换后后台立刻读不到最近一次摘要,这次已把当前:
|
||||||
|
|
||||||
|
- `code/public/_admin_templates/domain-seo-external/latest/*`
|
||||||
|
|
||||||
|
复制了一份到:
|
||||||
|
|
||||||
|
- `code/storage/external-seo/latest/*`
|
||||||
|
|
||||||
|
这样下一次后台读 `storage` 时,至少已有一份最近摘要可用。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 已验证
|
||||||
|
|
||||||
|
已通过语法检查:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php -l code/app/admin/controller/Site.php
|
||||||
|
php -l code/app/api/controller/SeoCollector.php
|
||||||
|
php -l code/app/common/helper/DomainExternalSeoSnapshotRunIndexHelper.php
|
||||||
|
php -l code/app/common/helper/DomainExternalSeoSnapshotValidateRunIndexHelper.php
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 当前仍需主线 Codex 注意
|
||||||
|
|
||||||
|
1. `code/public/_admin_templates/domain-seo-external/latest/*` 这批文件在仓库里当前仍是已跟踪文件
|
||||||
|
2. 本次收口已经阻止后续新运行继续写这条 `public` 路径
|
||||||
|
3. 但历史上已被 Git 跟踪的 `public` 运行产物,这次没有直接强删或批量移出版本库
|
||||||
|
4. 主线 Codex 提交前,建议明确把这批运行产物排除在提交之外
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 建议提交范围
|
||||||
|
|
||||||
|
建议优先给主线 Codex 复核这几份代码:
|
||||||
|
|
||||||
|
- [Site.php](/www/wwwroot/VideoSource2/code/app/admin/controller/Site.php:1058)
|
||||||
|
- [SeoCollector.php](/www/wwwroot/VideoSource2/code/app/api/controller/SeoCollector.php:35)
|
||||||
|
- [DomainExternalSeoSnapshotRunIndexHelper.php](/www/wwwroot/VideoSource2/code/app/common/helper/DomainExternalSeoSnapshotRunIndexHelper.php:7)
|
||||||
|
- [DomainExternalSeoSnapshotValidateRunIndexHelper.php](/www/wwwroot/VideoSource2/code/app/common/helper/DomainExternalSeoSnapshotValidateRunIndexHelper.php:7)
|
||||||
|
|
||||||
|
这份说明文档:
|
||||||
|
|
||||||
|
- [2026-04-19-domain-seo-external-storage收口说明.md](/www/wwwroot/VideoSource2/docs/2026-04-19-domain-seo-external-storage收口说明.md:1)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一句话结论
|
||||||
|
|
||||||
|
> 本次已经把 `domain-seo-external` 的 latest / snapshot 运行产物输出主链从 `public/_admin_templates/...` 收口到 `storage/external-seo/...`,后续不应再把这类后台摘要数据当源码提交。
|
||||||
@@ -163,6 +163,7 @@
|
|||||||
今天最新一轮已落档:
|
今天最新一轮已落档:
|
||||||
|
|
||||||
- [40-老模板每日复盘-2026-04-19.md](/www/wwwroot/VideoSource2/docs/old-tmp-seo/40-老模板每日复盘-2026-04-19.md)
|
- [40-老模板每日复盘-2026-04-19.md](/www/wwwroot/VideoSource2/docs/old-tmp-seo/40-老模板每日复盘-2026-04-19.md)
|
||||||
|
- [44-老模板环境核对与后台报错说明-2026-04-19.md](/www/wwwroot/VideoSource2/docs/old-tmp-seo/44-老模板环境核对与后台报错说明-2026-04-19.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
127
docs/old-tmp-seo/43-老模板每日例行巡检-2026-04-19.md
Normal file
127
docs/old-tmp-seo/43-老模板每日例行巡检-2026-04-19.md
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
# 43-老模板每日例行巡检 - 2026-04-19
|
||||||
|
|
||||||
|
## 目的
|
||||||
|
|
||||||
|
从今天开始,老模板 `1001-1005` 这条线每天不是只看蜘蛛日志。
|
||||||
|
|
||||||
|
还必须多做一个固定动作:
|
||||||
|
|
||||||
|
- 把数据库里的老模板域名全部跑一遍访问巡检
|
||||||
|
|
||||||
|
这属于例行工作,不再靠人工临时记忆。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、每日固定动作
|
||||||
|
|
||||||
|
每天至少做这 2 件事:
|
||||||
|
|
||||||
|
1. 看 `24h spider workbench`,分析抓取趋势与 SEO 目标偏差
|
||||||
|
2. 把数据库里老模板 `1001-1005` 的域名全量跑一次访问巡检
|
||||||
|
|
||||||
|
这两件事缺一不可。
|
||||||
|
|
||||||
|
原因很简单:
|
||||||
|
|
||||||
|
1. 蜘蛛日志只能说明“百度怎么抓”
|
||||||
|
2. 但它不能替代“这些域名现在能不能正常访问”
|
||||||
|
3. 如果域名本身访问已经异常,单看 spider workbench 很容易误判
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、已固化脚本
|
||||||
|
|
||||||
|
今天已经新增了一个老模板专用脚本:
|
||||||
|
|
||||||
|
- [old_tmp_domain_daily_probe.php](/www/wwwroot/VideoSource2/code/scripts/old_tmp_domain_daily_probe.php:1)
|
||||||
|
|
||||||
|
它会做这几件事:
|
||||||
|
|
||||||
|
1. 从数据库读取老模板域名
|
||||||
|
2. 默认范围是:
|
||||||
|
- `1001`
|
||||||
|
- `1002`
|
||||||
|
- `1003`
|
||||||
|
- `1004`
|
||||||
|
- `1005`
|
||||||
|
3. 调用现有的 `DomainImportProbeRunHelper`
|
||||||
|
4. 对每个 host 做采样和轨迹探测
|
||||||
|
5. 生成 `json/html` 巡检摘要
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、默认运行方式
|
||||||
|
|
||||||
|
在项目根目录执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /www/wwwroot/VideoSource2/code
|
||||||
|
php scripts/old_tmp_domain_daily_probe.php --format=text
|
||||||
|
```
|
||||||
|
|
||||||
|
如果想看完整 JSON:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /www/wwwroot/VideoSource2/code
|
||||||
|
php scripts/old_tmp_domain_daily_probe.php --format=json
|
||||||
|
```
|
||||||
|
|
||||||
|
如果只想巡检部分模板:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /www/wwwroot/VideoSource2/code
|
||||||
|
php scripts/old_tmp_domain_daily_probe.php --templates=1002,1003 --format=text
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、输出结果在哪里
|
||||||
|
|
||||||
|
默认会落到:
|
||||||
|
|
||||||
|
- `code/storage/domain-import-runs/YYYYMMDD/HHMMSS_old_tmp_daily_probe_xxxxxx/`
|
||||||
|
|
||||||
|
重点文件有两个:
|
||||||
|
|
||||||
|
1. `import-probe.summary.json`
|
||||||
|
2. `import-probe.summary.html`
|
||||||
|
|
||||||
|
文本模式下终端也会直接给出:
|
||||||
|
|
||||||
|
1. 总处理数
|
||||||
|
2. 通过数
|
||||||
|
3. 失败数
|
||||||
|
4. 失败 host 列表
|
||||||
|
5. 对应失败阶段和说明
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、每天回报最少要写什么
|
||||||
|
|
||||||
|
每天给主 Codex 或人工交班时,除了蜘蛛日志结论,还要补这 5 条:
|
||||||
|
|
||||||
|
1. 今天数据库老模板域名总巡检数是多少
|
||||||
|
2. 通过了多少
|
||||||
|
3. 失败了多少
|
||||||
|
4. 失败 host 主要卡在哪个阶段
|
||||||
|
5. 蜘蛛日志异常和访问异常是否落在同一批 host
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、和蜘蛛日志怎么配合看
|
||||||
|
|
||||||
|
最稳的方式是:
|
||||||
|
|
||||||
|
1. 先看 `old_tmp_domain_daily_probe.php` 结果
|
||||||
|
2. 确认是不是有整批域名访问异常
|
||||||
|
3. 再看 `24h spider workbench`
|
||||||
|
4. 最后判断:
|
||||||
|
- 是抓取问题
|
||||||
|
- 还是访问问题
|
||||||
|
- 还是两者同时存在
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、一句话交接
|
||||||
|
|
||||||
|
> 老模板这条线从 `2026-04-19` 起,日常例行工作固定为“两张表一起看”:一张是蜘蛛日志,一张是数据库域名全量访问巡检;只看其中一张,判断都会偏。
|
||||||
198
docs/old-tmp-seo/44-老模板环境核对与后台报错说明-2026-04-19.md
Normal file
198
docs/old-tmp-seo/44-老模板环境核对与后台报错说明-2026-04-19.md
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
# 44-老模板环境核对与后台报错说明 - 2026-04-19
|
||||||
|
|
||||||
|
## 目的
|
||||||
|
|
||||||
|
这份文档专门记录 `2026-04-19` 这次环境核对结论,解决两个后台报错的判断混乱问题:
|
||||||
|
|
||||||
|
1. `读取真实站外 summary 骨架失败`
|
||||||
|
2. `读取 SEO 结果观察面板失败`
|
||||||
|
|
||||||
|
结论先说:
|
||||||
|
|
||||||
|
> 当前核心问题不是老模板代码,也不是 `domain` 表本身,而是当前 `video2` 库缺少 `seo_external_snapshot` 表,同时相关 migration 尚未执行。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、今天实际核对了什么
|
||||||
|
|
||||||
|
按固定顺序核对:
|
||||||
|
|
||||||
|
1. `migrate:status`
|
||||||
|
2. `domain` 表字段状态
|
||||||
|
3. `seo_external_snapshot` 是否存在
|
||||||
|
4. 当前库里的 migration 记录表情况
|
||||||
|
|
||||||
|
特别约束:
|
||||||
|
|
||||||
|
- `migrate` 只能由 `www` 用户执行
|
||||||
|
|
||||||
|
今天的 `migrate:status` 也是按这个约束执行的。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、`migrate:status` 结果
|
||||||
|
|
||||||
|
今天已确认下面 3 条 migration 当前都是 `down`:
|
||||||
|
|
||||||
|
1. `20260119132713 AddBaiduTokenToVideoTable`
|
||||||
|
2. `20260410010000 CreateSeoExternalSnapshotTable`
|
||||||
|
3. `20260410020000 OptimizeSeoExternalSnapshotIndexes`
|
||||||
|
|
||||||
|
这说明:
|
||||||
|
|
||||||
|
1. `d_baidu_token` 这类字段补充没有执行
|
||||||
|
2. `seo_external_snapshot` 建表没有执行
|
||||||
|
3. `seo_external_snapshot` 的索引优化也没有执行
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、当前库的实际状态
|
||||||
|
|
||||||
|
当前 `.env` 已确认连接的是:
|
||||||
|
|
||||||
|
- `DB_NAME = video2`
|
||||||
|
|
||||||
|
### 1. `domain` 表
|
||||||
|
|
||||||
|
今天已确认:
|
||||||
|
|
||||||
|
- `domain` 表存在
|
||||||
|
- 基础字段如:
|
||||||
|
- `d_domain`
|
||||||
|
- `t_id`
|
||||||
|
存在
|
||||||
|
|
||||||
|
但今天没有查到:
|
||||||
|
|
||||||
|
- `d_baidu_token`
|
||||||
|
|
||||||
|
### 2. `seo_external_snapshot` 表
|
||||||
|
|
||||||
|
今天已确认:
|
||||||
|
|
||||||
|
- `seo_external_snapshot` 表不存在
|
||||||
|
|
||||||
|
这和后台报错完全一致。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、为什么“真实站外 summary 骨架失败”
|
||||||
|
|
||||||
|
触发链路是:
|
||||||
|
|
||||||
|
1. 后台接口:
|
||||||
|
- [Site.php getDomainExternalSeoRealSummary](/www/wwwroot/VideoSource2/code/app/admin/controller/Site.php:2941)
|
||||||
|
2. 调用:
|
||||||
|
- [DomainExternalSeoRealSummaryHelper.php](/www/wwwroot/VideoSource2/code/app/common/helper/DomainExternalSeoRealSummaryHelper.php:7)
|
||||||
|
3. 它一上来先走:
|
||||||
|
- `buildAutoSnapshotSummary($days)`
|
||||||
|
4. 这一步内部又调用:
|
||||||
|
- [DomainExternalSeoSnapshotAnalysisHelper.php](/www/wwwroot/VideoSource2/code/app/common/helper/DomainExternalSeoSnapshotAnalysisHelper.php:7)
|
||||||
|
5. 该 helper 底层模型:
|
||||||
|
- [SeoExternalSnapshotModel.php](/www/wwwroot/VideoSource2/code/app/model/SeoExternalSnapshotModel.php:9)
|
||||||
|
6. 绑定表名:
|
||||||
|
- `seo_external_snapshot`
|
||||||
|
|
||||||
|
所以这个报错的根因不是:
|
||||||
|
|
||||||
|
- 骨架模板坏了
|
||||||
|
- provider skeleton 坏了
|
||||||
|
|
||||||
|
而是:
|
||||||
|
|
||||||
|
- 在进入 skeleton fallback 之前,自动快照分支先查表
|
||||||
|
- 当前库没有 `seo_external_snapshot`
|
||||||
|
- 所以直接 SQL 异常
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、为什么“SEO 结果观察面板失败”
|
||||||
|
|
||||||
|
这次也已核对过,后台“SEO 结果观察面板”不是单独一块静态 UI,而是会去读“站外 SEO 观察数据”。
|
||||||
|
|
||||||
|
最像当前入口的是:
|
||||||
|
|
||||||
|
- [router.php](/www/wwwroot/VideoSource2/code/app/admin/config/router.php:161)
|
||||||
|
- `/domain/external/seo/cn/overview`
|
||||||
|
- [Site.php](/www/wwwroot/VideoSource2/code/app/admin/controller/Site.php:2580)
|
||||||
|
- `DomainExternalSeoCnOverviewHelper::buildOverview(...)`
|
||||||
|
|
||||||
|
而这个 overview 底层直接依赖:
|
||||||
|
|
||||||
|
1. `DomainExternalSeoSnapshotAnalysisHelper::buildSummary(...)`
|
||||||
|
2. `DomainExternalSeoSnapshotAnalysisHelper::buildIndexMovementSummary(...)`
|
||||||
|
3. `DomainExternalSeoSnapshotAnalysisHelper::buildKeywordMovementSummary(...)`
|
||||||
|
|
||||||
|
这些 helper 的底层数据源仍然是:
|
||||||
|
|
||||||
|
- `seo_external_snapshot`
|
||||||
|
|
||||||
|
所以这条报错本质上和“真实站外 summary 骨架失败”是同一类问题:
|
||||||
|
|
||||||
|
- 观察面板不是单独坏了
|
||||||
|
- 而是它背后的历史快照表没建起来
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、当前不要误判的点
|
||||||
|
|
||||||
|
### 1. 不要把主矛盾误判成 `domain` 表
|
||||||
|
|
||||||
|
当前 `domain` 表的 migration 确实没补齐,`d_baidu_token` 也没进库。
|
||||||
|
|
||||||
|
但今天这两个后台报错的第一矛盾不是它。
|
||||||
|
|
||||||
|
当前更直接的主矛盾是:
|
||||||
|
|
||||||
|
- `seo_external_snapshot` 缺表
|
||||||
|
|
||||||
|
### 2. 不要把问题误判成老模板 `1001-1005`
|
||||||
|
|
||||||
|
这两个报错属于:
|
||||||
|
|
||||||
|
- 后台站外 SEO 观察能力
|
||||||
|
- migration / 表结构层
|
||||||
|
|
||||||
|
而不是:
|
||||||
|
|
||||||
|
- 老模板前台 SEO 模板渲染失败
|
||||||
|
|
||||||
|
### 3. 不要直接在非 `www` 用户下跑 migrate
|
||||||
|
|
||||||
|
今天已经再次确认这条规则要固定下来:
|
||||||
|
|
||||||
|
- `migrate` 只能由 `www` 用户执行
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、当前最稳结论
|
||||||
|
|
||||||
|
截至 `2026-04-19` 当前环境,最稳结论是:
|
||||||
|
|
||||||
|
1. 当前数据库是 `video2`
|
||||||
|
2. `domain` 表存在,但相关新增字段未补齐
|
||||||
|
3. `seo_external_snapshot` 表不存在
|
||||||
|
4. 对应 migration 当前是 `down`
|
||||||
|
5. 后台“真实站外 summary / SEO 结果观察面板”这两类报错,根因都优先指向:
|
||||||
|
- `seo_external_snapshot` 缺失
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、后续最稳动作顺序
|
||||||
|
|
||||||
|
后续如果要继续推进,不要跳步,按下面顺序:
|
||||||
|
|
||||||
|
1. 先 `migrate:status`
|
||||||
|
2. 再核对 `domain` 表字段
|
||||||
|
3. 再核对 `seo_external_snapshot` 是否缺失
|
||||||
|
4. 最后再决定是否执行 migration
|
||||||
|
|
||||||
|
执行约束:
|
||||||
|
|
||||||
|
- 只能由 `www` 用户执行
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、一句话交接
|
||||||
|
|
||||||
|
> `2026-04-19` 这次后台报错核对已经确认:当前环境主矛盾不是老模板也不是 `domain` 表本身,而是 `video2` 库缺少 `seo_external_snapshot`,且相关 migration 仍是 `down`;后续如果要处理,必须按“先 status、再核字段和缺表、最后由 www 执行”的顺序推进。
|
||||||
@@ -28,6 +28,8 @@
|
|||||||
- [40-老模板每日复盘-2026-04-19.md](/www/wwwroot/VideoSource2/docs/old-tmp-seo/40-老模板每日复盘-2026-04-19.md)
|
- [40-老模板每日复盘-2026-04-19.md](/www/wwwroot/VideoSource2/docs/old-tmp-seo/40-老模板每日复盘-2026-04-19.md)
|
||||||
- [41-老模板SEO代码优化清单-2026-04-19.md](/www/wwwroot/VideoSource2/docs/old-tmp-seo/41-老模板SEO代码优化清单-2026-04-19.md)
|
- [41-老模板SEO代码优化清单-2026-04-19.md](/www/wwwroot/VideoSource2/docs/old-tmp-seo/41-老模板SEO代码优化清单-2026-04-19.md)
|
||||||
- [42-老模板SEO代码优化实录-2026-04-19.md](/www/wwwroot/VideoSource2/docs/old-tmp-seo/42-老模板SEO代码优化实录-2026-04-19.md)
|
- [42-老模板SEO代码优化实录-2026-04-19.md](/www/wwwroot/VideoSource2/docs/old-tmp-seo/42-老模板SEO代码优化实录-2026-04-19.md)
|
||||||
|
- [43-老模板每日例行巡检-2026-04-19.md](/www/wwwroot/VideoSource2/docs/old-tmp-seo/43-老模板每日例行巡检-2026-04-19.md)
|
||||||
|
- [44-老模板环境核对与后台报错说明-2026-04-19.md](/www/wwwroot/VideoSource2/docs/old-tmp-seo/44-老模板环境核对与后台报错说明-2026-04-19.md)
|
||||||
|
|
||||||
昨天的复盘在这里:
|
昨天的复盘在这里:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user