feat: add metadata workbench and shared seo rules

This commit is contained in:
root
2026-04-18 20:23:30 +08:00
parent 2ea87050a5
commit cec1fdbc69
44 changed files with 5488 additions and 68 deletions

View File

@@ -767,8 +767,8 @@ class SiteContext
$arrCandidates = [];
if ($strPage === 'home') {
// 首页优先吃 domain 表,避免已导入/AI 生成的首页 TKD 被旧标题池覆盖
if (in_array($strPage, ['home', 'search', 'category_index', 'category_list', 'rank_index', 'rank_list'], true)) {
// 首页、搜索页、分类页、榜单页优先吃 domain/published 文案,避免旧标题池抢占
$arrCandidates[] = $this->renderSeoFromDomainRecord($strCode, $strPage);
$arrCandidates[] = $this->renderSeoFromPool($strCode, $strPage);
$arrCandidates[] = $this->renderSeoFromLegacyKey($strCode, $strPage);
@@ -832,6 +832,10 @@ class SiteContext
$strSiteName = trim((string)($this->DomainModel->d_name ?? ''));
$strHost = trim((string)($this->DomainModel->d_domain ?? ''));
$strSeoCopyMeta = $this->renderSeoFromPublishedCopy($strCode, $strPage, $strHost, $strSiteName);
if ($strSeoCopyMeta !== '') {
return $strSeoCopyMeta;
}
if ($strPage === 'home') {
return match ($strCode) {
@@ -897,6 +901,115 @@ class SiteContext
return trim((string)($arrGeneric[$strCode] ?? ''));
}
protected function renderSeoFromPublishedCopy(string $strCode, string $strPage, string $strHost, string $strSiteName): string
{
$strHost = trim($strHost);
if ($strHost === '') {
return '';
}
$arrPageConfig = $this->resolveSeoCopySceneConfig($strPage);
if (empty($arrPageConfig['scene'])) {
return '';
}
$strScene = (string)$arrPageConfig['scene'];
$arrPageKeys = (array)($arrPageConfig['page_keys'] ?? []);
$arrPayload = \app\common\helper\SeoCopyStore::getPreferredPageData(
$strHost,
$strScene,
$arrPageKeys,
[\app\common\helper\SeoCopyStore::publishedRoot()]
);
if (empty($arrPayload)) {
return '';
}
$arrTokens = [
'site_name' => $strSiteName,
'keyword' => trim((string)$this->Request->get('keyword', '')),
'parent_category_name' => trim((string)(ConverterMovel::getVal('strVideoParentCategoryName') ?? '')),
'category_name' => trim((string)(ConverterMovel::getVal('strVideoCategoryName') ?? '')),
];
$strField = match ($strCode) {
'title' => 'title',
'keywords' => 'keywords',
'description' => 'description',
default => '',
};
if ($strField === '') {
return '';
}
$strValue = trim((string)($arrPayload[$strField] ?? ''));
if ($strValue === '') {
return '';
}
return \app\common\helper\SeoCopyStore::interpolateTemplate($strValue, $arrTokens);
}
protected function resolveSeoCopySceneConfig(string $strPage): array
{
return match ($strPage) {
'home' => [
'scene' => 'home',
'page_keys' => ['index'],
],
'search' => [
'scene' => 'search',
'page_keys' => array_values(array_filter([
\app\common\helper\SeoCopySchema::buildScenePageKey('search', [
trim((string)$this->Request->get('keyword', '')),
]),
'landing',
])),
],
'category_index' => [
'scene' => 'category_index',
'page_keys' => array_values(array_filter([
\app\common\helper\SeoCopySchema::buildScenePageKey('category_index', [
trim((string)$this->Request->route('strParentCategory')),
]),
'index',
])),
],
'category_list' => [
'scene' => 'category_list',
'page_keys' => array_values(array_filter([
\app\common\helper\SeoCopySchema::buildScenePageKey('category_list', [
trim((string)$this->Request->route('strParentCategory')),
trim((string)$this->Request->route('strCategory')),
]),
'default',
])),
],
'rank_index' => [
'scene' => 'rank_index',
'page_keys' => ['index'],
],
'rank_list' => [
'scene' => 'rank_list',
'page_keys' => array_values(array_filter([
\app\common\helper\SeoCopySchema::buildScenePageKey('rank_list', [
trim((string)$this->Request->route('strSortType')),
trim((string)$this->Request->route('strParentCategory')),
trim((string)$this->Request->route('strCategory')),
]),
\app\common\helper\SeoCopySchema::buildScenePageKey('rank_list', [
trim((string)$this->Request->route('strSortType')),
]),
'default',
])),
],
default => [
'scene' => '',
'page_keys' => [],
],
};
}
protected function normalizeSeoText(mixed $mValue): string
{
$strValue = trim((string)$mValue);
@@ -983,6 +1096,13 @@ class SiteContext
'高清免费',
'免费播放',
];
$arrCoreTopicWords = [
'电影',
'电视剧',
'短剧',
'综艺',
'动漫',
];
$arrParts = [];
foreach ($arrRawParts as $strPart) {
@@ -1008,7 +1128,7 @@ class SiteContext
continue;
}
if (mb_strlen($strPart) <= 2 && !preg_match('/^\d+$/u', $strPart)) {
if (mb_strlen($strPart) <= 2 && !preg_match('/^\d+$/u', $strPart) && !in_array($strPart, $arrCoreTopicWords, true)) {
continue;
}