This commit is contained in:
www
2026-05-26 17:02:57 +08:00
parent 7f910ee22f
commit 0096805a49
14 changed files with 830 additions and 58 deletions

View File

@@ -16,7 +16,7 @@ class DomainExternalSeoSnapshotAnalysisHelper
$arrProviders = [];
$arrHosts = [];
$arrLatestIndexByHost = [];
$arrLatestSignalsByHost = [];
$intKeywordSnapshots = (int)SeoExternalSnapshotModel::where('metric_date', '>=', $strStartDate)
->where('scope', 'keyword')
->count();
@@ -28,9 +28,10 @@ class DomainExternalSeoSnapshotAnalysisHelper
self::eachSnapshotRow(
SeoExternalSnapshotModel::where('metric_date', '>=', $strStartDate)
->where('scope', 'host'),
['id', 'provider', 'host', 'scope', 'metric_date', 'status', 'indexed_status', 'baidu_pc_ip_range', 'baidu_mobile_ip_range', 'pc_keyword_count', 'mobile_keyword_count', 'queried_at'],
static function (array $arrItem) use (&$arrProviders, &$arrHosts, &$arrLatestIndexByHost, &$strLatestMetricDate): void {
['id', 'provider', 'snapshot_type', 'host', 'scope', 'metric_date', 'status', 'indexed_status', 'result_count_text', 'baidu_pc_ip_range', 'baidu_mobile_ip_range', 'pc_keyword_count', 'mobile_keyword_count', 'queried_at'],
static function (array $arrItem) use (&$arrProviders, &$arrHosts, &$arrLatestSignalsByHost, &$strLatestMetricDate): void {
$strProvider = trim((string)($arrItem['provider'] ?? ''));
$strSnapshotType = trim((string)($arrItem['snapshot_type'] ?? ''));
$strHost = trim((string)($arrItem['host'] ?? ''));
$strMetricDate = trim((string)($arrItem['metric_date'] ?? ''));
$strStatus = trim((string)($arrItem['status'] ?? ''));
@@ -48,34 +49,33 @@ class DomainExternalSeoSnapshotAnalysisHelper
}
if ($strHost !== '') {
$strHostKey = $strHost;
$arrCurrent = $arrLatestIndexByHost[$strHostKey] ?? null;
$boolShouldReplace = false;
if (!$arrCurrent) {
$boolShouldReplace = true;
} else {
$strCurrentDate = (string)($arrCurrent['metric_date'] ?? '');
$intCurrentQueriedAt = (int)($arrCurrent['queried_at'] ?? 0);
if (strcmp($strCurrentDate, $strMetricDate) < 0) {
$boolShouldReplace = true;
} elseif ($strCurrentDate === $strMetricDate && $intCurrentQueriedAt < $intQueriedAt) {
$boolShouldReplace = true;
}
$arrCandidate = [
'host' => $strHost,
'provider' => $strProvider,
'snapshot_type' => $strSnapshotType,
'metric_date' => $strMetricDate,
'queried_at' => $intQueriedAt,
'status' => $strStatus,
'indexed_status' => $strIndexedStatus,
'result_count_text' => trim((string)($arrItem['result_count_text'] ?? '')),
'baidu_pc_ip_range' => trim((string)($arrItem['baidu_pc_ip_range'] ?? '')),
'baidu_mobile_ip_range' => trim((string)($arrItem['baidu_mobile_ip_range'] ?? '')),
'pc_keyword_count' => (int)($arrItem['pc_keyword_count'] ?? 0),
'mobile_keyword_count' => (int)($arrItem['mobile_keyword_count'] ?? 0),
];
if (self::shouldReplaceSnapshot($arrLatestSignalsByHost[$strHost]['display'] ?? null, $strMetricDate, $intQueriedAt)) {
$arrLatestSignalsByHost[$strHost]['display'] = $arrCandidate;
}
if ($boolShouldReplace) {
$arrLatestIndexByHost[$strHostKey] = [
'host' => $strHost,
'provider' => $strProvider,
'metric_date' => $strMetricDate,
'queried_at' => $intQueriedAt,
'status' => $strStatus,
'indexed_status' => $strIndexedStatus,
'baidu_pc_ip_range' => trim((string)($arrItem['baidu_pc_ip_range'] ?? '')),
'baidu_mobile_ip_range' => trim((string)($arrItem['baidu_mobile_ip_range'] ?? '')),
'pc_keyword_count' => (int)($arrItem['pc_keyword_count'] ?? 0),
'mobile_keyword_count' => (int)($arrItem['mobile_keyword_count'] ?? 0),
];
if ($strSnapshotType === 'site_query'
&& self::shouldReplaceSnapshot($arrLatestSignalsByHost[$strHost]['index'] ?? null, $strMetricDate, $intQueriedAt)) {
$arrLatestSignalsByHost[$strHost]['index'] = $arrCandidate;
}
if ($strSnapshotType === 'aizhan_summary'
&& self::shouldReplaceSnapshot($arrLatestSignalsByHost[$strHost]['keyword'] ?? null, $strMetricDate, $intQueriedAt)) {
$arrLatestSignalsByHost[$strHost]['keyword'] = $arrCandidate;
}
}
},
@@ -85,13 +85,44 @@ class DomainExternalSeoSnapshotAnalysisHelper
$intIndexedLikeCount = 0;
$intKeywordReadyCount = 0;
$intTrafficReadyCount = 0;
$arrHostRows = array_values($arrLatestIndexByHost);
$arrHostRows = [];
foreach ($arrLatestSignalsByHost as $strHost => $arrSignals) {
$arrDisplay = (array)($arrSignals['display'] ?? []);
$arrIndex = (array)($arrSignals['index'] ?? []);
$arrKeyword = (array)($arrSignals['keyword'] ?? []);
$arrProvidersForHost = [];
foreach ([$arrIndex, $arrKeyword, $arrDisplay] as $arrSignalRow) {
$strSignalProvider = trim((string)($arrSignalRow['provider'] ?? ''));
if ($strSignalProvider !== '') {
$arrProvidersForHost[$strSignalProvider] = true;
}
}
$arrHostRows[] = [
'host' => $strHost,
'provider' => implode(',', array_keys($arrProvidersForHost)),
'index_provider' => (string)($arrIndex['provider'] ?? ''),
'keyword_provider' => (string)($arrKeyword['provider'] ?? ''),
'metric_date' => max((string)($arrDisplay['metric_date'] ?? ''), (string)($arrIndex['metric_date'] ?? ''), (string)($arrKeyword['metric_date'] ?? '')),
'queried_at' => max((int)($arrDisplay['queried_at'] ?? 0), (int)($arrIndex['queried_at'] ?? 0), (int)($arrKeyword['queried_at'] ?? 0)),
'status' => (string)($arrDisplay['status'] ?? ''),
'indexed_status' => (string)($arrIndex['indexed_status'] ?? ''),
'result_count_text' => (string)($arrIndex['result_count_text'] ?? ''),
'baidu_pc_ip_range' => (string)($arrKeyword['baidu_pc_ip_range'] ?? ''),
'baidu_mobile_ip_range' => (string)($arrKeyword['baidu_mobile_ip_range'] ?? ''),
'pc_keyword_count' => (int)($arrKeyword['pc_keyword_count'] ?? 0),
'mobile_keyword_count' => (int)($arrKeyword['mobile_keyword_count'] ?? 0),
];
}
foreach ($arrHostRows as &$arrRow) {
$boolIndexedLike = (string)($arrRow['indexed_status'] ?? '') === 'indexed_like';
$boolIndexedLike = self::normalizeIndexState($arrRow) === 'indexed_like';
$boolKeywordReady = (int)($arrRow['pc_keyword_count'] ?? 0) > 0 || (int)($arrRow['mobile_keyword_count'] ?? 0) > 0;
$boolTrafficReady = !self::isZeroRange((string)($arrRow['baidu_pc_ip_range'] ?? ''))
|| !self::isZeroRange((string)($arrRow['baidu_mobile_ip_range'] ?? ''));
$arrRow['indexed_like'] = $boolIndexedLike;
$arrRow['keyword_ready'] = $boolKeywordReady;
$arrRow['traffic_ready'] = $boolTrafficReady;
@@ -113,6 +144,11 @@ class DomainExternalSeoSnapshotAnalysisHelper
if ($intLeftKeyword !== $intRightKeyword) {
return $intRightKeyword <=> $intLeftKeyword;
}
$intLeftIndexed = !empty($arrLeft['indexed_like']) ? 1 : 0;
$intRightIndexed = !empty($arrRight['indexed_like']) ? 1 : 0;
if ($intLeftIndexed !== $intRightIndexed) {
return $intRightIndexed <=> $intLeftIndexed;
}
return strcmp((string)($arrLeft['host'] ?? ''), (string)($arrRight['host'] ?? ''));
});
@@ -402,6 +438,19 @@ class DomainExternalSeoSnapshotAnalysisHelper
return $strRange === '' || $strRange === '0 ~ 0' || $strRange === '0~0';
}
protected static function shouldReplaceSnapshot(?array $arrCurrent, string $strMetricDate, int $intQueriedAt): bool
{
if (!$arrCurrent) {
return true;
}
$strCurrentDate = (string)($arrCurrent['metric_date'] ?? '');
$intCurrentQueriedAt = (int)($arrCurrent['queried_at'] ?? 0);
return strcmp($strCurrentDate, $strMetricDate) < 0
|| ($strCurrentDate === $strMetricDate && $intCurrentQueriedAt < $intQueriedAt);
}
protected static function normalizeIndexState(array $arrRow): string
{
$strIndexedStatus = trim((string)($arrRow['indexed_status'] ?? ''));

View File

@@ -27,14 +27,6 @@ class JsBuilder
@mkdir($targetDir, 0755, true);
}
// 输出文件名(域名专属缓存)
$targetFile = $targetDir . "{$staticHash}.js";
// 如果已经生成过,直接返回
if (file_exists($targetFile)) {
return "/static/js/compiled/{$staticHash}.js";
}
// 你可以像 CSS 一样在这里挂一个“全站基础 JS”
// 注意:如果没有这个文件,就别写入,否则会被 skip
$listJs = [
@@ -46,9 +38,46 @@ class JsBuilder
$finalJsFiles = array_merge($listJs, $jsFiles);
$finalJsFiles = array_values(array_unique(array_filter($finalJsFiles)));
$signatureParts = [
'static_hash' => $staticHash,
'dom_prefix' => $domPrefix,
'builder' => is_file(__FILE__) ? sha1_file(__FILE__) : (string)@filemtime(__FILE__),
'files' => [],
];
// 如果 compiled 已存在且比所有源文件都新,直接返回;否则自动重建。
$intLatestSourceTime = @filemtime(__FILE__) ?: 0;
foreach ($finalJsFiles as $file) {
$file = ltrim((string)$file, '/');
$path = $baseDir . $file;
if (is_file($path)) {
$intLatestSourceTime = max($intLatestSourceTime, (int)@filemtime($path));
$signatureParts['files'][] = [
'file' => $file,
'mtime' => (int)@filemtime($path),
'size' => (int)@filesize($path),
'sha1' => sha1_file($path),
];
} else {
$signatureParts['files'][] = [
'file' => $file,
'missing' => true,
];
}
}
// 前端代理的静态缓存按 path 命中query version 无法兜底;文件名必须跟随源码变化。
$sourceHash = substr(sha1((string)json_encode($signatureParts, JSON_UNESCAPED_SLASHES)), 0, 10);
$targetName = "{$staticHash}-{$sourceHash}.js";
$targetFile = $targetDir . $targetName;
if (file_exists($targetFile) && (int)@filemtime($targetFile) >= $intLatestSourceTime) {
return "/static/js/compiled/{$targetName}";
}
// 合并 JS 文件内容
$allJs = "";
$allJs .= "/*! compiled: {$staticHash}.js */\n";
$allJs .= "/*! compiled: {$targetName} */\n";
$allJs .= "(function(){\n'use strict';\n";
foreach ($finalJsFiles as $file) {
@@ -82,6 +111,6 @@ class JsBuilder
file_put_contents($targetFile, $allJs);
// 返回前端可访问路径
return "/static/js/compiled/{$staticHash}.js";
return "/static/js/compiled/{$targetName}";
}
}