This commit is contained in:
make
2026-01-09 01:28:23 +08:00
parent eb8c097777
commit 90fc16fbc3
241 changed files with 26518 additions and 3570 deletions

View File

@@ -785,7 +785,7 @@ namespace {
if (!is_string($strPinYin) || trim($strPinYin) === '') {
return 'k_' . substr(sha1($strZh), 0, 12);
}
return $strPinYin;
}
@@ -895,4 +895,51 @@ namespace {
// 转换为 UTF-8丢弃无效字符
return mb_convert_encoding($strInput, 'UTF-8', 'UTF-8');
}
/**
* loadSeoFile function
* 加载 php 文件数组
* @param string $poolId
* @param string $pageType
* @param string $field
* @return array
*/
function loadSeoFile(
string $poolId,
string $pageType,
string $field
): array {
static $memo = [];
$key = "{$poolId}:{$pageType}:{$field}";
if (isset($memo[$key])) {
return $memo[$key];
}
$file =
root_path() .
'public/initdata/video/pools/' .
$poolId . '/' .
$pageType . '/' .
$field . '.php';
if (!is_file($file)) {
return [];
}
$data = require $file;
if (!is_array($data)) {
return [];
}
return $memo[$key] = $data;
}
function buildUrlFromPattern(string $pattern, array $vars): string
{
foreach ($vars as $k => $v) {
$pattern = str_replace('{' . $k . '}', (string)$v, $pattern);
}
return '/' . ltrim($pattern, '/');
}
}

View File

@@ -0,0 +1,239 @@
<?php
namespace app\common;
class CommentPool
{
/**
* 兼容两种调用方式:
* 1) build($domain, $voArray, $cfg)
* 2) build($domain, $videoIdInt, $cfg, $ctx)
*
* @param string $domain
* @param mixed $videoId int(videoId)
* @param array $cfg
* @param array $ctx 可选:当只传 videoId 时用于占位符数据actor/director/name
*/
public static function build(string $domain, $videoId, array $cfg, array $ctx = []): array
{
$tpl = require root_path() . 'public/initdata/comment/comment_text_tpl.php';
if ($videoId <= 0) return [];
// ===== 冻结规则 =====
$videoLimit = self::videoLimit($domain, $videoId);
$cfgLimit = intval($cfg['limit'] ?? 0);
$limit = ($cfgLimit > 0)
? min($cfgLimit, $videoLimit)
: $videoLimit;
$layout = $cfg['layout'] ?? 'A';
$variant = intval($cfg['variant'] ?? 0);
$seed = self::stableSeed($domain . '|' . $videoId . '|' . $layout);
// 生成一个冗余池,再按 layout/variant 取子集
$pool = self::makePool($tpl, $ctx, $seed, max(12, $limit * 2));
return self::pick($pool, $layout, $variant, $limit);
}
private static function videoLimit(string $domain, int $videoId): int
{
// 基础范围39
$base = 3;
// 使用「域名 + 视频」作为冻结源
$seed = self::stableSeed($domain . '|' . $videoId);
return $base + ($seed % 7);
}
private static function stableSeed(string $s): int
{
return intval(sprintf('%u', crc32($s)));
}
private static function makePool(array $tpl, array $ctx, int $seed, int $n): array
{
$actors = self::firstName($ctx['v_actor'] ?? null);
$director = self::firstName($ctx['v_director'] ?? null);
$name = strval($ctx['v_name'] ?? '');
$blocks = array_keys($tpl);
if (!$blocks) return [];
$out = [];
$x = $seed ?: 1;
for ($i = 0; $i < $n; $i++) {
$x = ($x * 1103515245 + 12345) & 0x7fffffff;
// 每条评论 13 个语义块(稳定)
$take = 1 + ($x % 3);
// 稳定洗牌:用 seed 派生顺序,而不是 php shuffleshuffle 非稳定)
$pickedBlocks = self::stablePickBlocks($blocks, $x, $take);
$parts = [];
foreach ($pickedBlocks as $j => $k) {
$arr = $tpl[$k] ?? [];
if (!$arr) continue;
$txt = $arr[($x + $j) % count($arr)];
$txt = str_replace(
['{actor}', '{director}', '{name}'],
[$actors ?: '主演', $director ?: '导演', $name ?: '本片'],
$txt
);
$parts[] = $txt;
}
$text = implode('', array_values(array_unique(array_filter($parts))));
if ($text === '') $text = '整体还行,能看完。';
$out[] = [
'user' => self::fakeUser($x),
'time' => self::fakeTime($x),
'text' => $text,
];
}
return $out;
}
private static function stablePickBlocks(array $blocks, int $seed, int $take): array
{
$cnt = count($blocks);
$take = min($take, $cnt);
$res = [];
for ($i = 0; $i < $take; $i++) {
$idx = ($seed + $i * 7) % $cnt;
$res[] = $blocks[$idx];
}
return $res;
}
private static function pick(array $pool, string $layout, int $variant, int $limit): array
{
$count = count($pool);
if ($count === 0) return [];
$base = match ($layout) {
'A' => 0,
'B' => intval($count * 0.25),
'C' => intval($count * 0.50),
'D' => intval($count * 0.75),
default => 0,
};
$start = ($base + $variant) % $count;
$res = [];
for ($i = 0; $i < $limit; $i++) {
$res[] = $pool[($start + $i) % $count];
}
return $res;
}
private static function firstName($maybeArray): string
{
if (is_array($maybeArray) && isset($maybeArray[0])) return strval($maybeArray[0]);
if (is_string($maybeArray)) return $maybeArray;
return '';
}
private static function fakeUser(int $x): string
{
$users = [
'游客',
'影迷',
'路人甲',
'匿名用户',
'追剧党',
'电影控',
'深夜观众',
'随便看看',
'围观群众',
'看片路人',
'普通观众',
'吃瓜群众',
'影像爱好者',
'路过看看',
'夜猫子',
'周末观众',
'随手一评',
'观影路人',
'老影迷',
'普通网友',
'闲着看看',
'刷到就看',
'下班观众',
'影迷路过',
'随缘观影',
'看片群众',
'佛系观众',
'打发时间',
'路过评论',
'轻度影迷',
'周末看片',
'夜间观影',
'普通用户',
'看片一族',
'随手看看',
'观众之一',
'老黄',
'隔壁老黄',
'小明',
'小红',
'ID0368',
'东方不败',
'黄蓉',
];
return $users[$x % count($users)];
}
private static function fakeTime(int $x): string
{
$times = [
'刚刚',
'刚看完',
'不久前',
'刚才刷到',
'1 小时前',
'2 小时前',
'今天早些时候',
'今天',
'昨天',
'前两天',
'2 天前',
'3 天前',
'前几天',
'这两天',
'最近',
'最近几天',
'一周内',
'1 周前',
'差不多一周前',
'上周',
'前段时间',
'前些天',
'不久之前',
'前不久',
'最近刷到',
'最近看完',
'这几天',
'前几周',
];
return $times[$x % count($times)];
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace app\common;
class PinlunVariant
{
public static function pick(int $seed): int
{
return ($seed >> 4) % 20;
}
public static function group(int $variant): string
{
if ($variant < 4) return 'G1';
if ($variant < 8) return 'G2';
if ($variant < 12) return 'G3';
if ($variant < 16) return 'G4';
return 'G5';
}
}

View File

@@ -28,16 +28,16 @@ class CssBuilder
}
// 输出文件名(作为域名专属缓存)
$targetFile = $targetDir . "dom_{$staticHash}.css";
$targetFile = $targetDir . "{$staticHash}.css";
// 如果已经生成过,直接返回
if (file_exists($targetFile)) {
return "/static/css/compiled/dom_{$staticHash}.css";
return "/static/css/compiled/{$staticHash}.css";
}
$listCss = [
"list/list_base.css","list/list_cols.css","list/list_rows.css",
"title/title_A.css","list/title/title_B.css","list/title/title_C.css","list/title/title_D.css","list/title/title_E.css",
"list/title/title_A.css","list/title/title_B.css","list/title/title_C.css","list/title/title_D.css","list/title/title_E.css","list/title/title_F.css",
"list/shell/shell_A.css","list/shell/shell_B.css","list/shell/shell_C.css","list/shell/shell_D.css",
"list/item/_item_media.css","list/item/_item_poster.css","list/item/_item_rank.css","list/item/_item_text.css",
"list/item/_item_base.css","list/item/_item_title_clamp.css",
@@ -46,6 +46,8 @@ class CssBuilder
"pager/pager_base.css",
"seowords/seowords.css",
"breadcrumb/breadcrumb.css",
"pinlun/_pinlun_base.css",
// "pinlun/_pinlun_base-B.css",
// "rank/rank_home.css",
];
@@ -116,6 +118,6 @@ class CssBuilder
file_put_contents($targetFile, $allCss);
// 返回前端可访问路径
return "/static/css/compiled/dom_{$staticHash}.css";
return "/static/css/compiled/{$staticHash}.css";
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace app\common\helper;
class JsBuilder
{
/**
* 构建当前域名的 JS稳定版本
* - 自动合并模块 JS
* - 可选支持 __PFX__ 替换(和 CSS 同步)
* - 简单压缩空白(不做激进压缩,避免破坏正则/字符串)
* - 完全兼容 TP public/static/
*/
public static function build(array $jsFiles, string $domPrefix, string $staticHash): string
{
// Public 目录路径
$publicPath = root_path() . 'public' . DIRECTORY_SEPARATOR;
// 模块 JS 存放目录
$baseDir = $publicPath . "static/js/modules/";
// 构建后的合并文件目录
$targetDir = $publicPath . "static/js/compiled/";
// 自动创建 compiled 目录
if (!is_dir($targetDir)) {
@mkdir($targetDir, 0755, true);
}
// 输出文件名(域名专属缓存)
$targetFile = $targetDir . "{$staticHash}.js";
// 如果已经生成过,直接返回
if (file_exists($targetFile)) {
return "/static/js/compiled/{$staticHash}.js";
}
// 你可以像 CSS 一样在这里挂一个“全站基础 JS”
// 注意:如果没有这个文件,就别写入,否则会被 skip
$listJs = [
'lazy.js',
'player/dplayer.init.js',
];
// 你的页面/组件 JS也用 $jsFiles 传入
$finalJsFiles = array_merge($listJs, $jsFiles);
$finalJsFiles = array_values(array_unique(array_filter($finalJsFiles)));
// 合并 JS 文件内容
$allJs = "";
$allJs .= "/*! compiled: {$staticHash}.js */\n";
$allJs .= "(function(){\n'use strict';\n";
foreach ($finalJsFiles as $file) {
$file = ltrim((string)$file, '/');
$path = $baseDir . $file;
if (!is_file($path)) {
// echo "<!-- missing js: {$path} -->";
continue;
}
$js = (string)file_get_contents($path);
// 可选:前缀替换(如果你的 JS 里也需要选择器前缀)
$js = str_replace('__PFX__', $domPrefix, $js);
// 轻量压缩:去 BOM、统一换行、压缩行尾空白不做激进 minify
$js = preg_replace('/^\xEF\xBB\xBF/', '', $js);
$js = str_replace(["\r\n", "\r"], "\n", $js);
$js = preg_replace('/[ \t]+\n/', "\n", $js);
$js = trim($js);
// 拼接:用分隔注释便于你线上排查
$allJs .= "\n/* ===== {$file} ===== */\n";
$allJs .= $js . "\n;\n";
}
$allJs .= "\n})();\n";
// 写入合并后的 JS
file_put_contents($targetFile, $allJs);
// 返回前端可访问路径
return "/static/js/compiled/{$staticHash}.js";
}
}

View File

@@ -1,907 +0,0 @@
<?php
namespace app\common\helper;
class SiteStyle
{
/* ======================================================
* 公共入口
* ====================================================== */
public static function getConfig($domainRow = null): array
{
$host = self::resolveHost();
$seed = self::resolveSeed($host);
// 1) 读取或生成冻结 cfg必须持久化
$cfg = self::loadOrGenerateCfg($domainRow, $host, $seed);
// 2) 运行时 payloadTpStyle 用这个)
return self::buildRuntimePayload($cfg, $host, $seed, $domainRow);
}
/* ======================================================
* Host / Seed
* ====================================================== */
private static function resolveHost(): string
{
$host = $_SERVER['HTTP_HOST'] ?? 'default.com';
$host = strtolower(preg_replace('/^www\./i', '', $host));
$host = explode(':', $host)[0];
return $host ?: 'default.com';
}
private static function resolveSeed(string $host): int
{
return crc32($host);
}
/* ======================================================
* 读取 / 生成 / 补齐 / 持久化 cfg冻结层
* ====================================================== */
private static function loadOrGenerateCfg($domainRow, string $host, int $seed): array
{
$cfg = self::readDbConfig($domainRow)
?? self::readLocalJson($host)
?? self::generateFrozenCfg($host, $seed);
// 补齐旧 cfg版本升级用
$patched = false;
[$cfg, $patched] = self::patchCfgIfNeeded($cfg, $host, $seed);
// 不管来源是 DB/JSON只要补丁发生就必须写回保证可控
if ($patched) {
self::persistCfg($domainRow, $host, $cfg);
}
// 如果是新生成的,也要写回
if (!isset($cfg['_persisted'])) {
$cfg['_persisted'] = 1;
self::persistCfg($domainRow, $host, $cfg);
}
return $cfg;
}
private static function persistCfg($domainRow, string $host, array $cfg): void
{
// 去掉运行时标记(避免污染)
$store = $cfg;
unset($store['_persisted']);
self::writeDbConfig($domainRow, $store);
self::writeLocalJson($host, $store);
}
/**
* 新站:生成冻结 cfg四层结构
*/
private static function generateFrozenCfg(string $host, int $seed): array
{
// dom_prefix / hash 必须跟 host 强绑定(不要用 seed
$domPrefix = substr(md5($host . '_dom'), 0, 6);
$staticHash = substr(md5($host . '_v2025'), 0, 10);
// 模板编号(沿用你旧的 1-5
$idx = fn($shift) => (($seed >> $shift) % 5) + 1;
// theme 冻结mode/variant调色板运行时算也可冻结存
$themeMode = ['A', 'B', 'C', 'D'][$seed % 4];
$themeVariant = ($seed % 4) + 1;
// grid 冻结(所有页面通用)
$grid = self::buildGridLayout($seed);
// pages 冻结home/category
$homePage = self::buildHomePageCfg($seed);
$categoryPage = self::buildCategoryPageCfg($seed);
// list_layout 冻结:为“会被渲染的模块”提前生成(后续加模块只要补丁即可)
// 说明:这里生成的是“模块级默认布局”,页面渲染时按 module 取用即可
$listLayout = self::buildDefaultListLayouts($seed, $homePage, $categoryPage);
return [
'meta' => [
'host' => $host,
'seed' => $seed,
'dom_prefix' => $domPrefix,
'static_hash' => $staticHash,
'version' => 4, // 你现在的 cfg 版本号(以后升级用)
],
'global' => [
'page_max_width_pc' => self::$WIDTH_POOL[$seed % count(self::$WIDTH_POOL)],
'grid' => $grid,
'theme' => [
'mode' => $themeMode,
'variant' => $themeVariant,
],
],
'pages' => [
'home' => $homePage,
'category' => $categoryPage,
],
'components' => [
'templates' => [
'head_tpl' => $idx(0),
'foot_tpl' => $idx(1),
'banner_tpl' => $idx(2),
'list_tpl' => $idx(3),
'detail_tpl' => $idx(9),
'play_tpl' => $idx(10),
// 你旧系统里还有 recommend/trending/newest/ranking/category 等独立 tpl可继续保留
'recommend_tpl' => $idx(4),
'trending_tpl' => $idx(5),
'newest_tpl' => $idx(6),
'ranking_tpl' => $idx(7),
'category_tpl' => $idx(8),
],
'list' => [
'item_variants' => [
'01' => 20,
'02' => 20,
'03' => 20,
'04' => 20,
'05' => 20,
],
'semantic_map' => self::$MODULE_ITEM_WEIGHT,
'shell_rules' => self::$ITEM_SHELL_MAP,
],
],
// 模块布局冻结(核心)
'list_layout' => $listLayout,
];
}
/**
* 旧 cfg 补齐规则:只要缺字段就补,并标记 patched=true
*/
private static function patchCfgIfNeeded(array $cfg, string $host, int $seed): array
{
$patched = false;
// meta
if (!isset($cfg['meta'])) {
$cfg['meta'] = [];
$patched = true;
}
if (!isset($cfg['meta']['host'])) {
$cfg['meta']['host'] = $host;
$patched = true;
}
if (!isset($cfg['meta']['seed'])) {
$cfg['meta']['seed'] = $seed;
$patched = true;
}
if (!isset($cfg['meta']['dom_prefix'])) {
$cfg['meta']['dom_prefix'] = substr(md5($host . '_dom'), 0, 6);
$patched = true;
}
if (!isset($cfg['meta']['static_hash'])) {
$cfg['meta']['static_hash'] = substr(md5($host . '_v2025'), 0, 10);
$patched = true;
}
if (!isset($cfg['meta']['version'])) {
$cfg['meta']['version'] = 4;
$patched = true;
}
// global
if (!isset($cfg['global'])) {
$cfg['global'] = [];
$patched = true;
}
if (!isset($cfg['global']['page_max_width_pc'])) {
$cfg['global']['page_max_width_pc'] = self::$WIDTH_POOL[$seed % count(self::$WIDTH_POOL)];
$patched = true;
}
if (!isset($cfg['global']['grid'])) {
$cfg['global']['grid'] = self::buildGridLayout($seed);
$patched = true;
}
if (!isset($cfg['global']['theme'])) {
$cfg['global']['theme'] = [
'mode' => ['A', 'B', 'C', 'D'][$seed % 4],
'variant' => ($seed % 4) + 1,
];
$patched = true;
}
// pages
if (!isset($cfg['pages'])) {
$cfg['pages'] = [];
$patched = true;
}
if (!isset($cfg['pages']['home'])) {
$cfg['pages']['home'] = self::buildHomePageCfg($seed);
$patched = true;
}
if (!isset($cfg['pages']['category'])) {
$cfg['pages']['category'] = self::buildCategoryPageCfg($seed);
$patched = true;
}
// components
if (!isset($cfg['components'])) {
$cfg['components'] = [];
$patched = true;
}
if (!isset($cfg['components']['templates'])) {
$idx = fn($shift) => (($seed >> $shift) % 5) + 1;
$cfg['components']['templates'] = [
'head_tpl' => $idx(0),
'foot_tpl' => $idx(1),
'banner_tpl' => $idx(2),
'list_tpl' => $idx(3),
'detail_tpl' => $idx(9),
'play_tpl' => $idx(10),
'recommend_tpl' => $idx(4),
'trending_tpl' => $idx(5),
'newest_tpl' => $idx(6),
'ranking_tpl' => $idx(7),
'category_tpl' => $idx(8),
];
$patched = true;
}
if (!isset($cfg['components']['list'])) {
$cfg['components']['list'] = [
'item_variants' => ['01'=>20,'02'=>20,'03'=>20,'04'=>20,'05'=>20],
'semantic_map' => self::$MODULE_ITEM_WEIGHT,
'shell_rules' => self::$ITEM_SHELL_MAP,
];
$patched = true;
}
// list_layout冻结默认模块布局
if (!isset($cfg['list_layout']) || !is_array($cfg['list_layout'])) {
$cfg['list_layout'] = self::buildDefaultListLayouts(
$seed,
$cfg['pages']['home'],
$cfg['pages']['category']
);
$patched = true;
} else {
// 补齐缺少的默认模块布局(升级时很关键:你说的“分类页不写入”就靠这里补)
$needModules = self::collectNeededModules($cfg['pages']['home'], $cfg['pages']['category']);
foreach ($needModules as $m) {
if (!isset($cfg['list_layout'][$m])) {
$cfg['list_layout'][$m] = self::buildListCfgForModule($seed + crc32($m), $m, $cfg);
$patched = true;
}
}
}
return [$cfg, $patched];
}
/* ======================================================
* Runtime PayloadTpStyle
* ====================================================== */
private static function buildRuntimePayload(array $cfg, string $host, int $seed, $domainRow): array
{
$domPrefix = $cfg['meta']['dom_prefix'];
$staticHash = $cfg['meta']['static_hash'];
// 运行时主题色(从冻结的 mode/variant 计算)
$themeMode = $cfg['global']['theme']['mode'] ?? 'A';
$themeVariant = (int)($cfg['global']['theme']['variant'] ?? 1);
$themeColors = self::buildTheme($seed, $themeMode, $themeVariant);
// templates路径输出保持你旧版结构
$tpl = $cfg['components']['templates'];
$templates = [
'head' => "head/head_" . sprintf("%02d", (int)$tpl['head_tpl']),
'foot' => "footer/footer_" . sprintf("%02d", (int)$tpl['foot_tpl']),
'banner' => "module/banner/banner_" . sprintf("%02d", (int)$tpl['banner_tpl']),
'list' => "module/list/list_" . sprintf("%02d", (int)$tpl['list_tpl']),
'detail' => "module/detail/detail_" . sprintf("%02d", (int)$tpl['detail_tpl']),
'play' => "module/play/play_" . sprintf("%02d", (int)$tpl['play_tpl']),
// 旧系统模块(保留)
'recommend' => "module/recommend/recommend_" . sprintf("%02d", (int)$tpl['recommend_tpl']),
'trending' => "module/trending/trending_" . sprintf("%02d", (int)$tpl['trending_tpl']),
'newest' => "module/newest/newest_" . sprintf("%02d", (int)$tpl['newest_tpl']),
'ranking' => "module/ranking/ranking_" . sprintf("%02d", (int)$tpl['ranking_tpl']),
'category' => "module/category/category_" . sprintf("%02d", (int)$tpl['category_tpl']),
];
// css_files你当前只要 head/footer/banner/list/detail/play + 可选模块 css
$cssFiles = [
"head/head_" . sprintf("%02d", (int)$tpl['head_tpl']) . ".css",
"footer/footer_" . sprintf("%02d", (int)$tpl['foot_tpl']) . ".css",
"banner/banner_" . sprintf("%02d", (int)$tpl['banner_tpl']) . ".css",
"list/list_" . sprintf("%02d", (int)$tpl['list_tpl']) . ".css",
"detail/detail_" . sprintf("%02d", (int)$tpl['detail_tpl']) . ".css",
"play/play_" . sprintf("%02d", (int)$tpl['play_tpl']) . ".css",
];
$cssFiles = array_values(array_unique($cssFiles));
return [
'host' => $host,
'seed' => $seed,
'dom_prefix' => $domPrefix,
'static_hash' => $staticHash,
// cfg 全量给模板(你现在模板一直在用)
'template_cfg' => $cfg,
// 兼容你现在模板里直接用的快捷字段
'page_max_width_pc' => $cfg['global']['page_max_width_pc'],
'list_layout' => $cfg['list_layout'],
'category_page' => $cfg['pages']['category'],
// 原结构
'templates' => $templates,
'css_files' => $cssFiles,
] + $themeColors;
}
/* ======================================================
* Pages cfg冻结规则池 + 稳定映射)
* ====================================================== */
private static function buildHomePageCfg(int $seed): array
{
$modulePool = ['newest', 'hot', 'rank', 'recommend', 'trending'];
$shuffled = self::shuffleStable($modulePool, $seed + 101);
// 每域名固定 3~5
$count = 3 + ($seed % 3);
return [
'top_modules' => array_slice($shuffled, 0, $count),
];
}
private static function buildCategoryPageCfg(int $seed): array
{
return [
'top_block' => self::buildCategoryTopBlock($seed),
'sections_pool' => self::buildCategorySectionsPool($seed),
];
}
private static function buildCategoryTopBlock(int $seed): array
{
$modules = ['newest', 'hot', 'rank'];
return ['module' => $modules[$seed % count($modules)]];
}
private static function buildCategorySectionsPool(int $seed): array
{
$basePool = [
['shell' => 'A', 'item' => '01', 'title' => 'F', 'class' => 'compact'],
['shell' => 'B', 'item' => '01', 'title' => 'F', 'class' => ''],
['shell' => 'B', 'item' => '02', 'title' => 'F', 'class' => 'loose'],
['shell' => 'C', 'item' => '05', 'title' => 'F', 'class' => 'top compact'],
];
$pool = self::shuffleStable($basePool, $seed + 301);
$count = 3 + ($seed % 3); // 3~5basePool 只有4条这里实际最大=4你以后扩展 basePool 即可>5
return array_slice($pool, 0, min($count, count($pool)));
}
/**
* 供模板调用:二级分类块 cfg不再在模板里写 crc32 逻辑)
*
* 用法(模板里):
* <?php $cfg = \app\common\helper\SiteStyle::buildCategorySectionCfg($TpStyle['template_cfg'], $arrChildrenCategory['v_category_en'], $intChildrenKey); ?>
*/
public static function buildCategorySectionCfg(array $cfg, string $subCategoryEn, int $order = 0): array
{
$seed = (int)($cfg['meta']['seed'] ?? 0)
+ crc32($subCategoryEn)
+ $order * 13;
$pool = $cfg['pages']['category']['sections_pool'] ?? [];
if (empty($pool)) {
// 兜底
$pool = self::buildCategorySectionsPool($seed);
}
$base = $pool[$seed % count($pool)];
$item = (string)$base['item'];
$itemType = self::$ITEM_TYPE_MAP[$item] ?? 'poster';
$variantCount = (int)($cfg['components']['list']['item_variants'][$item] ?? 1);
$variant = $variantCount > 0 ? ($seed % $variantCount) : 0;
return [
'shell' => $base['shell'],
'item' => $item,
'item_type' => $itemType,
'item_variant' => $variant,
'title' => $base['title'],
'class' => $base['class'],
'grid' => $cfg['global']['grid'],
];
}
/* ======================================================
* list_layout冻结模块默认布局
* ====================================================== */
private static function buildDefaultListLayouts(int $seed, array $homePage, array $categoryPage): array
{
$needModules = self::collectNeededModules($homePage, $categoryPage);
$out = [];
foreach ($needModules as $m) {
$out[$m] = self::buildListCfgForModule($seed + crc32($m), $m, [
'global' => ['grid' => self::buildGridLayout($seed)],
'components' => ['list' => ['item_variants' => ['01'=>20,'02'=>20,'03'=>20,'04'=>20,'05'=>20]]],
]);
}
return $out;
}
private static function collectNeededModules(array $homePage, array $categoryPage): array
{
$modules = [];
// home 顶部模块
foreach (($homePage['top_modules'] ?? []) as $m) {
$modules[] = $m;
}
// category 顶部块模块
if (!empty($categoryPage['top_block']['module'])) {
$modules[] = $categoryPage['top_block']['module'];
}
// 常见页面:你后面肯定会用到(先冻结)
$modules[] = 'category_list';
$modules[] = 'search_list';
// 去重
$modules = array_values(array_unique(array_filter($modules)));
return $modules;
}
private static function buildListCfgForModule(int $seed, string $module, array $cfg): array
{
$layout = self::buildListLayout($seed, $module);
// Title
$layout['title'] = self::pickTitleTpl($seed + 17, $module);
$layout['title_text'] = self::buildTitleText($seed + 19, $module);
// Behavior
$behavior = self::buildListBehavior($seed + 23, $module);
$layout['behavior'] = $behavior;
$layout['class'] = trim(implode(' ', array_filter($behavior)));
// item variant冻结
$layout['item_variant'] = self::pickItemVariant(
$seed + 31,
$layout['item'],
$module
);
// grid冻结引用全局
$layout['grid'] = $cfg['global']['grid'] ?? self::buildGridLayout($seed);
return $layout;
}
/**
* 构建 List 布局(带语义权重 + 合法映射)
*/
private static function buildListLayout(int $seed, string $module): array
{
// Item语义优先
$itemIdx = self::pickItemBySemantic($module, $seed);
$itemType = self::$ITEM_TYPE_MAP[$itemIdx] ?? 'poster';
// Shell只在合法池中选
$allowedShells = self::$ITEM_SHELL_MAP[$itemType] ?? ['B'];
$shell = $allowedShells[($seed >> 4) % count($allowedShells)];
// Title只是一个默认值最终会被 pickTitleTpl 覆盖)
$titlePool = ['A', 'B', 'C', 'D', 'E'];
$title = $titlePool[($seed >> 6) % count($titlePool)];
return [
'module' => $module,
'item' => $itemIdx,
'item_type' => $itemType,
'shell' => $shell,
'title' => $title,
'class' => '', // 最终由 buildListBehavior 生成
];
}
/**
* item variant由模块/seed 稳定取值
*/
private static function pickItemVariant(int $seed, string $item, string $scope = 'list'): int
{
$count = 20;
$salt = crc32($scope);
return abs($seed + $salt) % $count;
}
/**
* 列表行为Behavior
*/
private static function buildListBehavior(int $seed, string $module): array
{
$behavior = [];
switch ($module) {
case 'newest':
$behavior[] = ($seed % 2 === 0) ? 'compact' : '';
$behavior[] = ($seed % 2 === 1) ? 'collapsed' : '';
break;
case 'hot':
case 'trending':
case 'recommend':
$behavior[] = ($seed % 3 === 0) ? 'loose' : '';
$behavior[] = ($seed % 2 === 0) ? 'emphasis' : '';
break;
case 'rank':
$behavior[] = 'top';
$behavior[] = 'compact';
break;
default:
// category_list / search_list 等兜底
$behavior[] = ($seed % 2 === 0) ? 'compact' : '';
}
return array_values(array_filter($behavior));
}
/**
* 根据模块语义 + seed 选择 Item带权重
*/
private static function pickItemBySemantic(string $module, int $seed): string
{
$conf = self::$MODULE_ITEM_WEIGHT[$module] ?? null;
if (!$conf) {
$pool = array_keys(self::$ITEM_TYPE_MAP);
return $pool[$seed % count($pool)];
}
// primary 75%
if (($seed & 0b11) !== 0) {
return $conf['primary'][$seed % count($conf['primary'])];
}
// secondary
if (!empty($conf['secondary']) && (($seed >> 2) & 1)) {
return $conf['secondary'][$seed % count($conf['secondary'])];
}
return $conf['fallback'][0];
}
/* ======================================================
* Grid冻结
* ====================================================== */
private static function pickPcCols(int $seed, string $size): int
{
$pool = self::$PC_COLS_MAP[$size] ?? [3];
return $pool[$seed % count($pool)];
}
private static function buildGridLayout(int $seed): array
{
return [
// H513 列
'cols_h5' => [1, 2, 3][$seed % 3],
// PC按断点
'cols_pc_sm' => self::pickPcCols($seed + 11, 'sm'),
'cols_pc_md' => self::pickPcCols($seed + 23, 'md'),
'cols_pc_lg' => self::pickPcCols($seed + 37, 'lg'),
];
}
/* ======================================================
* Title 文案池
* ====================================================== */
private static function mapTitleType(string $module): string
{
// 你要求category/search/recommend 可复用 newest 的文案池
return match ($module) {
'category_list', 'search_list', 'recommend' => 'newest',
default => $module,
};
}
private static function pickStable(array $list, int $seed)
{
if (empty($list)) return null;
$seed = abs($seed);
return $list[$seed % count($list)];
}
private static function buildTitleText(int $seed, string $module): array
{
$type = self::mapTitleType($module);
if (!isset(self::$TITLE_POOL[$type])) {
$type = 'newest';
}
$pool = self::$TITLE_POOL[$type];
return [
'primary' => self::pickStable($pool['primary'], $seed),
'secondary' => self::pickStable($pool['secondary'], $seed >> 2),
'seo' => self::pickStable($pool['seo'], $seed >> 4),
];
}
private static function pickTitleTpl(int $seed, string $module): string
{
$map = [
'newest' => ['A', 'B', 'D'],
'hot' => ['A', 'C', 'D', 'B'],
'rank' => ['E', 'D'],
'trending' => ['A', 'C', 'D'],
'recommend' => ['A', 'B', 'C'],
'category_list'=> ['F', 'A'],
'search_list' => ['A', 'B'],
];
$list = $map[$module] ?? ['A'];
return $list[$seed % count($list)];
}
/* ======================================================
* DB / JSON
* ====================================================== */
private static function readDbConfig($domainRow): ?array
{
try {
if (!$domainRow) return null;
$raw = is_array($domainRow)
? ($domainRow['t_cfg'] ?? null)
: ($domainRow->t_cfg ?? null);
if (empty($raw)) return null;
return json_decode($raw, true) ?: null;
} catch (\Throwable $e) {
return null;
}
}
private static function writeDbConfig($domainRow, array $cfg): void
{
if (!$domainRow || is_array($domainRow)) return;
try {
$domainRow->t_cfg = json_encode($cfg, JSON_UNESCAPED_UNICODE);
$domainRow->save();
} catch (\Throwable $e) {
}
}
private static function readLocalJson(string $host): ?array
{
$file = root_path() . "storage/theme_cache/{$host}.json";
if (!is_file($file)) return null;
return json_decode(file_get_contents($file), true) ?: null;
}
private static function writeLocalJson(string $host, array $cfg): void
{
$dir = root_path() . "storage/theme_cache/";
if (!is_dir($dir)) @mkdir($dir, 0755, true);
file_put_contents(
$dir . "{$host}.json",
json_encode($cfg, JSON_UNESCAPED_UNICODE)
);
}
/* ======================================================
* 稳定洗牌
* ====================================================== */
private static function shuffleStable(array $arr, int $seed): array
{
$result = $arr;
$rand = $seed;
for ($i = count($result) - 1; $i > 0; $i--) {
$rand = ($rand * 31 + 17) & 0x7fffffff;
$j = $rand % ($i + 1);
[$result[$i], $result[$j]] = [$result[$j], $result[$i]];
}
return $result;
}
/* ======================================================
* 主题色(沿用你原来的 buildTheme + 辅助函数)
* ====================================================== */
private static function buildTheme(int $seed, string $mode, int $variant): array
{
$base = $seed + $variant * 97;
if ($mode === 'D') $mode = ['A', 'B', 'C'][$base % 3];
$h = $base % 360;
switch ($mode) {
case 'A':
$primary = self::hslToHex($h, 78, 55);
$secondary = self::hslToHex($h + 30, 65, 50);
$accent = self::hslToHex($h + 310, 85, 56);
$bg = '#F8FAFC';
$bgSoft = '#F1F5F9';
break;
case 'B':
$primary = self::hslToHex($h, 55, 60);
$secondary = self::hslToHex($h + 40, 40, 65);
$accent = self::hslToHex($h + 300, 45, 58);
$bg = '#FBFBFE';
$bgSoft = '#F5F5FA';
break;
case 'C':
$primary = self::hslToHex($h, 80, 55);
$secondary = self::hslToHex($h + 200, 60, 50);
$accent = self::hslToHex($h + 40, 75, 60);
$bg = self::hslToHex($h + 190, 30, 12);
$bgSoft = self::hslToHex($h + 190, 25, 16);
break;
default:
$primary = self::hslToHex($h, 55, 60);
$secondary = self::hslToHex($h + 40, 40, 65);
$accent = self::hslToHex($h + 300, 45, 58);
$bg = '#FBFBFE';
$bgSoft = '#F5F5FA';
}
$dark = self::isDarkColor($bg);
return [
'color_primary' => $primary,
'color_secondary' => $secondary,
'color_accent' => $accent,
'color_bg' => $bg,
'color_bg_soft' => $bgSoft,
'color_text_primary' => $dark ? '#FFF' : '#111',
'color_text_secondary' => $dark ? '#CCC' : '#666',
'color_border' => $dark ? 'rgba(255,255,255,.1)' : 'rgba(0,0,0,.1)',
'color_grad_start' => $primary,
'color_grad_end' => $secondary,
'shadow_color' => $dark ? 'rgba(0,0,0,.7)' : 'rgba(0,0,0,.12)',
'is_dark_mode' => $dark,
];
}
private static function hslToHex($h, $s, $l): string
{
$h /= 360;
$s /= 100;
$l /= 100;
$c = (1 - abs(2 * $l - 1)) * $s;
$x = $c * (1 - abs(fmod($h * 6, 2) - 1));
$m = $l - $c / 2;
if ($h < 1 / 6) [$r, $g, $b] = [$c, $x, 0];
elseif ($h < 2 / 6) [$r, $g, $b] = [$x, $c, 0];
elseif ($h < 3 / 6) [$r, $g, $b] = [0, $c, $x];
elseif ($h < 4 / 6) [$r, $g, $b] = [0, $x, $c];
elseif ($h < 5 / 6) [$r, $g, $b] = [$x, 0, $c];
else [$r, $g, $b] = [$c, 0, $x];
$r = round(($r + $m) * 255);
$g = round(($g + $m) * 255);
$b = round(($b + $m) * 255);
return sprintf("#%02X%02X%02X", $r, $g, $b);
}
private static function isDarkColor(string $hex): bool
{
$hex = ltrim($hex, '#');
$r = hexdec(substr($hex, 0, 2));
$g = hexdec(substr($hex, 2, 2));
$b = hexdec(substr($hex, 4, 2));
$lum = (0.2126 * $r + 0.7152 * $g + 0.0722 * $b) / 255;
return $lum < 0.45;
}
/* ======================================================
* 常量池
* ====================================================== */
private static array $WIDTH_POOL = [860, 900, 960, 1000, 1080, 1140, 1200, 1280, 1360];
private static array $PC_COLS_MAP = [
'sm' => [3, 4],
'md' => [4, 5, 6],
'lg' => [6, 7, 8, 9],
];
/**
* Shell × Item 合法组合映射poster/media/rank
*/
private static array $ITEM_SHELL_MAP = [
'poster' => ['B', 'D'],
'media' => ['A', 'D'],
'rank' => ['C'],
];
/**
* Item 编号 → Item 类型
*/
private static array $ITEM_TYPE_MAP = [
'01' => 'poster',
'02' => 'media',
'03' => 'rank',
'04' => 'poster',
'05' => 'rank',
];
/**
* 模块语义 → Item 权重池
*/
private static array $MODULE_ITEM_WEIGHT = [
'newest' => [
'primary' => ['01', '04'],
'secondary' => ['02'],
'fallback' => ['01'],
],
'hot' => [
'primary' => ['01', '04'],
'secondary' => ['02'],
'fallback' => ['01'],
],
'rank' => [
'primary' => ['05'],
'secondary' => ['03'],
'fallback' => ['05'],
],
// 兜底模块
'trending' => [
'primary' => ['01', '04'],
'secondary' => ['02'],
'fallback' => ['01'],
],
'recommend' => [
'primary' => ['01', '04'],
'secondary' => ['02'],
'fallback' => ['01'],
],
'category_list' => [
'primary' => ['01'],
'secondary' => ['02'],
'fallback' => ['01'],
],
'search_list' => [
'primary' => ['02'],
'secondary' => ['01'],
'fallback' => ['02'],
],
];
private static array $TITLE_POOL = [
'newest' => [
'primary' => ['最近更新','最新上线','新片速递','今日更新','新内容推荐'],
'secondary' => ['第一时间为你呈现','每日持续更新','不错过任何新片','刚刚上线,抢先观看'],
'seo' => ['最新电影电视剧更新','今日最新影视资源','新上线影视内容合集'],
],
'hot' => [
'primary' => ['热门推荐','热播精选','人气必看','大家都在看'],
'secondary' => ['近期热度持续攀升','高点击率影片推荐','口碑与热度兼具','当前最受欢迎内容'],
'seo' => ['热门影视作品推荐','高人气电影电视剧合集','热播影视排行榜推荐'],
],
'rank' => [
'primary' => ['排行榜','热度榜单','人气排行','播放榜'],
'secondary' => ['数据实时更新','热度排序参考','近期播放趋势','高人气作品排行'],
'seo' => ['影视排行榜前十名','热门电影电视剧排行','高播放量影视榜单'],
],
];
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,229 @@
<?php
declare(strict_types=1);
namespace app\common\helper;
class UrlBuilder
{
/**
* 当前域名 TpStyle运行期注入
*/
protected array $tp;
public function __construct(array $tpStyle)
{
$this->tp = $tpStyle;
}
/* ==========================================================
* 基础能力
* ========================================================== */
protected function family(): array
{
return $this->tp['template_cfg']['url_family'] ?? [];
}
protected function trimSlash(string $path): string
{
return '/' . ltrim($path, '/');
}
/* ==========================================================
* 首页
* ========================================================== */
public function home(): string
{
return '/';
}
/* ==========================================================
* 分类
* ========================================================== */
/**
* 分类首页(展示所有一级分类)
* pattern: classes
*/
public function categoryHome(): string
{
$pattern = $this->family()['category_home']['pattern']
?? 'classes';
return $this->replacePattern($pattern, []);
}
/**
* 一级分类页
* pattern: classes/{strParentCategory}
*/
public function categoryParent(string $strParentCategory): string
{
$pattern = $this->family()['category_parent']['pattern']
?? 'classes/{strParentCategory}';
return $this->replacePattern($pattern, [
'strParentCategory' => $strParentCategory,
]);
}
/**
* 二级分类页(分页)
* pattern: classes/{strParentCategory}/{strCategory}/page/{intPage}
*/
public function categoryChild(
string $strParentCategory,
string $strCategory,
int|string $intPage = 1
): string {
$pattern = $this->family()['category_child']['pattern']
?? 'classes/{strParentCategory}/{strCategory}/page/{intPage}';
return $this->replacePattern($pattern, [
'strParentCategory' => $strParentCategory,
'strCategory' => $strCategory,
'intPage' => max(1, (int)$intPage),
]);
}
/* ==========================================================
* 排行榜
* ========================================================== */
/**
* 排行榜首页
* /rank/index
*/
public function rankIndex(): string
{
$pattern = $this->family()['rank_index']['pattern']
?? 'rank/index';
return $this->replacePattern($pattern, []);
}
/**
* 排行榜列表
* /rank/day
* /rank/day/action
*/
public function rankList(string $strSortType): string
{
$tpl = $this->family()['rank_list']['pattern']
?? 'rank/{strSortType}';
return $this->replacePattern($tpl, [
'strSortType' => $strSortType,
]);
}
/* ==========================================================
* 详情页
* ========================================================== */
/**
* 详情页
* /voddetail/slug-id
*/
public function detail(string $strPinyin, int $intVId): string
{
$pattern = $this->family()['detail']['pattern']
?? 'voddetail/{strPinyin}-{intVId}';
return $this->replacePattern($pattern, [
'strPinyin' => $strPinyin,
'intVId' => $intVId,
]);
}
/**
* 伪造详情页
* pattern: video/{strPinyin}-{intVId}-{intVForgeId}
*/
public function detailForge(
string $strPinyin,
int $intVId,
int $intVForgeId
): string {
$pattern = $this->family()['detail_forge']['pattern']
?? 'video/{strPinyin}-{intVId}-{intVForgeId}';
return $this->replacePattern($pattern, [
'strPinyin' => $strPinyin,
'intVId' => $intVId,
'intVForgeId' => $intVForgeId,
]);
}
/**
* 播放页
* /vodplay/slug-id-line-episode
*/
public function play(
string $strPinyin,
int $intVId,
string $strPlayType,
int $intPlayIndex
): string {
$pattern = $this->family()['play']['pattern']
?? 'vodplay/{strPinyin}-{intVId}-{strPlayType}-{intPlayIndex}';
return $this->replacePattern($pattern, [
'strPinyin' => $strPinyin,
'intVId' => $intVId,
'strPlayType' => $strPlayType,
'intPlayIndex' => $intPlayIndex,
]);
}
/* ==========================================================
* 搜索
* ========================================================== */
/**
* 搜索入口
* /search.html
*/
public function searchEntry(): string
{
$entry = $this->family()['search']['pattern'] ?? 'search.html';
return $this->trimSlash($entry);
}
/**
* 搜索结果
* /search.html?keyword=xxx
*/
public function searchResult(string $keyword): string
{
$entry = $this->searchEntry();
return $entry . '?keyword=' . urlencode($keyword);
}
/**
* 历史记录
*/
public function history(): string
{
$pattern = $this->family()['history']['pattern']
?? 'history';
return $this->replacePattern($pattern, []);
}
protected function replacePattern(string $pattern, array $vars): string
{
foreach ($vars as $key => $val) {
$pattern = str_replace('{' . $key . '}', (string)$val, $pattern);
}
return $this->trimSlash($pattern);
}
}

View File

@@ -0,0 +1,180 @@
<?php
namespace app\common\seo;
use think\facade\Request;
use app\common\helper\SiteStyle;
use think\helper\Str;
class SeoRenderer
{
protected array $cfg; // 冻结 cfg 中的 seo
protected array $pool; // 运行期 seo_phrase 池
public function __construct(array $tpStyle)
{
$this->cfg = $tpStyle['template_cfg']['seo'] ?? [];
// 根据 pool_id 取运行期池(不冻结)
// $poolId = $this->cfg['pool_id'] ?? '';
// $this->pool = SiteStyle::SEO_POOL[$poolId]['seo_phrase'] ?? [];
}
/**
* 只负责:选一条模板
*/
// public function getTemplate(string $field, string $strPage): string
// {
// // 1⃣ 取当前字段 + 页面类型的文案池
// $phrases = loadSeoFile(
// $this->cfg['pool_id'],
// $strPage,
// $field
// );
// if (!$phrases) {
// return '';
// }
// // 2⃣ 冻结的 slot
// $slot = $this->cfg['phrase_pick'][$strPage][$field] ?? 0;
// // slot 是二维
// if (isset($phrases[$slot]) && is_array($phrases[$slot])) {
// $list = $phrases[$slot];
// } else {
// $list = $phrases;
// }
// // 3⃣ 稳定消费 index不受扩容影响
// $len = $this->cfg['slot_len'][$strPage][$field] ?? count($list);
// $len = max(1, min($len, count($list)));
// // $idx = abs(crc32(
// // Request::pathinfo() ?: Request::host()
// // )) % $len;
// $idx = $this->cfg['phrase_idx'][$strPage][$field] ?? 0;
// return $list[$idx] ?? '';
// return $list[$idx] ?? '';
// }
// public function getTemplate(string $field, string $strPage): string
// {
// if (empty($this->cfg['pool_id'])) {
// return '';
// }
// // 1⃣ 加载运行期文案池(不冻结)
// $phrases = loadSeoFile(
// $this->cfg['pool_id'],
// $strPage,
// $field
// );
// if (!$phrases || !is_array($phrases)) {
// return '';
// }
// // 2⃣ 冻结 slot
// $slot = $this->cfg['phrase_pick'][$strPage][$field] ?? 0;
// if (isset($phrases[$slot]) && is_array($phrases[$slot])) {
// $list = $phrases[$slot];
// } else {
// // 兜底:当成单 slot
// $list = $phrases;
// }
// if (!$list) {
// return '';
// }
// // 3⃣ 冻结 idx核心
// $idx = $this->cfg['phrase_idx'][$strPage][$field] ?? 0;
// return $list[$idx] ?? '';
// }
public function getTemplate(string $field, string $strPage): string
{
if (empty($this->cfg['pool_id'])) {
return '';
}
// 1⃣ 加载运行期文案池
$phrases = loadSeoFile(
$this->cfg['pool_id'],
$strPage,
$field
);
if (!$phrases || !is_array($phrases)) {
return '';
}
// 2⃣ 冻结 slot
$slot = $this->cfg['phrase_pick'][$strPage][$field] ?? 0;
if (isset($phrases[$slot]) && is_array($phrases[$slot])) {
$list = $phrases[$slot];
} else {
$list = $phrases;
}
if (!$list) {
return '';
}
// ===============================
// 3⃣ idx 选择(终态)
// ===============================
$idx = 0;
switch ($strPage) {
case 'detail':
case 'play':
// 视频实体页seed + videoId
$videoId = (int) Request::param('intVId', 0);
if ($videoId > 0) {
$len = count($list);
$idx = abs(crc32(
$this->cfg['pool_id']
. '|detail|'
. $field
. '|' . $videoId
)) % $len;
}
break;
case 'detail_forge':
// 伪造详情seed + videoId + forgeId
$videoId = (int) Request::param('intVId', 0);
$forgeId = (int) Request::param('intVForgeId', 0);
if ($videoId > 0 && $forgeId > 0) {
$len = count($list);
$idx = abs(crc32(
$this->cfg['pool_id']
. '|detail_forge|'
. $field
. '|' . $videoId
. '|' . $forgeId
)) % $len;
}
break;
default:
// 非实体页:域名级冻结 idx
$idx = $this->cfg['phrase_idx'][$strPage][$field] ?? 0;
break;
}
return $list[$idx] ?? '';
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,12 +4,10 @@
<head>
{block name="get-data"}{/block}
<meta charset="UTF-8">
<title>{block name="title"}{/block}</title>
<meta name="keywords" content='{block name="keywords"}{/block}'>
<meta name="description" content='{block name="description"}{/block}'>
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
{// 动态主题颜色 }
<style>
:root{
@@ -23,8 +21,7 @@
--border-color: {$TpStyle.color_border};
--grad-start: {$TpStyle.color_grad_start};
--grad-end: {$TpStyle.color_grad_end};
--page-max-width: {$TpStyle.page_max_width_pc}px;
--page-max-width: {$TpStyle.template_cfg.global.page_max_width_pc}px;
}
body{
background: var(--bg-color);
@@ -33,7 +30,7 @@
</style>
{// 每个域名专属 CSS合并 + 前缀替换后) }
<link rel="stylesheet" href="{$TpCss}">
<link rel="stylesheet" href="{$strTpCss}">
{block name="head"}{/block}
{block name="head-css"}{/block}
@@ -54,19 +51,23 @@
})();
</script>
</head>
{block name="strPageCode"}
<?php $strPageCode = 'home'; ?>
{/block}
<body data-class="{$TpStyle.dom_prefix}">
{// header}
{include file="$TpTpl.head" /}
{include file="$TpStyle.templates.head" /}
<main class="{$TpStyle.dom_prefix}-main">
{block name="main"}{/block}
</main>
{// footer }
{include file="$TpTpl.foot" /}
{include file="$TpStyle.templates.foot" /}
{// DOM 干扰节点,站群差异用 }
<div style="display:none">tpl-{$TpStyle.static_hash}</div>
@@ -79,7 +80,7 @@
{block name="footer-js"}{/block}
<script type="text/javascript"
src="{site:cfg code='PUBLIC_STATIC_DOMAIN' encode='false'/}/static/js/lazy.js?v={site:cfg code='STATIC_FILE_VERSION' encode='false'/}"></script>
src="{site:cfg code='PUBLIC_STATIC_DOMAIN' encode='false'/}{$strTpJs}?v={site:cfg code='STATIC_FILE_VERSION' encode='false'/}"></script>
</body>
</html>

View File

@@ -1,98 +0,0 @@
{extend name="base" /}
{block name="get-data"}
{video:listexp count="6" sort_type="tuijian" d_key="key" d_val="Video" cache_life="3600" export_name="arrVideoTuijian"
/}
{video:listexp count="6" sort_type="piaofang" d_key="key" d_val="Video" cache_life="3600"
export_name="arrVideoPiaofang" /}
{video:listexp
count="12"
sort_type="tuijian"
export_name="arrVideoRecommend"
/}
{video:listexp
count="12"
sort_type="zuixin"
export_name="arrVideoNewest"
/}
{video:listexp
count="12"
sort_type="zuire"
export_name="arrVideoTrending"
/}
{video:listexp
count="12"
sort_type="ranking"
export_name="arrVideoRanking"
/}
{site:grm page_code="h5_index" diff="0" num="80" g_key="arrGrm" /}
{/block}
{block name="title"}
{site:replace code="VIDEO@INDEX@INDEX@TITLE"}
{/block}
{block name="keywords"}
{site:replace code="VIDEO@INDEX@INDEX@KEYWORDS"}
{/block}
{block name="description"}
{site:replace code="VIDEO@INDEX@INDEX@DESCRIPTION"}
{/block}
{block name="main"}
{// ================= 最近更新 ================= }
{include file="module/list/home_newest" /}
{// ================= 热门推荐 ================= }
{include file="module/list/home_hot" /}
{// ================= 排行榜 ================= }
{include file="module/list/home_rank" /}
<div class="{$TpStyle.dom_prefix}-page-wrap">
{foreach $TpStyle.home_modules as $key=>$mod }
{if $mod == 'banner'}
{include file="$TpTpl.banner" /}
{/if}
{if $mod == 'recommend'}
{include file="$TpTpl.recommend" /}
{/if}
{if $mod == 'trending'}
{include file="$TpTpl.trending" /}
{/if}
{if $mod == 'newest'}
{include file="$TpTpl.newest" /}
{/if}
{if $mod == 'ranking'}
{include file="$TpTpl.ranking" /}
{/if}
{if $mod == 'category'}
{include file="$TpTpl.category" /}
{/if}
{/foreach}
{include file="$TpTpl.list" /}
</div>
{/block}

View File

@@ -4,25 +4,64 @@
{/block}
{block name="title"}{site:replace code="VIDEO@ @INDEX@TITLE"}{/block}
{block name="keywords"}{site:replace code="VIDEO@INDEX@INDEX@KEYWORDS"}{/block}
{block name="description"}{site:replace code="VIDEO@INDEX@INDEX@DESCRIPTION"}{/block}
{block name="title"}
{site:replace code="VIDEO@INDEX@INDEX@TITLE"}
{/block}
{block name="head"}
<meta name="robots" content="index,follow">
<link rel="canonical" href='https://{$DomainModel->d_domain}/'>
{block name="keywords"}
{site:replace code="VIDEO@INDEX@INDEX@KEYWORDS"}
{/block}
{block name="description"}
{site:replace code="VIDEO@INDEX@INDEX@DESCRIPTION"}
{/block}
{// 社交媒体标签 }
<meta property="og:title" content='{site:replace code="VIDEO@INDEX@INDEX@TITLE"}' />
<meta property="og:description" content='{site:replace code="VIDEO@INDEX@INDEX@DESCRIPTION"}' />
<meta property="og:url" content="https://{$DomainModel->d_domain}" />
<meta property="og:type" content="website" />
{// 结构化数据 }
<script type="application/ld+json">
[
{
"@type": "WebSite",
"name": "{$DomainModel->d_name}",
"url": "https://{$DomainModel->d_domain}",
"alternateName": "{$DomainModel->d_domain}",
"description": "{site:replace code="VIDEO@INDEX@INDEX@DESCRIPTION"}",
"potentialAction": {
"@type": "SearchAction",
"target": 'https://{$DomainModel->d_domain}{site:vsurl key="search_term_string" p="1"/}',
"query-input": "required name=search_term_string"
}
},
]
</script>
{/block}
{block name="main"}
<main class="page-home" style="max-width:{$TpStyle.page_max_width_pc}px;margin:0 auto;">
{foreach $TpStyle.template_cfg.pages.home.modules as $module}
<main class="page-home" style="max-width:{$TpStyle.template_cfg.global.page_max_width_pc}px;margin:0 auto;">
{// lunli }
{assign name="Slot" value="$TpStyle.template_cfg.pages.home.lunliSlots[0]"}
{assign name="title" value="$Slot.title_text"}
{include file="module/list/title/_title_router" /}
{assign name="listCfg" value="$TpStyle.template_cfg.list_layout.lunli"}
{assign name="limit" value="$listCfg.layout['max_items']"}
{video:listexp count="$limit" v_parent_category_en="dian-ying"
v_category_en="lun-li-pian" d_key="key" d_val="Video" cache_life="3600"
export_name="__LIST__" /}
{include file="module/list/shell/_shell_router" /}
{// top}
{foreach $TpStyle.template_cfg.pages.home.slots as $Slot}
{assign name="module" value="$Slot['layout_key']"}
{assign name="limit" value="$TpStyle.template_cfg.list_layout[$module]['layout']['max_items']"}
{assign name="limit" value="$TpStyle.list_layout[$module]['layout']['max_items']"}
{if $module == 'rank'}
{video:ranklistexp count="$limit" sort_type="weekly" d_key="key" d_val="Video" cache_life="3600"
export_name="__LIST__" /}
@@ -30,13 +69,38 @@
{video:listexp count="$limit" sort_type="$module" d_key="key" d_val="Video" cache_life="3600"
export_name="__LIST__" /}
{/if}
{include file="module/list/home_block" /}
{/foreach}
{// 分类}
{foreach $TpStyle.template_cfg.pages.home.categories as $Category}
{assign name="Slot" value="$Category"}
{site:vciurl parent_category="$Category.key" export_name="strMoreUrl" /}
{assign name="title" value="$Slot.title_text"}
{include file="module/list/title/_title_router" /}
{assign name="Module" value="$Category.layout_key"}
{assign name="listCfg" value="$TpStyle.template_cfg.list_layout[$module]"}
{assign name="limit" value="$listCfg.layout['max_items']"}
{video:listexp count="$limit"
v_parent_category_en="$Category.key"
sort_type="news"
d_key="d_key" d_val="Video" cache_life="3600"
export_name="__LIST__" /}
{// ===== Shell + Item ===== }
{include file="module/list/shell/_shell_router" /}
{/foreach}
</main>
{/block}

View File

@@ -6,7 +6,12 @@
{if $intVariant == 0}
<span class="{$TpStyle.dom_prefix}-bc-text">
{volist name="arrBreadcrumb" id="node" key="i"}
{$node.title}{if $i < count($arrBreadcrumb)} &gt; {/if}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<em>{$node.title}</em>
{/if}
{if $i < count($arrBreadcrumb)} &gt; {/if}
{/volist}
</span>
@@ -27,7 +32,11 @@
{elseif $intVariant == 2}
<small class="{$TpStyle.dom_prefix}-bc-small">
{volist name="arrBreadcrumb" id="node"}
{$node.title}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{/volist}
</small>
@@ -36,7 +45,12 @@
<p class="{$TpStyle.dom_prefix}-bc-sentence">
当前所在位置:
{volist name="arrBreadcrumb" id="node" key="i"}
{$node.title}{if $i < count($arrBreadcrumb)} {/if}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{if $i < count($arrBreadcrumb)} {/if}
{/volist}
</p>
@@ -44,7 +58,11 @@
{elseif $intVariant == 4}
<time class="{$TpStyle.dom_prefix}-bc-time">
{volist name="arrBreadcrumb" id="node"}
{$node.title}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{/volist}
</time>
@@ -52,7 +70,12 @@
{elseif $intVariant == 5}
<strong class="{$TpStyle.dom_prefix}-bc-strong">
{volist name="arrBreadcrumb" id="node" key="i"}
{$node.title}{if $i < count($arrBreadcrumb)} / {/if}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{if $i < count($arrBreadcrumb)} / {/if}
{/volist}
</strong>
@@ -60,7 +83,11 @@
{elseif $intVariant == 6}
<em class="{$TpStyle.dom_prefix}-bc-em">
{volist name="arrBreadcrumb" id="node"}
{$node.title}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{/volist}
</em>
@@ -68,7 +95,11 @@
{elseif $intVariant == 7}
<address class="{$TpStyle.dom_prefix}-bc-address">
{volist name="arrBreadcrumb" id="node"}
{$node.title}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{/volist}
</address>
@@ -76,7 +107,11 @@
{elseif $intVariant == 8}
<blockquote class="{$TpStyle.dom_prefix}-bc-quote">
{volist name="arrBreadcrumb" id="node"}
{$node.title}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{/volist}
</blockquote>
@@ -85,7 +120,12 @@
<p class="{$TpStyle.dom_prefix}-bc-paragraph">
本页面内容来源于
{volist name="arrBreadcrumb" id="node" key="i"}
{$node.title}{if $i < count($arrBreadcrumb)} · {/if}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{if $i < count($arrBreadcrumb)} · {/if}
{/volist}
</p>
@@ -106,7 +146,11 @@
<p class="{$TpStyle.dom_prefix}-bc-prefix">
您当前浏览的是:
{volist name="arrBreadcrumb" id="node"}
{$node.title}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{/volist}
</p>
@@ -114,7 +158,11 @@
{elseif $intVariant == 12}
<h6 class="{$TpStyle.dom_prefix}-bc-h6">
{volist name="arrBreadcrumb" id="node"}
{$node.title}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{/volist}
</h6>
@@ -122,7 +170,11 @@
{elseif $intVariant == 13}
<code class="{$TpStyle.dom_prefix}-bc-code">
{volist name="arrBreadcrumb" id="node"}
{$node.title}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{/volist}
</code>
@@ -130,7 +182,11 @@
{elseif $intVariant == 14}
<kbd class="{$TpStyle.dom_prefix}-bc-kbd">
{volist name="arrBreadcrumb" id="node"}
{$node.title}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{/volist}
</kbd>
@@ -139,7 +195,12 @@
<p class="{$TpStyle.dom_prefix}-bc-long">
本页面为
{volist name="arrBreadcrumb" id="node" key="i"}
{$node.title}{if $i < count($arrBreadcrumb)} {/if}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{if $i < count($arrBreadcrumb)} {/if}
{/volist}
相关内容展示
</p>
@@ -148,7 +209,13 @@
{elseif $intVariant == 16}
<p class="{$TpStyle.dom_prefix}-bc-mark">
{volist name="arrBreadcrumb" id="node"}
<mark>{$node.title}</mark>
<mark>
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
</mark>
{/volist}
</p>
@@ -156,7 +223,12 @@
{elseif $intVariant == 17}
<span class="{$TpStyle.dom_prefix}-bc-inline">
{volist name="arrBreadcrumb" id="node" key="i"}
{$node.title}{if $i < count($arrBreadcrumb)} , {/if}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{if $i < count($arrBreadcrumb)} , {/if}
{/volist}
</span>
@@ -164,7 +236,11 @@
{elseif $intVariant == 18}
<footer class="{$TpStyle.dom_prefix}-bc-footer">
{volist name="arrBreadcrumb" id="node"}
{$node.title}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{/volist}
</footer>
@@ -172,7 +248,11 @@
{else}
<div class="{$TpStyle.dom_prefix}-bc-default">
{volist name="arrBreadcrumb" id="node"}
{$node.title}
{if !empty($node.url)}
<a href="{$node.url}">{$node.title}</a>
{else /}
<span>{$node.title}</span>
{/if}
{/volist}
</div>
{/if}

View File

@@ -0,0 +1,21 @@
{if !empty($arrAddon.summary) || !empty($arrAddon.tags) || !empty($arrAddon.tip)}
<section class="{$TpStyle.dom_prefix}-synx">
{if !empty($arrAddon.summary)}
<p class="{$TpStyle.dom_prefix}-synx-summary">{$arrAddon.summary}</p>
{/if}
{if !empty($arrAddon.tags)}
<div class="{$TpStyle.dom_prefix}-synx-tags">
{volist name="$arrAddon.tags" id="t"}
<span class="{$TpStyle.dom_prefix}-synx-tag">{$t}</span>
{/volist}
</div>
{/if}
{if !empty($arrAddon.tip)}
<p class="{$TpStyle.dom_prefix}-synx-tip">{$arrAddon.tip}</p>
{/if}
</section>
{/if}

View File

@@ -1,17 +1,18 @@
{// ===================== Cover Variants ===================== }
{video:imgalt video="$arrVideo" slot="detail_cover" item_type="poster" export_name="strAlt" /}
{if $variant == 0}
<div class="{$TpStyle.dom_prefix}-dm-cover v0">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}"
alt="{$arrVideo.v_name}">
alt="{$strAlt}">
</div>
{elseif $variant == 1}
<figure class="{$TpStyle.dom_prefix}-dm-cover v1">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}"
alt="{$arrVideo.v_name}">
alt="{$strAlt}">
<figcaption class="{$TpStyle.dom_prefix}-dm-cover-cap">
{$arrVideo.v_remarks}
</figcaption>
@@ -22,19 +23,19 @@
href='{site:vpurl v_id="$arrVideo.v_id" v_py="$arrVideo.v_name_en" play_type="default" play_index="1" /}'>
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}"
alt="{$arrVideo.v_name}">
alt="{$strAlt}">
</a>
{elseif $variant == 3}
<div class="{$TpStyle.dom_prefix}-dm-cover v3">
<div class="{$TpStyle.dom_prefix}-dm-cover-bg"
data-bg="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}"></div>
<img class="{$TpStyle.dom_prefix}-dm-cover-bg" alt="{$strAlt}"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
</div>
{elseif $variant == 4}
<div class="{$TpStyle.dom_prefix}-dm-cover v4">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}" alt="{$strAlt}">
<span class="{$TpStyle.dom_prefix}-dm-cover-badge">
{$arrVideo.v_year}
</span>
@@ -43,7 +44,7 @@
{elseif $variant == 5}
<div class="{$TpStyle.dom_prefix}-dm-cover v5">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}" alt="{$strAlt}">
<span class="{$TpStyle.dom_prefix}-dm-cover-score">
{$arrVideo.v_score}
</span>
@@ -51,29 +52,29 @@
{elseif $variant == 6}
<section class="{$TpStyle.dom_prefix}-dm-cover v6">
<div class="{$TpStyle.dom_prefix}-dm-cover-bg"
data-bg="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}"></div>
<img class="{$TpStyle.dom_prefix}-dm-cover-bg" alt="{$strAlt}"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
<span class="{$TpStyle.dom_prefix}-dm-cover-play"></span>
</section>
{elseif $variant == 7}
<article class="{$TpStyle.dom_prefix}-dm-cover v7">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}" alt="{$strAlt}">
</article>
{elseif $variant == 8}
<div class="{$TpStyle.dom_prefix}-dm-cover v8">
<picture class="{$TpStyle.dom_prefix}-dm-cover-pic">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}" alt="{$strAlt}">
</picture>
</div>
{elseif $variant == 9}
<div class="{$TpStyle.dom_prefix}-dm-cover v9">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}" alt="{$strAlt}">
<span class="{$TpStyle.dom_prefix}-dm-cover-remark">
{$arrVideo.v_remarks}
</span>
@@ -81,36 +82,36 @@
{elseif $variant == 10}
<div class="{$TpStyle.dom_prefix}-dm-cover v10">
<div class="{$TpStyle.dom_prefix}-dm-cover-bg"
data-bg="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}"></div>
<img class="{$TpStyle.dom_prefix}-dm-cover-bg" alt="{$strAlt}"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
<span class="{$TpStyle.dom_prefix}-dm-cover-tag">HD</span>
</div>
{elseif $variant == 11}
<a class="{$TpStyle.dom_prefix}-dm-cover v11"
href='{site:vpurl v_id="$arrVideo.v_id" v_py="$arrVideo.v_name_en" play_type="default" play_index="1" /}'>
<div class="{$TpStyle.dom_prefix}-dm-cover-bg"
data-bg="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}"></div>
<img class="{$TpStyle.dom_prefix}-dm-cover-bg" alt="{$strAlt}"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
</a>
{elseif $variant == 12}
<div class="{$TpStyle.dom_prefix}-dm-cover v12">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}" alt="{$strAlt}">
<span class="{$TpStyle.dom_prefix}-dm-cover-top">更新中</span>
</div>
{elseif $variant == 13}
<div class="{$TpStyle.dom_prefix}-dm-cover v13">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}" alt="{$strAlt}">
<span class="{$TpStyle.dom_prefix}-dm-cover-corner"></span>
</div>
{elseif $variant == 14}
<div class="{$TpStyle.dom_prefix}-dm-cover v14">
<div class="{$TpStyle.dom_prefix}-dm-cover-bg"
data-bg="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}"></div>
<img class="{$TpStyle.dom_prefix}-dm-cover-bg" alt="{$strAlt}"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
<span class="{$TpStyle.dom_prefix}-dm-cover-year">
{$arrVideo.v_year}
</span>
@@ -119,7 +120,7 @@
{elseif $variant == 15}
<div class="{$TpStyle.dom_prefix}-dm-cover v15">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}" alt="{$strAlt}">
<span class="{$TpStyle.dom_prefix}-dm-cover-free">
免费
</span>
@@ -128,24 +129,24 @@
{elseif $variant == 16}
<div class="{$TpStyle.dom_prefix}-dm-cover v16">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}" alt="{$strAlt}">
<span class="{$TpStyle.dom_prefix}-dm-cover-mask"></span>
</div>
{elseif $variant == 17}
<aside class="{$TpStyle.dom_prefix}-dm-cover v17">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
<img class="{$TpStyle.dom_prefix}-dm-cover-img" alt="{$strAlt}"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
</aside>
{elseif $variant == 18}
<div class="{$TpStyle.dom_prefix}-dm-cover v18"
data-cover="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
</div>
<img class="{$TpStyle.dom_prefix}-dm-cover v18" alt="{$strAlt}"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
{elseif $variant == 19}
<section class="{$TpStyle.dom_prefix}-dm-cover v19">
<img class="{$TpStyle.dom_prefix}-dm-cover-img"
<img class="{$TpStyle.dom_prefix}-dm-cover-img" alt="{$strAlt}"
src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$arrVideo.v_pic}">
</section>

View File

@@ -132,3 +132,7 @@
</article>
{/if}
{video:seoaddon video="$arrVideo" export_name="arrAddon" /}
{include file="module/detail/_seo_addon" /}

View File

@@ -1,6 +1,6 @@
{// ===================== Meta Variants (Array-aware, no i_last) ===================== }
{// 预计算长度(避免 i_last }
{// 预计算长度(避免 i_last }
{assign name="len_area" value="is_array($arrVideo.v_area)?count($arrVideo.v_area):0"}
{assign name="len_actor" value="is_array($arrVideo.v_actor)?count($arrVideo.v_actor):0"}
{assign name="len_director" value="is_array($arrVideo.v_director)?count($arrVideo.v_director):0"}

View File

@@ -3,13 +3,12 @@
$mod = $module;
// 2. 读取该模块的 layout 配置(冻结)
$cfg = $TpStyle['list_layout'][$mod] ?? null;
$listCfg = $TpStyle['list_layout'][$mod] ?? null;
$cfg = $TpStyle['template_cfg']['list_layout'][$mod] ?? null;
$listCfg = $TpStyle['template_cfg']['list_layout'][$mod] ?? null;
if (!$cfg) return;
// 3. 绑定数据变量(只在这里做一次映射)
$title = $cfg['title_text'] ?? null;
$title = $Slot['title_text'] ?? null;
?>
<section class="mod-{$mod}">

View File

@@ -1,10 +1,11 @@
{php}
// 统一从 cfg 下发(冻结)
$variant = isset($cfg['item_variant']) ? intval($cfg['item_variant']) : 0;
// 统一从 listCfg 下发(冻结)
$variant = isset($listCfg['item_variant']) ? intval($listCfg['item_variant']) : 0;
{/php}
{video:imgalt video="$vo" slot="list_poster" item_type="$listCfg.item_type" export_name="strAlt" /}
{switch $cfg.item}
{switch $listCfg.item}
{case 01}
{include file="module/list/item/item_01" /}

View File

@@ -5,7 +5,7 @@
<article class="{$TpStyle.dom_prefix}-item poster v0">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img class="lazyload-img" src="{$vo.v_pic}" alt="{$vo.v_name}">
<img class="lazyload-img" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -23,7 +23,7 @@
<li class="{$TpStyle.dom_prefix}-item poster v1">
<figure>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}" alt="{$vo.v_name}" class="lazyload-img {$TpStyle.dom_prefix}-item-cover">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}" class="lazyload-img {$TpStyle.dom_prefix}-item-cover">
<figcaption>
<strong >{$vo.v_name}</strong>
<span>{$vo.v_year}</span>
@@ -39,9 +39,9 @@
<h3 ><a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" >{$vo.v_name}</a></h3>
<p>{$vo.v_year}</p>
</div>
<div class="{$TpStyle.dom_prefix}-item-cover">
<img class="lazyload-img" src="{$vo.v_pic}">
</div>
<a class="{$TpStyle.dom_prefix}-item-cover" href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img class="lazyload-img" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
</a>
</div>
{elseif $variant == 3}
@@ -50,7 +50,7 @@
<div class="{$TpStyle.dom_prefix}-inner">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-thumb">
<img class="lazyload-img {$TpStyle.dom_prefix}-item-cover" src="{$vo.v_pic}">
<img class="lazyload-img {$TpStyle.dom_prefix}-item-cover" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
</div>
<h3>{$vo.v_name}</h3>
</a>
@@ -63,23 +63,24 @@
<h3 class="{$TpStyle.dom_prefix}-title {$TpStyle.dom_prefix}-item-title">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">{$vo.v_name}</a>
</h3>
<div class="{$TpStyle.dom_prefix}-media {$TpStyle.dom_prefix}-item-cover">
<img class="lazyload-img" src="{$vo.v_pic}">
</div>
<a class="{$TpStyle.dom_prefix}-media {$TpStyle.dom_prefix}-item-cover" href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img class="lazyload-img" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}">
</a>
</section>
{elseif $variant == 5}
{// Variant 5span + div 混合 }
<div class="{$TpStyle.dom_prefix}-entry poster v5">
<span class="{$TpStyle.dom_prefix}-media ">
<img src="/static/img/load.png"
data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}"
alt="{$vo.v_name ?? ''} - {$vo.v_parent_category ?? ''}{$vo.v_category ?? ''}免费高清电影在线观看" class="{$TpStyle.dom_prefix}-item-cover lazyload-img">
</span>
<div class="{$TpStyle.dom_prefix} meta">
<strong>{$vo.v_name}</strong>
<em>{$vo.v_year}</em>
</div>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<span class="{$TpStyle.dom_prefix}-media ">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}"
alt="{$vo.v_name ?? ''} - {$vo.v_parent_category ?? ''}{$vo.v_category ?? ''}免费高清电影在线观看" class="{$TpStyle.dom_prefix}-item-cover lazyload-img">
</span>
<div class="{$TpStyle.dom_prefix} meta">
<strong>{$vo.v_name}</strong>
<em>{$vo.v_year}</em>
</div>
</a>
</div>
{elseif $variant == 6}
@@ -89,7 +90,7 @@
<h3 >{$vo.v_name}</h3>
</header>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}" class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img">
</a>
</article>
@@ -97,12 +98,12 @@
{// Variant 7反向嵌套 }
<div class="{$TpStyle.dom_prefix}-item poster v7">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-info">
<h3 class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</h3>
<div class="{$TpStyle.dom_prefix}-info {$TpStyle.dom_prefix}-item-title">
<h3 >{$vo.v_name}</h3>
<p>{$vo.v_year}</p>
</div>
<figure>
<img src="{$vo.v_pic}">
<figure class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="lazyload-img">
</figure>
</a>
</div>
@@ -111,31 +112,31 @@
{// Variant 8极简 }
<div class="{$TpStyle.dom_prefix}-item poster v8">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" >
<img src="{$vo.v_pic}">
<span class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</span>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="lazyload-img {$TpStyle.dom_prefix}-item-cover">
<span>{$vo.v_name}</span>
</a>
</div>
{elseif $variant == 9}
{// Variant 9多层包裹 }
<div class="{$TpStyle.dom_prefix}-item poster v9">
<div class="{$TpStyle.dom_prefix}-wrap">
<div class="{$TpStyle.dom_prefix}-cover">
<img src="{$vo.v_pic}">
<a class="{$TpStyle.dom_prefix}-wrap" href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-cover {$TpStyle.dom_prefix}-item-cover">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="lazyload-img">
</div>
<div class="{$TpStyle.dom_prefix}-text">
<h3 class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</h3>
<h3>{$vo.v_name}</h3>
<small>{$vo.v_year}</small>
</div>
</div>
</a>
</div>
{elseif $variant == 10}
{// Variant 10aside 结构 }
<aside class="{$TpStyle.dom_prefix}-item poster v10">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}">
<h3 class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</h3>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="lazyload-img {$TpStyle.dom_prefix}-item-cover">
<h3>{$vo.v_name}</h3>
</a>
</aside>
@@ -143,19 +144,19 @@
{// Variant 11dl / dt / dd }
<dl class="{$TpStyle.dom_prefix}-item poster v11">
<dt>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" >
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="lazyload-img {$TpStyle.dom_prefix}-item-cover">
</a>
</dt>
<dd class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</dd>
<dd >{$vo.v_name}</dd>
</dl>
{elseif $variant == 12}
{// Variant 12section + header }
<section class="{$TpStyle.dom_prefix}-item poster v12">
<header>{$vo.v_name}</header>
<header class=" {$TpStyle.dom_prefix}-item-title">{$vo.v_name}</header>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img" alt="{$strAlt}">
</a>
</section>
@@ -163,7 +164,7 @@
{// Variant 13figure 无 figcaption }
<figure class="{$TpStyle.dom_prefix}-item poster v13">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img">
</a>
</figure>
@@ -172,7 +173,7 @@
<div class="{$TpStyle.dom_prefix}-item poster v14">
<strong class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</strong>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img">
</a>
</div>
@@ -181,7 +182,7 @@
<div class="{$TpStyle.dom_prefix}-item poster v15">
<p>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" >
<img src="{$vo.v_pic}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img">
{$vo.v_name}
</a>
</p>
@@ -191,24 +192,24 @@
{// Variant 16div + data }
<div class="{$TpStyle.dom_prefix}-item poster v16" data-id="{$vo.v_id}">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}">
<span class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</span>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img">
<span >{$vo.v_name}</span>
</a>
</div>
{elseif $variant == 17}
{// Variant 17h4 }
<div class="{$TpStyle.dom_prefix}-item poster v17">
<h4 >{$vo.v_name}</h4>
<h4 class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</h4>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img">
</a>
</div>
{elseif $variant == 18}
{// Variant 18纯链接卡 }
<a class="{$TpStyle.dom_prefix}-item poster v18" href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img">
<span>{$vo.v_name}</span>
</a>
@@ -216,8 +217,8 @@
{// Variant 19极端自由结构 }
<div class="{$TpStyle.dom_prefix}-box poster v19">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
{$vo.v_name}
<img src="{$vo.v_pic}">
<h2 class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</h2>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img">
</a>
</div>
{/if}

View File

@@ -2,10 +2,10 @@
{if $variant == 0}
{// V0 标准(你给的母型) }
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}" class="lazyload-img">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -32,10 +32,10 @@
{elseif $variant == 1}
{// V1 figure/figcaption 语义化 }
<li class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<li class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<figure class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="lazyload-img" alt="{$strAlt}" >
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -59,7 +59,17 @@
{elseif $variant == 2}
{// V2 信息前置 + 封面后置(结构反转) }
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$TpStyle.lazy_img}" class="lazyload-img" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
</div>
</a>
<div class="{$TpStyle.dom_prefix}-item-info">
<h3 class="{$TpStyle.dom_prefix}-item-title">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">{$vo.v_name}</a>
@@ -78,26 +88,17 @@
<p class="{$TpStyle.dom_prefix}-item-extra">主演:{$vo.v_actor[0]}</p>
{/if}
</div>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
</div>
</a>
</article>
{elseif $variant == 3}
{// V3 多层包裹inner / media / text }
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<div class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-inner">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-media">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img class="lazyload-img" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -129,7 +130,7 @@
{elseif $variant == 4}
{// V4 header + section 分块 }
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<header class="{$TpStyle.dom_prefix}-item-info">
<h3 class="{$TpStyle.dom_prefix}-item-title">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">{$vo.v_name}</a>
@@ -142,7 +143,7 @@
<section class="{$TpStyle.dom_prefix}-item-cover">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}" class="lazyload-img">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -160,10 +161,10 @@
</article>
{elseif $variant == 5}
{// V5 a 包裹只包 cover标题单独 a双入口 }
<div class="{$TpStyle.dom_prefix}-item {$TpStyle.dom_prefix}-item02-{$variant} item02 {$item_type|default='media'} {$cfg.class|default=''} ">
<div class="{$TpStyle.dom_prefix}-item {$TpStyle.dom_prefix}-item02-{$variant} item02 {$item_type|default='media'} ">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="lazyload-img" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -192,10 +193,10 @@
{elseif $variant == 6}
{// V6 nav 风格(技术人员很难一眼归类) }
<nav class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<nav class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<span class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" class="lazyload-img" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -222,10 +223,10 @@
{elseif $variant == 7}
{// V7 aside + main 结构 }
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<div class="{$TpStyle.dom_prefix}-item item item02 {$item_type|default='media'} ">
<aside class="{$TpStyle.dom_prefix}-item-cover">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}" class="lazyload-img {$TpStyle.dom_prefix}-item-cover">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -251,14 +252,14 @@
{elseif $variant == 8}
{// V8 标题在外层 headerlink 只包内容区 }
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<header class="{$TpStyle.dom_prefix}-item-info">
<h3 class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</h3>
</header>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}" class="lazyload-img">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -281,10 +282,10 @@
{elseif $variant == 9}
{// V9 切分为两个链接块cover/info 各自 a }
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img class="lazyload-img" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -310,10 +311,10 @@
{elseif $variant == 10}
{// V10 dl/dt/dd 语义结构(很“独立站”) }
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}" class="lazyload-img">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -337,7 +338,7 @@
{elseif $variant == 11}
{// V11 section + article 嵌套(深度变化) }
<section class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<section class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<article>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-info">
@@ -349,7 +350,7 @@
</div>
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="lazyload-img" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -369,11 +370,11 @@
{elseif $variant == 12}
{// V12 picture 包裹 + strong/em }
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-cover">
<picture>
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" class="lazyload-img" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
</picture>
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
@@ -398,10 +399,10 @@
{elseif $variant == 13}
{// V13 ul/li 信息块(结构伪装成列表条目) }
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img class="lazyload-img" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -424,7 +425,7 @@
{elseif $variant == 14}
{// V14 小标题 + 内容块分离(多层) }
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<div class="{$TpStyle.dom_prefix}-item-info">
<h3 class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</h3>
<p class="{$TpStyle.dom_prefix}-item-meta">
@@ -436,7 +437,7 @@
<div class="mid">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img class="lazyload-img" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -456,7 +457,7 @@
{elseif $variant == 15}
{// V15 强语义header/aside/footer 三段 }
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<header class="{$TpStyle.dom_prefix}-item-info">
<h3 class="{$TpStyle.dom_prefix}-item-title">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">{$vo.v_name}</a>
@@ -465,7 +466,7 @@
<aside class="{$TpStyle.dom_prefix}-item-cover">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}" class="lazyload-img">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -488,10 +489,10 @@
{elseif $variant == 16}
{// V16 同 class 挂在不同标签(指纹扰动强) }
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<figure class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="lazyload-img" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -515,11 +516,11 @@
{elseif $variant == 17}
{// V17 双层 link外层 div 伪装) }
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<div class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<div class="{$TpStyle.dom_prefix}-item-link">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" class="lazyload-img" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -546,7 +547,7 @@
{elseif $variant == 18}
{// V18 compact 文本强:标题/信息同级 }
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<article class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-info">
<h3 class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</h3>
@@ -566,7 +567,7 @@
</div>
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img class="lazyload-img" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}
@@ -576,11 +577,11 @@
{else}
{// V19 最终扰动ol/li 语义(但仍然是单 item }
<ol class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} {$cfg.class|default=''}">
<ol class="{$TpStyle.dom_prefix}-item item02 {$item_type|default='media'} ">
<li>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item-link">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$strAlt}" class="lazyload-img">
{notempty name="vo.v_score"}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_score}</span>
{/notempty}

View File

@@ -2,12 +2,12 @@
{if $variant == 0}
{// Variant 00原始基准 }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a class="{$TpStyle.dom_prefix}-item-link"
href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}"
title="{$vo.v_name}">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}" loading="lazy"/>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" class="lazyload-img" loading="lazy"/>
{if isset($vo.v_level)}
<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_level}</span>
{/if}
@@ -24,10 +24,10 @@
{elseif $variant == 1}
{// Variant 01article → section }
<section class="{$TpStyle.dom_prefix}-item poster score">
<section class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" class="lazyload-img"/>
{if isset($vo.v_level)}<em class="{$TpStyle.dom_prefix}-item-score">{$vo.v_level}</em>{/if}
</div>
<div class="{$TpStyle.dom_prefix}-item-info">
@@ -38,9 +38,9 @@
{elseif $variant == 2}
{// Variant 02a 外包 }
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item poster score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}" class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" class="lazyload-img" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}"/>
{if isset($vo.v_level)}<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_level}</span>{/if}
</div>
<div class="{$TpStyle.dom_prefix}-item-info">
@@ -50,10 +50,10 @@
{elseif $variant == 3}
{// Variant 03header / footer }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<header class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img class="lazyload-img" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}"/>
</header>
<footer class="{$TpStyle.dom_prefix}-item-info">
<strong class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</strong>
@@ -64,10 +64,10 @@
{elseif $variant == 4}
{// Variant 04figure / figcaption }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<figure class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" class="lazyload-img"/>
{if isset($vo.v_level)}<figcaption class="{$TpStyle.dom_prefix}-item-score">{$vo.v_level}</figcaption>{/if}
</figure>
<div class="{$TpStyle.dom_prefix}-item-info">
@@ -78,10 +78,10 @@
{elseif $variant == 5}
{// Variant 05meta 改为 p }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" class="lazyload-img" alt="{$vo.v_name}"/>
</div>
<div class="{$TpStyle.dom_prefix}-item-info">
<h3 class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</h3>
@@ -95,10 +95,10 @@
{elseif $variant == 6}
{// Variant 06strong title }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" class="lazyload-img" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}"/>
</div>
<div class="{$TpStyle.dom_prefix}-item-info">
<strong class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</strong>
@@ -108,11 +108,11 @@
{elseif $variant == 7}
{// Variant 07div 层级加深 }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<div class="{$TpStyle.dom_prefix}-wrap">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img class="lazyload-img" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}"/>
</div>
<div class="{$TpStyle.dom_prefix}-item-info">
<h3 class="{$TpStyle.dom_prefix}-item-title">{$vo.v_name}</h3>
@@ -123,19 +123,19 @@
{elseif $variant == 8}
{// Variant 08nav }
<nav class="{$TpStyle.dom_prefix}-item poster score">
<nav class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img"/>
<span>{$vo.v_name}</span>
</a>
</nav>
{elseif $variant == 9}
{// Variant 09small meta }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" class="lazyload-img" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}"/>
</div>
<small>{$vo.v_name}</small>
</a>
@@ -143,10 +143,10 @@
{elseif $variant == 10}
{// Variant 10title 在 cover 内 }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-item-cover">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img class="lazyload-img" src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" />
<span class="title-inside">{$vo.v_name}</span>
</div>
</a>
@@ -154,38 +154,38 @@
{elseif $variant == 11}
{// Variant 11去 info }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" class="lazyload-img {$TpStyle.dom_prefix}-item-cover"/>
<h3 >{$vo.v_name}</h3>
</a>
</article>
{elseif $variant == 12}
{// Variant 12score 提前 }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
{if isset($vo.v_level)}<span class="{$TpStyle.dom_prefix}-item-score">{$vo.v_level}</span>{/if}
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name} " class="{$TpStyle.dom_prefix}-item-cover lazyload-img"/>
<h3>{$vo.v_name}</h3>
</a>
</article>
{elseif $variant == 13}
{// Variant 13em title }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" class="lazyload-img {$TpStyle.dom_prefix}-item-cover"/>
<em>{$vo.v_name}</em>
</a>
</article>
{elseif $variant == 14}
{// Variant 14多 span }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<span class="{$TpStyle.dom_prefix}-img">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<span class="{$TpStyle.dom_prefix}-img ">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img"/>
</span>
<span class="txt">{$vo.v_name}</span>
</a>
@@ -194,36 +194,36 @@
{elseif $variant == 15}
{// Variant 15article 外包 }
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<article class="{$TpStyle.dom_prefix}-item poster score">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" class="lazyload-img {$TpStyle.dom_prefix}-item-cover"/>
<span>{$vo.v_name}</span>
</article>
</a>
{elseif $variant == 16}
{// Variant 16section + h4 }
<section class="{$TpStyle.dom_prefix}-item poster score">
<section class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" class="lazyload-img {$TpStyle.dom_prefix}-item-cover"/>
<h4>{$vo.v_name}</h4>
</a>
</section>
{elseif $variant == 17}
{// Variant 17p title }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" class="lazyload-img {$TpStyle.dom_prefix}-item-cover"/>
<p>{$vo.v_name}</p>
</a>
</article>
{elseif $variant == 18}
{// Variant 18label }
<article class="{$TpStyle.dom_prefix}-item poster score">
<article class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
<label>
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<img src="{$vo.v_pic}" alt="{$vo.v_name}"/>
<img src="{$TpStyle.lazy_img}" data-src="{site:cfg code='PUBLIC_COVER_DOMAIN' encode='false'/}{$vo.v_pic}" alt="{$vo.v_name}" class="{$TpStyle.dom_prefix}-item-cover lazyload-img"/>
{$vo.v_name}
</a>
</label>
@@ -232,7 +232,7 @@
{else}
{// Variant 19极简反转 }
<a href="{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en' /}">
<div class="{$TpStyle.dom_prefix}-item poster score">
<div class="{$TpStyle.dom_prefix}-item poster {$TpStyle.dom_prefix}-item4-v{$variant} score">
{$vo.v_name}
</div>
</a>

View File

@@ -1,4 +1,4 @@
{switch $cfg.shell}
{switch $listCfg.shell}
{case A}
{include file="module/list/shell/shell_A" /}

View File

@@ -1,4 +1,4 @@
<section class="{$TpStyle.dom_prefix}-shellA {$cfg.class}">
<section class="{$TpStyle.dom_prefix}-shellA {$listCfg.class}">
{notempty name="__LIST__"}
<div class="{$TpStyle.dom_prefix}-list"
data-max-lg="{$listCfg.layout.max.lg}"
@@ -6,11 +6,13 @@
data-max-sm="{$listCfg.layout.max.sm}"
data-max-h5="{$listCfg.layout.max.h5}"
style="--cols-lg: {$listCfg.grid.cols_pc_lg};--cols-md: {$listCfg.grid.cols_pc_md};--cols-sm: {$listCfg.grid.cols_pc_sm};--cols-h5: {$listCfg.grid.cols_h5};">
{volist name="__LIST__" id="vo" key="i"}
{// 这里由上层决定具体使用哪一个 item 模板 }
{assign name="item_type" value="$cfg.item_type|default='poster'"}
{include file="module/list/item/_item_router" /}
{volist name="__LIST__" id="vo" key="i"}
{// 这里由上层决定具体使用哪一个 item 模板 }
{assign name="item_type" value="$listCfg.item_type|default='poster'"}
{include file="module/list/item/_item_router" /}
{/volist}
</div>

View File

@@ -1,4 +1,4 @@
<section class="{$TpStyle.dom_prefix}-shellB {$cfg.class}" >
<section class="{$TpStyle.dom_prefix}-shellB {$listCfg.class}" >
{notempty name="__LIST__"}
<div class="{$TpStyle.dom_prefix}-list"
data-max-lg="{$listCfg.layout.max.lg}"
@@ -8,7 +8,7 @@
style="--cols-lg: {$listCfg.grid.cols_pc_lg};--cols-md: {$listCfg.grid.cols_pc_md};--cols-sm: {$listCfg.grid.cols_pc_sm};--cols-h5: {$listCfg.grid.cols_h5};">
{volist name="__LIST__" id="vo" key="i"}
{// Item 模板由上层决定,如 item_01 / item_04 }
{assign name="item_type" value="$cfg.item_type|default='poster'"}
{assign name="item_type" value="$listCfg.item_type|default='poster'"}
{include file="module/list/item/_item_router" /}
{/volist}
</div>

View File

@@ -1,4 +1,4 @@
<section class="{$TpStyle.dom_prefix}-shellC {$cfg.class}">
<section class="{$TpStyle.dom_prefix}-shellC {$listCfg.class}">
{notempty name="__LIST__"}
<ol class="{$TpStyle.dom_prefix}-list"
data-max-lg="{$listCfg.layout.max.lg}"
@@ -8,7 +8,7 @@
style="--cols-lg: {$listCfg.grid.cols_pc_lg};--cols-md: {$listCfg.grid.cols_pc_md};--cols-sm: {$listCfg.grid.cols_pc_sm};--cols-h5: {$listCfg.grid.cols_h5};">
{volist name="__LIST__" id="vo" key="i"}
{// 榜单类推荐 item_03 / item_05 }
{assign name="item_type" value="$cfg.item_type|default='poster'"}
{assign name="item_type" value="$listCfg.item_type|default='poster'"}
{include file="module/list/item/_item_router" /}
{/volist}

View File

@@ -1,4 +1,4 @@
<section class="{$TpStyle.dom_prefix}-shellD {$cfg.class}" >
<section class="{$TpStyle.dom_prefix}-shellD {$listCfg.class}" >
{notempty name="__GROUPS__"}
{volist name="__GROUPS__" id="group"}
<div class="{$TpStyle.dom_prefix}-shellD-group">
@@ -20,7 +20,7 @@
style="--cols-lg: {$listCfg.grid.cols_pc_lg};--cols-md: {$listCfg.grid.cols_pc_md};--cols-sm: {$listCfg.grid.cols_pc_sm};--cols-h5: {$listCfg.grid.cols_h5};">
{volist name="group.list" id="vo" key="i"}
{// Item 模板由上层决定 }
{assign name="item_type" value="$cfg.item_type|default='poster'"}
{assign name="item_type" value="$listCfg.item_type|default='poster'"}
{include file="module/list/item/_item_router" /}
{/volist}
</div>

View File

@@ -1,4 +1,4 @@
{switch $cfg.title}
{switch $Slot.title_tpl.family}
{case A}
{include file="module/list/title/title_A" /}
@@ -20,6 +20,10 @@
{include file="module/list/title/title_E" /}
{/case}
{case F}
{include file="module/list/title/title_F" /}
{/case}
{default}
{include file="module/list/title/title_A" /}
{/default}

View File

@@ -1,21 +1,365 @@
<header class="{$TpStyle.dom_prefix}-titleF">
<div class="{$TpStyle.dom_prefix}-titleF-left">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">
{$title.primary}
</h3>
{//
title_F_variants.html
Family: F
Variant index: 0..19 (与 item 的 0..19 一致)
依赖变量:
- $TpStyle.dom_prefix
- $title.primary / $title.secondary
- $strMoreUrl (可空)
- $Slot.more_text (可空,默认“更多”)
}
{if !empty($title.secondary)}
<span class="{$TpStyle.dom_prefix}-titleF-sub">
{$title.secondary}
{switch $Slot.title_tpl.variant}
{case value="0"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v00" data-tf="F00">
<div class="{$TpStyle.dom_prefix}-titleF-left">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-more">
<a href="{$strMoreUrl}" >{$Slot.more_text|default='更多'}</a>
</div>
{/if}
</header>
{/case}
{case value="1"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v01" data-tf="F01">
<div class="{$TpStyle.dom_prefix}-titleF-row">
<div class="{$TpStyle.dom_prefix}-titleF-stack">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<p class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</p>{/if}
</div>
{if !empty($strMoreUrl)}
<a class="{$TpStyle.dom_prefix}-titleF-more" href="{$strMoreUrl}"
>{$Slot.more_text|default='更多'}</a>
{/if}
</div>
</header>
{/case}
{case value="2"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v02" data-tf="F02">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">
<span class="{$TpStyle.dom_prefix}-titleF-dot" aria-hidden="true"></span>
<span class="{$TpStyle.dom_prefix}-titleF-txt">{$title.primary}</span>
</h3>
<div class="{$TpStyle.dom_prefix}-titleF-meta">
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
{if !empty($strMoreUrl)}
<span class="{$TpStyle.dom_prefix}-titleF-more">
<a href="{$strMoreUrl}" >{$Slot.more_text|default='更多'}</a>
</span>
{/if}
</div>
</header>
{/case}
{if !empty($moreUrl)}
{case value="3"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v03" data-tf="F03">
<div class="{$TpStyle.dom_prefix}-titleF-top">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-more">
<a href="{$strMoreUrl}" aria-label="{$Slot.more_text|default='更多'}">»</a>
</div>
{/if}
</div>
{if !empty($title.secondary)}<div class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</div>{/if}
</header>
{/case}
{case value="4"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v04" data-tf="F04">
<div class="{$TpStyle.dom_prefix}-titleF-grid">
<div class="{$TpStyle.dom_prefix}-titleF-cell">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<small class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</small>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-cell {$TpStyle.dom_prefix}-titleF-cell--more">
<a class="{$TpStyle.dom_prefix}-titleF-more" href="{$strMoreUrl}"
>{$Slot.more_text|default='更多'}</a>
</div>
{/if}
</div>
</header>
{/case}
{case value="5"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v05" data-tf="F05">
<div class="{$TpStyle.dom_prefix}-titleF-left">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">
<span class="{$TpStyle.dom_prefix}-titleF-mark" aria-hidden="true"></span>
{$title.primary}
</h3>
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
</div>
{if !empty($strMoreUrl)}
<nav class="{$TpStyle.dom_prefix}-titleF-nav" aria-label="More">
<a class="{$TpStyle.dom_prefix}-titleF-more" href="{$strMoreUrl}"
>{$Slot.more_text|default='更多'}</a>
</nav>
{/if}
</header>
{/case}
{case value="6"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v06" data-tf="F06">
<div class="{$TpStyle.dom_prefix}-titleF-line" aria-hidden="true"></div>
<div class="{$TpStyle.dom_prefix}-titleF-body">
<div class="{$TpStyle.dom_prefix}-titleF-text">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<p class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</p>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-cta">
<a href="{$strMoreUrl}" >{$Slot.more_text|default='更多'}</a>
</div>
{/if}
</div>
</header>
{/case}
{case value="7"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v07" data-tf="F07">
<div class="{$TpStyle.dom_prefix}-titleF-wrap">
<div class="{$TpStyle.dom_prefix}-titleF-head">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-tail">
<a class="{$TpStyle.dom_prefix}-titleF-more" href="{$strMoreUrl}" >
<span class="{$TpStyle.dom_prefix}-titleF-moreTxt">{$Slot.more_text|default='更多'}</span>
<i class="{$TpStyle.dom_prefix}-titleF-moreIco" aria-hidden="true"></i>
</a>
</div>
{/if}
</div>
</header>
{/case}
{case value="8"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v08" data-tf="F08">
<div class="{$TpStyle.dom_prefix}-titleF-left">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">
{$title.primary}
<em class="{$TpStyle.dom_prefix}-titleF-sfx" aria-hidden="true"></em>
</h3>
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-more">
<a href="{$moreUrl}" rel="nofollow">
{$moreText|default='更多'}
<a href="{$strMoreUrl}" >
<span class="{$TpStyle.dom_prefix}-titleF-moreTxt">{$Slot.more_text|default='更多'}</span>
</a>
</div>
{/if}
</header>
{/case}
{case value="9"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v09" data-tf="F09">
<div class="{$TpStyle.dom_prefix}-titleF-bar">
<div class="{$TpStyle.dom_prefix}-titleF-l">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<div class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</div>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-r">
<a class="{$TpStyle.dom_prefix}-titleF-more" href="{$strMoreUrl}"
>{$Slot.more_text|default='更多'}</a>
</div>
{/if}
</div>
</header>
{/case}
{case value="10"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v10" data-tf="F10">
<div class="{$TpStyle.dom_prefix}-titleF-head">
<h3 class="{$TpStyle.dom_prefix}-titleF-main"><span aria-hidden="true">#</span>{$title.primary}</h3>
{if !empty($strMoreUrl)}
<a class="{$TpStyle.dom_prefix}-titleF-more" href="{$strMoreUrl}"
>{$Slot.more_text|default='更多'}</a>
{/if}
</div>
{if !empty($title.secondary)}
<div class="{$TpStyle.dom_prefix}-titleF-foot">
<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>
</div>
{/if}
</header>
{/case}
{case value="11"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v11" data-tf="F11">
<div class="{$TpStyle.dom_prefix}-titleF-rail" aria-hidden="true"></div>
<div class="{$TpStyle.dom_prefix}-titleF-content">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
<div class="{$TpStyle.dom_prefix}-titleF-actions">
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
{if !empty($strMoreUrl)}
<a class="{$TpStyle.dom_prefix}-titleF-more" href="{$strMoreUrl}"
>{$Slot.more_text|default='更多'}</a>
{/if}
</div>
</div>
</header>
{/case}
{case value="12"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v12" data-tf="F12">
<div class="{$TpStyle.dom_prefix}-titleF-left">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
</div>
<div class="{$TpStyle.dom_prefix}-titleF-right">
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
{if !empty($strMoreUrl)}
<span class="{$TpStyle.dom_prefix}-titleF-more">
<a href="{$strMoreUrl}" >{$Slot.more_text|default='更多'}</a>
</span>
{/if}
</div>
</header>
{/case}
{case value="13"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v13" data-tf="F13">
<div class="{$TpStyle.dom_prefix}-titleF-center">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-moreWrap">
<a class="{$TpStyle.dom_prefix}-titleF-more" href="{$strMoreUrl}"
>{$Slot.more_text|default='更多'}</a>
</div>
{/if}
</header>
{/case}
{case value="14"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v14" data-tf="F14">
<div class="{$TpStyle.dom_prefix}-titleF-inner">
<div class="{$TpStyle.dom_prefix}-titleF-title">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-more">
<a href="{$strMoreUrl}" >
<span class="{$TpStyle.dom_prefix}-titleF-moreTxt">{$Slot.more_text|default='更多'}</span>
</a>
</div>
{/if}
</div>
<div class="{$TpStyle.dom_prefix}-titleF-divider" aria-hidden="true"></div>
</header>
{/case}
{case value="15"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v15" data-tf="F15">
<div class="{$TpStyle.dom_prefix}-titleF-left">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">
<span class="{$TpStyle.dom_prefix}-titleF-pre" aria-hidden="true"></span>
{$title.primary}
</h3>
</div>
<div class="{$TpStyle.dom_prefix}-titleF-right">
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
{if !empty($strMoreUrl)}
<a class="{$TpStyle.dom_prefix}-titleF-more" href="{$strMoreUrl}"
>{$Slot.more_text|default='更多'}</a>
{/if}
</div>
</header>
{/case}
{case value="16"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v16" data-tf="F16">
<div class="{$TpStyle.dom_prefix}-titleF-hero">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($strMoreUrl)}
<a class="{$TpStyle.dom_prefix}-titleF-more" href="{$strMoreUrl}" >
<span class="{$TpStyle.dom_prefix}-titleF-moreTxt">{$Slot.more_text|default='更多'}</span>
</a>
{/if}
</div>
{if !empty($title.secondary)}
<div class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</div>
{/if}
</header>
{/case}
{case value="17"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v17" data-tf="F17">
<div class="{$TpStyle.dom_prefix}-titleF-row">
<div class="{$TpStyle.dom_prefix}-titleF-text">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-more">
<a href="{$strMoreUrl}" >
<span class="{$TpStyle.dom_prefix}-titleF-moreTxt">{$Slot.more_text|default='更多'}</span>
<span class="{$TpStyle.dom_prefix}-titleF-moreArr" aria-hidden="true"></span>
</a>
</div>
{/if}
</div>
</header>
{/case}
{case value="18"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v18" data-tf="F18">
<!-- <div class="{$TpStyle.dom_prefix}-titleF-cap" aria-hidden="true"></div> -->
<div class="{$TpStyle.dom_prefix}-titleF-body">
<div class="{$TpStyle.dom_prefix}-titleF-left">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<small class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</small>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-more">
<a href="{$strMoreUrl}" >{$Slot.more_text|default='更多'}</a>
</div>
{/if}
</div>
</header>
{/case}
{case value="19"}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v19" data-tf="F19">
<div class="{$TpStyle.dom_prefix}-titleF-a">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-b">
<a class="{$TpStyle.dom_prefix}-titleF-more" href="{$strMoreUrl}" >
<span class="{$TpStyle.dom_prefix}-titleF-moreTxt">{$Slot.more_text|default='更多'}</span>
<i class="{$TpStyle.dom_prefix}-titleF-ico" aria-hidden="true"></i>
</a>
</div>
{/if}
</header>
{/case}
{default /}
<header class="{$TpStyle.dom_prefix}-titleF {$TpStyle.dom_prefix}-titleF-v00" data-tf="F00">
<div class="{$TpStyle.dom_prefix}-titleF-left">
<h3 class="{$TpStyle.dom_prefix}-titleF-main">{$title.primary}</h3>
{if !empty($title.secondary)}<span class="{$TpStyle.dom_prefix}-titleF-sub">{$title.secondary}</span>{/if}
</div>
{if !empty($strMoreUrl)}
<div class="{$TpStyle.dom_prefix}-titleF-more">
<a href="{$strMoreUrl}" >{$Slot.more_text|default='更多'}</a>
</div>
{/if}
</header>
{/default}
{/switch}

View File

@@ -23,31 +23,35 @@
{include file="module/playline/playline_router" /}
{/case}
{case value="pinlun"}
{include file="module/pinlun/pinlun_router" /}
{/case}
{case value="list"}
{notempty name="pageCfg.list.modules"}
{notempty name="pageCfg.list.slots"}
{volist name="pageCfg.list.modules" id="module"}
{volist name="pageCfg.list.slots" id="Slot"}
{assign name="cfg" value="$TpStyle.template_cfg.list_layout[$module]"}
{assign name="title" value="$Slot.title_text"}
{assign name="title" value="$cfg.title_text"}
{assign name="listCfg" value="$TpStyle.template_cfg.list_layout[$Slot.layout_key]" /}
{include file="module/list/title/title_A" /}
{assign name="limit" value="$listCfg['layout']['max_items']"}
{assign name="listCfg" value="$TpStyle.list_layout[$module]" /}
{assign name="limit" value="$cfg['layout']['max_items']"}
{if $module == 'rank'}
{if $Slot.layout_key == 'rank'}
{video:ranklistexp count="$limit" sort_type="weekly" d_key="key" d_val="Video" cache_life="3600" v_parent_category_en="$Request.route.strParentCategory"
export_name="__LIST__" /}
{else/}
{video:listexp count="$limit" sort_type="$module" d_key="key" d_val="Video" cache_life="3600" v_parent_category_en="$Request.route.strParentCategory"
{video:listexp count="$limit" sort_type="$Slot.layout_key" d_key="key" d_val="Video" cache_life="3600" v_parent_category_en="$Request.route.strParentCategory"
export_name="__LIST__" /}
{/if}
{include file="module/list/title/_title_router" /}
{include file="module/list/shell/_shell_router" /}
{/volist}

View File

@@ -0,0 +1,359 @@
{switch $variant}
{case value="0"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">最新评论</h3>
<span class="{$TpStyle.dom_prefix}-cmt-count">共 {:$arrPinlun ? count($arrPinlun) : 0} 条</span>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span class="{$TpStyle.dom_prefix}-cmt-user">{$it.user}</span>
<time class="{$TpStyle.dom_prefix}-cmt-time">{$it.time}</time>
</div>
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
</article>
{/volist}
</div>
</section>
{/case}
{case value="1"}
<section class="{$baseCls}">
<div class="{$TpStyle.dom_prefix}-cmt-hd">
<strong class="{$TpStyle.dom_prefix}-cmt-title">观众留言</strong>
</div>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span> · <span>{$it.time}</span>
</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="2"}
<aside class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h4 class="{$TpStyle.dom_prefix}-cmt-title">短评</h4>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">“{$it.text}”</p>
<footer class="{$TpStyle.dom_prefix}-cmt-meta">
<small>{$it.user}</small>
<small>{$it.time}</small>
</footer>
</article>
{/volist}
</div>
</aside>
{/case}
{case value="3"}
<section class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">大家都在说</h3>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<b>{$it.user}</b> <i>{$it.time}</i>
</div>
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="4"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">讨论区</h3>
</header>
<ol class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<li class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<span class="{$TpStyle.dom_prefix}-cmt-meta">{$it.user} · {$it.time}</span>
</li>
{/volist}
</ol>
</section>
{/case}
{case value="5"}
<div class="{$baseCls}">
<div class="{$TpStyle.dom_prefix}-cmt-hd">
<span class="{$TpStyle.dom_prefix}-cmt-title">网友热评</span>
</div>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<header class="{$TpStyle.dom_prefix}-cmt-meta">
<span class="{$TpStyle.dom_prefix}-cmt-user">{$it.user}</span>
</header>
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<footer class="{$TpStyle.dom_prefix}-cmt-meta">
<time>{$it.time}</time>
</footer>
</article>
{/volist}
</div>
</div>
{/case}
{case value="6"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">评论精选</h3>
<a class="{$TpStyle.dom_prefix}-cmt-more" href="javascript:void(0)">更多</a>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span><span>{$it.time}</span>
</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="7"}
<aside class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">看完的朋友说</h3>
<ul class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<li class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<small>{$it.user}</small>
<small>{$it.time}</small>
</div>
</li>
{/volist}
</ul>
</aside>
{/case}
{case value="8"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h4 class="{$TpStyle.dom_prefix}-cmt-title">短评区</h4>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<p class="{$TpStyle.dom_prefix}-cmt-meta">来自 {$it.user} · {$it.time}</p>
</article>
{/volist}
</div>
</section>
{/case}
{case value="9"}
<section class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">评论</h3>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<span class="{$TpStyle.dom_prefix}-cmt-user">{$it.user}</span>
<span class="{$TpStyle.dom_prefix}-cmt-time">{$it.time}</span>
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="10"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<strong class="{$TpStyle.dom_prefix}-cmt-title">留言板</strong>
</header>
<dl class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<dt class="{$TpStyle.dom_prefix}-cmt-meta">{$it.user} · {$it.time}</dt>
<dd class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</dd>
</div>
{/volist}
</dl>
</section>
{/case}
{case value="11"}
<div class="{$baseCls}">
<div class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">互动</h3>
</div>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text"><mark>{$it.text}</mark></p>
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span> <span>{$it.time}</span>
</div>
</article>
{/volist}
</div>
</div>
{/case}
{case value="12"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h4 class="{$TpStyle.dom_prefix}-cmt-title">影评摘录</h4>
</header>
<ol class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<li class="{$TpStyle.dom_prefix}-cmt-item">
<blockquote class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</blockquote>
<cite class="{$TpStyle.dom_prefix}-cmt-meta">{$it.user} · {$it.time}</cite>
</li>
{/volist}
</ol>
</section>
{/case}
{case value="13"}
<section class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">短评</h3>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span class="{$TpStyle.dom_prefix}-cmt-user">{$it.user}</span>
<span class="{$TpStyle.dom_prefix}-cmt-time">{$it.time}</span>
</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="14"}
<aside class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">大家怎么看</h3>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<header class="{$TpStyle.dom_prefix}-cmt-meta">
<small>{$it.user}</small>
</header>
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
</article>
{/volist}
</div>
</aside>
{/case}
{case value="15"}
<div class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">评论区</h3>
<ul class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<li class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<p class="{$TpStyle.dom_prefix}-cmt-meta">{$it.time}</p>
</li>
{/volist}
</ul>
</div>
{/case}
{case value="16"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h4 class="{$TpStyle.dom_prefix}-cmt-title">看法</h4>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<footer class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span>
</footer>
</article>
{/volist}
</div>
</section>
{/case}
{case value="17"}
<section class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">观后感</h3>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<div class="{$TpStyle.dom_prefix}-cmt-meta">{$it.user}</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="18"}
<aside class="{$baseCls}">
<strong class="{$TpStyle.dom_prefix}-cmt-title">评论摘要</strong>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span><span>{$it.time}</span>
</div>
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
</div>
{/volist}
</div>
</aside>
{/case}
{case value="19"}
<div class="{$baseCls}">
<h4 class="{$TpStyle.dom_prefix}-cmt-title">讨论</h4>
<ol class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<li class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
<small class="{$TpStyle.dom_prefix}-cmt-meta">{$it.user} · {$it.time}</small>
</li>
{/volist}
</ol>
</div>
{/case}
{default}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">最新评论</h3>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span class="{$TpStyle.dom_prefix}-cmt-user">{$it.user}</span>
<time class="{$TpStyle.dom_prefix}-cmt-time">{$it.time}</time>
</div>
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
</article>
{/volist}
</div>
</section>
{/default}
{/switch}

View File

@@ -0,0 +1,33 @@
<{$wrapTag} class="{$baseCls}">
{if $titleTag}
<{$titleTag} class="{$TpStyle.dom_prefix}-cmt-title">观众评论</{$titleTag}>
{/if}
<ul class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<li class="{$TpStyle.dom_prefix}-cmt-item">
{if $arrRule.meta == 'top'}
<div class="{$TpStyle.dom_prefix}-cmt-meta">
{if $arrRule.user}<span>{$it.user}</span>{/if}
{if $arrRule.time}<span>{$it.time}</span>{/if}
</div>
{/if}
<div class="{$TpStyle.dom_prefix}-cmt-text">
{$it.text}
</div>
{if $arrRule.meta == 'bottom'}
<div class="{$TpStyle.dom_prefix}-cmt-meta">
{if $arrRule.user}<span>{$it.user}</span>{/if}
{if $arrRule.time}<span>{$it.time}</span>{/if}
</div>
{/if}
</li>
{/volist}
</ul>
</{$wrapTag}>

View File

@@ -0,0 +1,34 @@
<{$wrapTag} class="{$baseCls}">
{if $titleTag}
<{$titleTag} class="{$TpStyle.dom_prefix}-cmt-title">网友热评</{$titleTag}>
{/if}
<div class="{$TpStyle.dom_prefix}-cmt-cards">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-card">
{if $arrRule.meta == 'top'}
<div class="{$TpStyle.dom_prefix}-cmt-meta">
{if $arrRule.user}<span>{$it.user}</span>{/if}
{if $arrRule.time}<span>{$it.time}</span>{/if}
</div>
{/if}
<div class="{$TpStyle.dom_prefix}-cmt-text">
{$it.text}
</div>
{if $arrRule.meta == 'bottom'}
<div class="{$TpStyle.dom_prefix}-cmt-meta">
{if $arrRule.user}<span>{$it.user}</span>{/if}
{if $arrRule.time}<span>{$it.time}</span>{/if}
</div>
{/if}
</div>
{/volist}
</div>
</{$wrapTag}>

View File

@@ -0,0 +1,61 @@
{php}
/**
* Layout A标准影评 / SEO 语义型
* variant ∈ 019
*/
$V = $variant % 20;
$titles = [
'最新评论','观众留言','短评','大家都在说','讨论区',
'网友热评','评论精选','看完的朋友说','短评区','评论',
'留言板','互动','影评摘录','短评','大家怎么看',
'评论区','看法','观后感','评论摘要','讨论'
];
$titleTags = ['h3','h4','strong','span',null];
$wrapTags = ['section','aside','div'];
$listTags = ['div','ul','ol','dl'];
$itemTags = ['article','div','li'];
$titleText = $titles[$V];
$titleTag = $titleTags[$V % count($titleTags)];
$wrapTag = $wrapTags[$V % count($wrapTags)];
$listTag = $listTags[$V % count($listTags)];
$itemTag = $itemTags[$V % count($itemTags)];
$metaPos = $V % 3; // 0=top 1=bottom 2=inline
{/php}
<{$wrapTag} class="{$baseCls} layout-a v{$V}">
{if $titleTag}
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<{$titleTag} class="{$TpStyle.dom_prefix}-cmt-title">{$titleText}</{$titleTag}>
</header>
{/if}
<{$listTag} class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<{$itemTag} class="{$TpStyle.dom_prefix}-cmt-item">
{if $metaPos == 0}
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span>
<time>{$it.time}</time>
</div>
{/if}
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
{if $metaPos == 1}
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span>
<time>{$it.time}</time>
</div>
{/if}
</{$itemTag}>
{/volist}
</{$listTag}>
</{$wrapTag}>

View File

@@ -0,0 +1,70 @@
{php}
$V = $variant % 20;
/* 20 个不同标题 */
$titles = [
'观众评论','大家都在说','留言区','网友讨论','评论列表',
'讨论区','大家怎么看','留言板','影迷交流','看法汇总',
'用户反馈','评论','短评','影迷说','大家的意见',
'交流区','讨论','留言','网友声音','评论区'
];
/* 标签池 */
$wrapTags = ['section','div','aside'];
$listTags = ['ul','ol','div'];
$itemTags = ['li','li','div']; // 强化列表感
$titleTags = ['h3','h4','strong','span',null];
$titleText = $titles[$V];
$wrapTag = $wrapTags[$V % count($wrapTags)];
$listTag = $listTags[$V % count($listTags)];
$itemTag = $itemTags[$V % count($itemTags)];
$titleTag = $titleTags[$V % count($titleTags)];
$metaPos = $V % 4; // 0=top 1=bottom 2=inline 3=none
{/php}
<{$wrapTag} class="{$baseCls} layout-b v{$V}">
{if $titleTag}
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<{$titleTag} class="{$TpStyle.dom_prefix}-cmt-title">
{$titleText}
</{$titleTag}>
</header>
{/if}
<{$listTag} class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<{$itemTag} class="{$TpStyle.dom_prefix}-cmt-item">
{if $metaPos == 0}
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span>
<span>{$it.time}</span>
</div>
{/if}
{if $metaPos == 2}
<span class="{$TpStyle.dom_prefix}-cmt-user">{$it.user}</span>
{/if}
<div class="{$TpStyle.dom_prefix}-cmt-text">
{$it.text}
</div>
{if $metaPos == 1}
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span>
<span>{$it.time}</span>
</div>
{/if}
</{$itemTag}>
{/volist}
</{$listTag}>
</{$wrapTag}>

View File

@@ -0,0 +1,74 @@
{php}
$V = $variant % 20;
/* 20 个标题(偏内容 / 热评) */
$titles = [
'网友热评','大家的看法','评论精选','短评摘要','热门反馈',
'讨论精选','观后感','大家在说','影评摘录','热评',
'评论亮点','精选留言','内容反馈','观众声音','短评',
'讨论要点','网友评价','反馈','热门评论','大家的意见'
];
$wrapTags = ['div','section','aside'];
$cardsWrap = ['div','div','section'];
$cardTags = ['div','article'];
$titleTags = ['strong','h3','h4','span',null];
$titleText = $titles[$V];
$wrapTag = $wrapTags[$V % count($wrapTags)];
$cardsTag = $cardsWrap[$V % count($cardsWrap)];
$cardTag = $cardTags[$V % count($cardTags)];
$titleTag = $titleTags[$V % count($titleTags)];
$metaMode = $V % 5; // 0=user 1=time 2=both 3=none 4=inline
{/php}
<{$wrapTag} class="{$baseCls} layout-c v{$V}">
{if $titleTag}
<{$titleTag} class="{$TpStyle.dom_prefix}-cmt-title">
{$titleText}
</{$titleTag}>
{/if}
<{$cardsTag} class="{$TpStyle.dom_prefix}-cmt-cards">
{volist name="arrPinlun" id="it"}
<{$cardTag} class="{$TpStyle.dom_prefix}-cmt-card">
{if $metaMode == 0}
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span>
</div>
{/if}
{if $metaMode == 1}
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<time>{$it.time}</time>
</div>
{/if}
<div class="{$TpStyle.dom_prefix}-cmt-text">
{$it.text}
</div>
{if $metaMode == 2}
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span>
<time>{$it.time}</time>
</div>
{/if}
{if $metaMode == 4}
<span class="{$TpStyle.dom_prefix}-cmt-inline">
{$it.user} · {$it.time}
</span>
{/if}
</{$cardTag}>
{/volist}
</{$cardsTag}>
</{$wrapTag}>

View File

@@ -0,0 +1,359 @@
{switch $variant}
{case value="0"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">最新评论</h3>
<span class="{$TpStyle.dom_prefix}-cmt-count">共 {:$arrPinlun ? count($arrPinlun) : 0} 条</span>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span class="{$TpStyle.dom_prefix}-cmt-user">{$it.user}</span>
<time class="{$TpStyle.dom_prefix}-cmt-time">{$it.time}</time>
</div>
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
</article>
{/volist}
</div>
</section>
{/case}
{case value="1"}
<section class="{$baseCls}">
<div class="{$TpStyle.dom_prefix}-cmt-hd">
<strong class="{$TpStyle.dom_prefix}-cmt-title">观众留言</strong>
</div>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span> · <span>{$it.time}</span>
</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="2"}
<aside class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h4 class="{$TpStyle.dom_prefix}-cmt-title">短评</h4>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">“{$it.text}”</p>
<footer class="{$TpStyle.dom_prefix}-cmt-meta">
<small>{$it.user}</small>
<small>{$it.time}</small>
</footer>
</article>
{/volist}
</div>
</aside>
{/case}
{case value="3"}
<section class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">大家都在说</h3>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<b>{$it.user}</b> <i>{$it.time}</i>
</div>
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="4"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">讨论区</h3>
</header>
<ol class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<li class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<span class="{$TpStyle.dom_prefix}-cmt-meta">{$it.user} · {$it.time}</span>
</li>
{/volist}
</ol>
</section>
{/case}
{case value="5"}
<div class="{$baseCls}">
<div class="{$TpStyle.dom_prefix}-cmt-hd">
<span class="{$TpStyle.dom_prefix}-cmt-title">网友热评</span>
</div>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<header class="{$TpStyle.dom_prefix}-cmt-meta">
<span class="{$TpStyle.dom_prefix}-cmt-user">{$it.user}</span>
</header>
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<footer class="{$TpStyle.dom_prefix}-cmt-meta">
<time>{$it.time}</time>
</footer>
</article>
{/volist}
</div>
</div>
{/case}
{case value="6"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">评论精选</h3>
<a class="{$TpStyle.dom_prefix}-cmt-more" href="javascript:void(0)">更多</a>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span><span>{$it.time}</span>
</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="7"}
<aside class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">看完的朋友说</h3>
<ul class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<li class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<small>{$it.user}</small>
<small>{$it.time}</small>
</div>
</li>
{/volist}
</ul>
</aside>
{/case}
{case value="8"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h4 class="{$TpStyle.dom_prefix}-cmt-title">短评区</h4>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<p class="{$TpStyle.dom_prefix}-cmt-meta">来自 {$it.user} · {$it.time}</p>
</article>
{/volist}
</div>
</section>
{/case}
{case value="9"}
<section class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">评论</h3>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<span class="{$TpStyle.dom_prefix}-cmt-user">{$it.user}</span>
<span class="{$TpStyle.dom_prefix}-cmt-time">{$it.time}</span>
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="10"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<strong class="{$TpStyle.dom_prefix}-cmt-title">留言板</strong>
</header>
<dl class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<dt class="{$TpStyle.dom_prefix}-cmt-meta">{$it.user} · {$it.time}</dt>
<dd class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</dd>
</div>
{/volist}
</dl>
</section>
{/case}
{case value="11"}
<div class="{$baseCls}">
<div class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">互动</h3>
</div>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text"><mark>{$it.text}</mark></p>
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span> <span>{$it.time}</span>
</div>
</article>
{/volist}
</div>
</div>
{/case}
{case value="12"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h4 class="{$TpStyle.dom_prefix}-cmt-title">影评摘录</h4>
</header>
<ol class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<li class="{$TpStyle.dom_prefix}-cmt-item">
<blockquote class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</blockquote>
<cite class="{$TpStyle.dom_prefix}-cmt-meta">{$it.user} · {$it.time}</cite>
</li>
{/volist}
</ol>
</section>
{/case}
{case value="13"}
<section class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">短评</h3>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span class="{$TpStyle.dom_prefix}-cmt-user">{$it.user}</span>
<span class="{$TpStyle.dom_prefix}-cmt-time">{$it.time}</span>
</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="14"}
<aside class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">大家怎么看</h3>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<header class="{$TpStyle.dom_prefix}-cmt-meta">
<small>{$it.user}</small>
</header>
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
</article>
{/volist}
</div>
</aside>
{/case}
{case value="15"}
<div class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">评论区</h3>
<ul class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<li class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<p class="{$TpStyle.dom_prefix}-cmt-meta">{$it.time}</p>
</li>
{/volist}
</ul>
</div>
{/case}
{case value="16"}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h4 class="{$TpStyle.dom_prefix}-cmt-title">看法</h4>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<footer class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span>
</footer>
</article>
{/volist}
</div>
</section>
{/case}
{case value="17"}
<section class="{$baseCls}">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">观后感</h3>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
<div class="{$TpStyle.dom_prefix}-cmt-meta">{$it.user}</div>
</div>
{/volist}
</div>
</section>
{/case}
{case value="18"}
<aside class="{$baseCls}">
<strong class="{$TpStyle.dom_prefix}-cmt-title">评论摘要</strong>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<div class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span>{$it.user}</span><span>{$it.time}</span>
</div>
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
</div>
{/volist}
</div>
</aside>
{/case}
{case value="19"}
<div class="{$baseCls}">
<h4 class="{$TpStyle.dom_prefix}-cmt-title">讨论</h4>
<ol class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<li class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</div>
<small class="{$TpStyle.dom_prefix}-cmt-meta">{$it.user} · {$it.time}</small>
</li>
{/volist}
</ol>
</div>
{/case}
{default}
<section class="{$baseCls}">
<header class="{$TpStyle.dom_prefix}-cmt-hd">
<h3 class="{$TpStyle.dom_prefix}-cmt-title">最新评论</h3>
</header>
<div class="{$TpStyle.dom_prefix}-cmt-list">
{volist name="arrPinlun" id="it"}
<article class="{$TpStyle.dom_prefix}-cmt-item">
<div class="{$TpStyle.dom_prefix}-cmt-meta">
<span class="{$TpStyle.dom_prefix}-cmt-user">{$it.user}</span>
<time class="{$TpStyle.dom_prefix}-cmt-time">{$it.time}</time>
</div>
<p class="{$TpStyle.dom_prefix}-cmt-text">{$it.text}</p>
</article>
{/volist}
</div>
</section>
{/default}
{/switch}

View File

@@ -0,0 +1,36 @@
{site:pinlun id="$arrVideo.v_id" export_name="arrPinlunData" /}
{assign name="arrPinlun" value="$arrPinlunData.arrPinlun"}
{assign name="arrRule" value="$arrPinlunData.arrRule"}
{assign name="pinlunCfg" value="$pageCfg.pinlun"}
{assign name="layout" value="$pinlunCfg.layout"}
{assign name="variant" value="$pinlunCfg.variant"}
{assign name="wrapTag" value="$arrRule.wrap"}
{assign name="titleTag" value="$arrRule.title"}
{php}
// 统一 class冻结
$baseCls = $TpStyle['dom_prefix'] . '-cmt'
. ' layout-' . strtolower($layout)
. ' v' . $variant;
{/php}
{switch $layout}
{case value="A"}
{include file="module/pinlun/layout/layout_A" /}
{/case}
{case value="B"}
{include file="module/pinlun/layout/layout_B" /}
{/case}
{case value="C"}
{include file="module/pinlun/layout/layout_C" /}
{/case}
{default}
{include file="module/pinlun/layout/layout_A" /}
{/default}
{/switch}

View File

@@ -0,0 +1,39 @@
{site:pinlun id="$arrVideo.v_id" export_name="arrPinlunData" /}
{assign name="arrPinlun" value="$arrPinlunData.arrPinlun"}
{assign name="pinlunCfg" value="$pageCfg.pinlun"}
{assign name="layout" value="$pinlunCfg.layout"}
{assign name="variant" value="$pinlunCfg.variant"}
{php}
// 统一 class冻结
$baseCls = $TpStyle['dom_prefix'] . '-cmt'
. ' layout-' . strtolower($layout)
. ' v' . $variant;
{/php}
{switch $layout}
{case value="A"}
{include file="module/pinlun/pinlun_A" /}
{/case}
{case value="B"}
{include file="module/pinlun/pinlun_B" /}
{/case}
{case value="C"}
{include file="module/pinlun/pinlun_C" /}
{/case}
{case value="D"}
{include file="module/pinlun/pinlun_D" /}
{/case}
{default}
{include file="module/pinlun/pinlun_A" /}
{/default}
{/switch}

View File

@@ -6,7 +6,7 @@
{if $variant == 0}
<nav class="{$TpStyle.dom_prefix}-pl-tabs">
{foreach $arrVideo.v_play_url as $line=>$list}
<span class="{$TpStyle.dom_prefix}-pl-tab">{$line}</span>
<span class="{$TpStyle.dom_prefix}-pl-tab">{video:getlinename code="$line" encode="false"/}</span>
{/foreach}
</nav>
<ul class="{$TpStyle.dom_prefix}-pl-grid">
@@ -21,7 +21,7 @@
{elseif $variant == 1}
{foreach $arrVideo.v_play_url as $line=>$list}
<section class="{$TpStyle.dom_prefix}-pl-block">
<h4>{$line}</h4>
<h4>{video:getlinename code="$line" encode="false"/}</h4>
<ol>
{volist name="list" id="ep" key="i"}
<li><a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a></li>
@@ -34,7 +34,7 @@
{elseif $variant == 2}
<dl class="{$TpStyle.dom_prefix}-pl-dl">
{foreach $arrVideo.v_play_url as $line=>$list}
<dt>{$line}</dt>
<dt>{video:getlinename code="$line" encode="false"/}</dt>
<dd>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a>
@@ -46,7 +46,7 @@
{// ================= Variant 3UL + strong ================= }
{elseif $variant == 3}
{foreach $arrVideo.v_play_url as $line=>$list}
<strong>{$line}</strong>
<strong>{video:getlinename code="$line" encode="false"/}</strong>
<ul>
{volist name="list" id="ep" key="i"}
<li><a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a></li>
@@ -58,7 +58,7 @@
{elseif $variant == 4}
{foreach $arrVideo.v_play_url as $line=>$list}
<article class="{$TpStyle.dom_prefix}-pl-card">
<header>{$line}</header>
<header>{video:getlinename code="$line" encode="false"/}</header>
<div>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a>
@@ -71,7 +71,7 @@
{elseif $variant == 5}
<table class="{$TpStyle.dom_prefix}-pl-table">
{foreach $arrVideo.v_play_url as $line=>$list}
<tr><th colspan="2">{$line}</th></tr>
<tr><th colspan="2">{video:getlinename code="$line" encode="false"/}</th></tr>
{volist name="list" id="ep" key="i"}
<tr>
<td>{$i}</td>
@@ -85,7 +85,7 @@
{elseif $variant == 6}
{foreach $arrVideo.v_play_url as $line=>$list}
<nav>
<b>{$line}</b>
<b>{video:getlinename code="$line" encode="false"/}</b>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a>
{/volist}
@@ -95,7 +95,7 @@
{// ================= Variant 7Span Flow ================= }
{elseif $variant == 7}
{foreach $arrVideo.v_play_url as $line=>$list}
<p>{$line}</p>
<p>{video:getlinename code="$line" encode="false"/}</p>
<div>
{volist name="list" id="ep" key="i"}
<span><a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a></span>
@@ -108,7 +108,7 @@
<ul>
{foreach $arrVideo.v_play_url as $line=>$list}
<li>
{$line}
{video:getlinename code="$line" encode="false"/}
<ul>
{volist name="list" id="ep" key="i"}
<li><a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a></li>
@@ -121,7 +121,7 @@
{// ================= Variant 9Minimal ================= }
{elseif $variant == 9}
{foreach $arrVideo.v_play_url as $line=>$list}
<h5>{$line}</h5>
<h5>{video:getlinename code="$line" encode="false"/}</h5>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a>
{/volist}
@@ -131,7 +131,7 @@
{else}
{foreach $arrVideo.v_play_url as $line=>$list}
<section>
<h4>{$line}</h4>
<h4>{video:getlinename code="$line" encode="false"/}</h4>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a>
{/volist}

View File

@@ -1,13 +1,13 @@
<section class="{$TpStyle.dom_prefix}-pl {$TpStyle.dom_prefix}-pl-b">
{assign name="variant" value="$pageCfg.playline.variant"}
{php}$intLineIndex=0;{/php}
{// ================= Variant 0Left Line / Right Grid ================= }
{if $variant == 0}
<div class="{$TpStyle.dom_prefix}-pl-wrap">
<aside class="{$TpStyle.dom_prefix}-pl-lines">
{foreach $arrVideo.v_play_url as $line=>$list}
<div class="{$TpStyle.dom_prefix}-pl-line">{$line}</div>
<div class="{$TpStyle.dom_prefix}-pl-line">{video:getlinename code="$line" encode="false"/}</div>
{/foreach}
</aside>
<div class="{$TpStyle.dom_prefix}-pl-episodes">
@@ -26,7 +26,7 @@
<div class="{$TpStyle.dom_prefix}-pl-columns">
<ul class="{$TpStyle.dom_prefix}-pl-lines">
{foreach $arrVideo.v_play_url as $line=>$list}
<li>{$line}</li>
<li>{video:getlinename code="$line" encode="false"/}</li>
{/foreach}
</ul>
<ul class="{$TpStyle.dom_prefix}-pl-episodes">
@@ -42,7 +42,7 @@
{elseif $variant == 2}
<dl class="{$TpStyle.dom_prefix}-pl-dl">
{foreach $arrVideo.v_play_url as $line=>$list}
<dt>{$line}</dt>
<dt>{video:getlinename code="$line" encode="false"/}</dt>
<dd>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a>
@@ -55,7 +55,7 @@
{elseif $variant == 3}
{foreach $arrVideo.v_play_url as $line=>$list}
<section class="{$TpStyle.dom_prefix}-pl-section">
<header>{$line}</header>
<header>{video:getlinename code="$line" encode="false"/}</header>
<div>
{volist name="list" id="ep" key="i"}
<span><a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a></span>
@@ -68,7 +68,7 @@
{elseif $variant == 4}
<table class="{$TpStyle.dom_prefix}-pl-table">
{foreach $arrVideo.v_play_url as $line=>$list}
<tr><th>{$line}</th><td>
<tr><th>{video:getlinename code="$line" encode="false"/}</th><td>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a>
{/volist}
@@ -81,7 +81,7 @@
<div class="{$TpStyle.dom_prefix}-pl-nav-wrap">
<nav>
{foreach $arrVideo.v_play_url as $line=>$list}
<a>{$line}</a>
<a>{video:getlinename code="$line" encode="false"/}</a>
{/foreach}
</nav>
<section>
@@ -97,7 +97,7 @@
{elseif $variant == 6}
<aside class="{$TpStyle.dom_prefix}-pl-aside">
{foreach $arrVideo.v_play_url as $line=>$list}
<h5>{$line}</h5>
<h5>{video:getlinename code="$line" encode="false"/}</h5>
{/foreach}
</aside>
<ol class="{$TpStyle.dom_prefix}-pl-episodes">
@@ -111,7 +111,7 @@
{// ================= Variant 7Compact ================= }
{elseif $variant == 7}
{foreach $arrVideo.v_play_url as $line=>$list}
<p><b>{$line}</b></p>
<p><b>{video:getlinename code="$line" encode="false"/}</b></p>
<p>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a>
@@ -123,7 +123,7 @@
{elseif $variant == 8}
<table>
{foreach $arrVideo.v_play_url as $line=>$list}
<tr><td>{$line}</td><td>
<tr><td>{video:getlinename code="$line" encode="false"/}</td><td>
<table>
{volist name="list" id="ep" key="i"}
<tr><td><a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a></td></tr>
@@ -137,7 +137,7 @@
{elseif $variant == 9}
{foreach $arrVideo.v_play_url as $line=>$list}
<article>
<h3>{$line}</h3>
<h3>{video:getlinename code="$line" encode="false"/}</h3>
<p>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a>
@@ -148,13 +148,14 @@
{// ================= Variant 1019兜底 ================= }
{else}
{foreach $arrVideo.v_play_url as $line=>$list}
<div>
<strong>{$line}</strong>
{foreach $arrVideo.v_play_url as $line=>$list }
<div class="{if $intLineIndex==0}active{/if}">
<strong>{video:getlinename code="$line" encode="false"/}</strong>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">{$ep.name}</a>
{/volist}
</div>
{php}$intLineIndex++;{/php}
{/foreach}
{/if}

View File

@@ -6,7 +6,7 @@
{if $variant == 0}
{foreach $arrVideo.v_play_url as $line=>$list}
<section class="{$TpStyle.dom_prefix}-pl-block">
<h3>{$line}</h3>
<h3>{video:getlinename code="$line" encode="false"/}</h3>
<ol>
{volist name="list" id="ep" key="i"}
<li>
@@ -23,7 +23,7 @@
{elseif $variant == 1}
{foreach $arrVideo.v_play_url as $line=>$list}
<article class="{$TpStyle.dom_prefix}-pl-article">
<header><h4>{$line}</h4></header>
<header><h4>{video:getlinename code="$line" encode="false"/}</h4></header>
<div>
{volist name="list" id="ep" key="i"}
<p>
@@ -40,7 +40,7 @@
{elseif $variant == 2}
<dl class="{$TpStyle.dom_prefix}-pl-dl">
{foreach $arrVideo.v_play_url as $line=>$list}
<dt>{$line}</dt>
<dt>{video:getlinename code="$line" encode="false"/}</dt>
{volist name="list" id="ep" key="i"}
<dd>
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">
@@ -54,7 +54,7 @@
{// ================= Variant 3段落式 ================= }
{elseif $variant == 3}
{foreach $arrVideo.v_play_url as $line=>$list}
<h4>{$line}</h4>
<h4>{video:getlinename code="$line" encode="false"/}</h4>
<p>
{volist name="list" id="ep" key="i"}
<span>
@@ -70,7 +70,7 @@
{elseif $variant == 4}
{foreach $arrVideo.v_play_url as $line=>$list}
<blockquote class="{$TpStyle.dom_prefix}-pl-quote">
<strong>{$line}</strong>
<strong>{video:getlinename code="$line" encode="false"/}</strong>
{volist name="list" id="ep" key="i"}
<div>
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">
@@ -84,7 +84,7 @@
{// ================= Variant 5UL + Paragraph ================= }
{elseif $variant == 5}
{foreach $arrVideo.v_play_url as $line=>$list}
<h4>{$line}</h4>
<h4>{video:getlinename code="$line" encode="false"/}</h4>
<ul>
{volist name="list" id="ep" key="i"}
<li>
@@ -102,7 +102,7 @@
{elseif $variant == 6}
{foreach $arrVideo.v_play_url as $line=>$list}
<section>
<h4>{$line}</h4>
<h4>{video:getlinename code="$line" encode="false"/}</h4>
{volist name="list" id="ep" key="i"}
<div>
<time>{$i}</time>
@@ -118,7 +118,7 @@
{elseif $variant == 7}
{foreach $arrVideo.v_play_url as $line=>$list}
<div>
<h3>{$line}</h3>
<h3>{video:getlinename code="$line" encode="false"/}</h3>
<p>
本线路提供以下资源:
{volist name="list" id="ep" key="i"}
@@ -133,7 +133,7 @@
{// ================= Variant 8Mixed OL / P ================= }
{elseif $variant == 8}
{foreach $arrVideo.v_play_url as $line=>$list}
<h4>{$line}</h4>
<h4>{video:getlinename code="$line" encode="false"/}</h4>
{volist name="list" id="ep" key="i"}
<p>
第 {$i} 集:
@@ -147,7 +147,7 @@
{// ================= Variant 9Minimal Reading ================= }
{elseif $variant == 9}
{foreach $arrVideo.v_play_url as $line=>$list}
<h5>{$line}</h5>
<h5>{video:getlinename code="$line" encode="false"/}</h5>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">
{$ep.name}
@@ -159,8 +159,8 @@
{else}
{foreach $arrVideo.v_play_url as $line=>$list}
<section>
<strong>{$line}</strong>
{volist name="list" id="ep" key="i"}
<strong>{video:getlinename code="$line" encode="false"/} : </strong>
{volist name="list" id="ep" key="i"}
<a href="{site:vpurl v_id='$arrVideo.v_id' play_type='$line' play_index='$i'/}">
{$ep.name}
</a>

View File

@@ -2,61 +2,144 @@
{block name="get-data"}
{video:pagerexp page="$Request.route.intPage" limit="30" button_num="10" cache_life="3600"
v_parent_category_en="$Request.route.strParentCategory"
v_category_en="$Request.route.strCategory"
v_lang_en="$Request.route.strLang"
v_area_en="$Request.route.strArea"
v_year="$Request.route.strYear"
sort_type="$Request.route.strOrder"
d_key="d_key" d_val="Video" p_val="page_data" func="generateVideoPager" export_name="resData" /}
{assign name="strCategory" value="$Request.route.strCategory"}
{assign name="ModuleCfg" value="$TpStyle.template_cfg.pages.category_list.cat2_map[$strCategory]"}
{assign name="Slot" value="$ModuleCfg"}
{assign name="title" value="$ModuleCfg.title_text"}
{assign name="listCfg" value="$TpStyle.template_cfg.list_layout.category_list"}
{assign name="limit" value="$listCfg.layout.max_items"}
{video:pagerexp page="$Request.route.intPage" limit="$limit" button_num="10" cache_life="3600"
v_parent_category_en="$Request.route.strParentCategory"
v_category_en="$Request.route.strCategory"
d_key="d_key" d_val="Video" p_val="page_data" func="generateVideoPager" export_name="resData" /}
{assign name="__LIST__" value="$resData.data"}
{/block}
{block name="title"}
在线观看
{block name="title"}{site:seotkd code="title" page="category_list" /}{/block}
{block name="keywords"}{site:seotkd code="keywords" page="category_list" /}{/block}
{block name="description"}{site:seotkd code="description" page="category_list" /}{/block}
{block name="head"}
<meta name="robots" content="index,follow">
<link rel="canonical" href='https://{$DomainModel->d_domain}{site:vclurl parent_category="$Request.route.strParentCategory" category="$Request.route.strCategory" /}'>
{// 社交媒体标签}
<meta property="og:title" content='{site:seotkd code="title" page="category_list" /}' />
<meta property="og:description" content='{site:seotkd code="description" page="category_list" /}' />
<meta property="og:url" content="https://{$DomainModel->d_domain}" />
{switch $Request.route.strParentCategory }
{case 'dian-ying' }
<meta property="og:type" content="video.movie" />
{/case}
{case 'dian-shi-ju' }
<meta property="og:type" content="video.episode" />
{/case}
{case 'zong-yi' }
<meta property="og:type" content="video.tv_show" />
{/case}
{case 'dong-man' }
<meta property="og:type" content="video.episode" />
{/case}
{case 'duan-ju-da-quan' }
<meta property="og:type" content="video.episode" />
{/case}
{default /}
<meta property="og:type" content="video.movie" />
{/switch}
{// 结构化数据}
<script type="application/ld+json">
[
{
"@context": "https://schema.org",
"@type": "CollectionPage",
"name": "{$DomainModel->d_name} - 最新{site:getval code="strVideoParentCategoryName" /}推荐",
"url": "https://{$DomainModel->d_domain}",
"description": "{site:seotkd code="description" page="category_list" /}",
"potentialAction": {
"@type": "SearchAction",
"target": 'https://{$DomainModel->d_domain}{site:vsurl key="search_term_string" p="1"/}",
"query-input": "required name=search_term_string"
}
"hasPart": [
{volist name="resData.data" id="Video" key="key"}
{if $key < 5 }
{
"@type": "VideoObject",
"name": "{$Video.v_name}",
"description": "{$Video.v_description}",
"thumbnailUrl": '{$Video.v_pic}',
"uploadDate": "{:date('Y-m-d')}",
"url": 'https://{$DomainModel->d_domain}{site:vurl v_id="$Video.v_id" v_py="$Video.v_name_en"/}',
},
{/if}
{/volist}
]
},
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "首页",
"item": "https://{$DomainModel->d_domain}"
},
{
"@type": "ListItem",
"position": 2,
"name": "分类首页",
"item": "https://{$DomainModel->d_domain}{site:vciurl parent_category="$Request.route.strParentCategory" /}"
},
{
"@type": "ListItem",
"position": 3,
"name": "分类列表",
"item": "https://{$DomainModel->d_domain}{site:vclurl parent_category="$Request.route.strParentCategory" category="$Request.route.strCategory" page="$Request.route.intPage"}"
}
]
},
]
</script>
{/block}
{block name="strPageCode"}<?php $strPageCode = 'category'; ?>{/block}
{block name="main"}
<main class="page-category-sub" style="max-width:{$TpStyle.page_max_width_pc}px;margin:0 auto;">
<main class="page-category-sub" style="max-width:{$TpStyle.template_cfg.global.page_max_width_pc}px;margin:0 auto;">
{php}
// 1. 读取冻结 cfg
$cfg = $TpStyle['list_layout']['category_list'];
{include file="module/list/title/_title_router" /}
// 2. 构建标题(不随机)
$title = [
'primary' => '',
'secondary' => '共 ' . $resData['p_data']['total'] . ' 部影片',
];
{/php}
{// ===== Title ===== }
{include file="module/list/title/title_F" /}
{// ===== Shell + Item ===== }
{assign name="__LIST__" value="$resData.data"}
{assign name="listCfg" value="$TpStyle.list_layout.category_list"}
{include file="module/list/shell/_shell_router" /}
{// ===== Pagination ===== }
{php}
$pagerArr = $resData['p_data']['pager'] ?? [];
$page = $resData['p_data']['page'] ?? 1;
$pages = $resData['p_data']['pages'] ?? 1;
$pagerArr = $resData['p_data']['pager'] ?? [];
$page = $resData['p_data']['page'] ?? 1;
$pages = $resData['p_data']['pages'] ?? 1;
// 从 cfg 取分页配置(你会在 SiteStyle 冻结下发)
$pagerCfg = $TpStyle['template_cfg']['components']['pager'] ?? [];
// 从 cfg 取分页配置(你会在 SiteStyle 冻结下发)
$pagerCfg = $TpStyle['template_cfg']['components']['pager'] ?? [];
{/php}
{assign name="listCfg" value="$TpStyle.list_layout.category_list"}
{include file="module/pager/_pager_router" /}
</main>

View File

@@ -6,27 +6,115 @@
{/block}
{block name="title"}{site:replace code="VIDEO@GETCATEGORYINDEX@TITLE"}{/block}
{block name="keywords"}{site:replace code="VIDEO@GETCATEGORYINDEX@KEYWORDS"}{/block}
{block name="description"}{site:replace code="VIDEO@GETCATEGORYINDEX@DESCRIPTION"}{/block}
{block name="title"}{site:seotkd code="title" page="category_index" /}{/block}
{block name="keywords"}{site:seotkd code="keywords" page="category_index" /}{/block}
{block name="description"}{site:seotkd code="description" page="category_index" /}{/block}
{block name="head"}
<meta name="robots" content="index,follow">
<link rel="canonical" href='https://{$DomainModel->d_domain}{site:vciurl parent_category="$Request.route.strParentCategory" /}'>
<meta property="og:title" content='{site:replace code="VIDEO@GETCATEGORYINDEX@TITLE"}' />
<meta property="og:description" content='{site:replace code="VIDEO@GETCATEGORYINDEX@DESCRIPTION"}' />
<meta property="og:url" content="https://{$DomainModel->d_domain}" />
{switch $Request.route.strParentCategory }
{case 'dian-ying' }
<meta property="og:type" content="video.movie" />
{/case}
{case 'dian-shi-ju' }
<meta property="og:type" content="video.episode" />
{/case}
{case 'zong-yi' }
<meta property="og:type" content="video.tv_show" />
{/case}
{case 'dong-man' }
<meta property="og:type" content="video.episode" />
{/case}
{case 'duan-ju-da-quan' }
<meta property="og:type" content="video.episode" />
{/case}
{default /}
<meta property="og:type" content="video.movie" />
{/switch}
<script type="application/ld+json">
[
{
"@context": "https://schema.org",
"@type": "CollectionPage",
"name": "{$DomainModel->d_name} - 最新{site:getval code="strVideoParentCategoryName" /}推荐",
"url": "https://{$DomainModel->d_domain}",
"description": "{site:replace code="VIDEO@GETCATEGORYINDEX@DESCRIPTION"}",
"potentialAction": {
"@type": "SearchAction",
"target": 'https://{$DomainModel->d_domain}{site:vsurl key="search_term_string" p="1"/}",
"query-input": "required name=search_term_string"
}
"hasPart": [
{video:ranklist count="5"
v_parent_category_en="$Request.route.strParentCategory"
sort_type="weekly"
d_key="key" d_val="Video" cache_life="3600"}
{if $key < 5 }
{
"@type": "VideoObject",
"name": "{$Video.v_name}",
"description": "{$Video.v_description}",
"thumbnailUrl": '{$Video.v_pic}',
"uploadDate": "{:date('Y-m-d')}",
"url": 'https://{$DomainModel->d_domain}{site:vurl v_id="$Video.v_id" v_py="$Video.v_name_en"/}',
},
{/if}
{/video:ranklist}
]
},
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "首页",
"item": "https://{$DomainModel->d_domain}"
},
{
"@type": "ListItem",
"position": 2,
"name": "分类首页",
"item": "https://{$DomainModel->d_domain}{site:vciurl parent_category="$Request.route.strParentCategory" /}"
}
]
},
]
</script>
{/block}
{block name="head-css"}{/block}
{block name="head-js"}{/block}
{block name="strPageCode"}<?php $strPageCode = 'category_type'; ?>{/block}
{block name="main"}
<main class="page-category" style="max-width:{$TpStyle.page_max_width_pc}px;margin:0 auto;">
<main class="page-category" style="max-width:{$TpStyle.template_cfg.global.page_max_width_pc}px;margin:0 auto;">
<!-- ================= 聚合推荐区 ================= -->
{assign name="topModule" value="$TpStyle.template_cfg.pages.category_index.top_block.module"}
{// ================= 聚合推荐区 =================}
{assign name="strParentCategory" value="$Request.route.strParentCategory"}
{assign name="cfg" value="$TpStyle.template_cfg.list_layout[$topModule]"}
{assign name="TopModuleCfg" value="$TpStyle.template_cfg.pages.category.cat1_map[$strParentCategory]"}
{assign name="limit" value="$cfg['layout']['max_items']"}
{assign name="topModule" value="$TopModuleCfg.top_module"}
{assign name="Slot" value="$TopModuleCfg.top_slot"}
{assign name="listCfg" value="$TpStyle.template_cfg.list_layout[$topModule]"}
{assign name="limit" value="$listCfg.layout.max_items"}
{if $topModule == 'rank'}
{video:ranklistexp count="$limit" sort_type="weekly" d_key="key" d_val="Video" cache_life="3600" v_parent_category_en="$Request.route.strParentCategory"
export_name="__LIST__" /}
@@ -37,24 +125,29 @@
{/if}
{assign name="title" value="$cfg.title_text"}
{assign name="title" value="$TopModuleCfg.top_slot.title_text"}
{include file="module/list/title/title_A" /}
{assign name="listCfg" value="$TpStyle.template_cfg.list_layout.category_list_index"}
{include file="module/list/title/_title_router" /}
{include file="module/list/shell/_shell_router" /}
<!-- ================= 二级分类区块 ================= -->
{//- ================= 二级分类区块 ================= }
{video:categorytype category_type="ONE" d_key="key" d_val="val"}
{if $val.v_category_en == $Request.route.strParentCategory}
{foreach $val.children as $i => $sub}
{assign name="ParentCategory" value="$TpStyle.template_cfg.pages.category.cat1_map[$val.v_category_en]"}
{video:listexp count="12"
{foreach $ParentCategory.subcat_slots as $i => $sub}
{assign name="listCfg" value="$TpStyle.template_cfg.list_layout[$sub.layout_key]"}
{assign name="limit" value="$listCfg.layout.max_items"}
{assign name="title" value="$sub.title_text"}
{assign name="Slot" value="$sub"}
{video:listexp count="$limit"
v_parent_category_en="$Request.route.strParentCategory"
v_category_en="$sub.v_category_en"
v_category_en="$sub.key"
v_lang_en="all"
v_area_en="all"
v_year="all"
@@ -62,38 +155,11 @@
d_key="d_key" d_val="Video" cache_life="3600"
export_name="__LIST__" /}
{php}
// 1⃣ 生成该二级分类的 section cfg冻结
$sectionCfg = \app\common\helper\SiteStyle::buildCategorySectionCfg(
$TpStyle['template_cfg'],
$sub['v_category_en'],
$i
);
// 2⃣ 数据源(按二级分类变量名取)
$listVar = 'arrSubPreview_' . $sub['v_category_en'];
// $__LIST__ = $listVar ?? [];
//$__LIST__ = $arrVideoNewest ?? [];
// 3⃣ Title二级分类固定 F
$title = [
'primary' => $sub['v_category'],
'secondary' => '精选推荐',
];
// 4⃣ 更多链接
$moreUrl = '/videotype-dian-ying/xi-ju-pian-all-all-all/all-page1';
{/php}
{site:vclurl parent_category="$Request.route.strParentCategory" category="$sub.key" page="1" export_name="strMoreUrl"/}
<section class="category-sub-block">
<!-- ===== TitleF===== -->
{include file="module/list/title/title_F" /}
<!-- ===== Shell + Item ===== -->
{assign name="cfg" value="$sectionCfg"}
{assign name="listCfg" value="$TpStyle.list_layout.category_list_index"}
{include file="module/list/title/_title_router" /}
{include file="module/list/shell/_shell_router" /}

View File

@@ -1,21 +1,82 @@
{extend name="base" /}
{block name="get-data"}
{assign name="arrSlots" value="$TpStyle.template_cfg.pages.rank_home.slots"}
{/block}
{block name="title"}{site:replace code="VIDEO@GETVIDEORANKINDEX@TITLE"}{/block}
{block name="keywords"}{site:replace code="VIDEO@GETVIDEORANKINDEX@KEYWORDS"}{/block}
{block name="description"}{site:replace code="VIDEO@GETVIDEORANKINDEX@DESCRIPTION"}{/block}
{block name="title"}{site:seotkd code="title" page="rank_index" /}{/block}
{block name="keywords"}{site:seotkd code="keywords" page="rank_index" /}{/block}
{block name="description"}{site:seotkd code="description" page="rank_index" /}{/block}
{block name="head"}
<meta name="robots" content="index,follow">
<link rel="canonical" href='https://{$DomainModel->d_domain}{$strRankUrlTemp}'>
{// 社交媒体标签}
<meta property="og:title" content='{site:seotkd code="title" page="rank_index" /}' />
<meta property="og:description" content='{site:seotkd code="description" page="rank_index" /}' />
<meta property="og:url" content="https://{$DomainModel->d_domain}" />
<meta property="og:type" content="video.movie" />
<script type="application/ld+json">
[
{
"@context": "https://schema.org",
"@type": "CollectionPage",
"name": "{$DomainModel->d_name} - 最新排行榜推荐",
"url": "https://{$DomainModel->d_domain}",
"headline": '{site:seotkd code="title" page="rank_index" /}',
"description": '{site:seotkd code="description" page="rank_index" /}',
"potentialAction": {
"@type": "SearchAction",
"target": 'https://{$DomainModel->d_domain}{site:vsurl key="search_term_string" p="1"/}",
"query-input": "required name=search_term_string"
}
"hasPart": [
{video:ranklist count="5"
sort_type="weekly"
d_key="key" d_val="Video" cache_life="3600"}
{if $key < 10 }
{
"@type": "VideoObject",
"name": "{$Video.v_name}",
"description": "{$Video.v_description}",
"thumbnailUrl": '{$Video.v_pic}',
"uploadDate": "{:date('Y-m-d')}",
"url": 'https://{$DomainModel->d_domain}{site:vurl v_id="$Video.v_id" v_py="$Video.v_name_en"/}',
},
{/if}
{/video:ranklist}
]
},
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "首页",
"item": "https://{$DomainModel->d_domain}"
},
{
"@type": "ListItem",
"position": 2,
"name": "排行榜首页",
"item": "https://{$DomainModel->d_domain}{$strRankUrlTemp}"
}
]
},
]
</script>
{/block}
{block name="head-css"}
{/block}
@@ -28,35 +89,22 @@
{block name="main"}
{assign name="cfg" value="$TpStyle.template_cfg.list_layout.rank_list_index"}
{assign name="listCfg" value="$TpStyle.template_cfg.list_layout.rank_list_index"}
{assign name="rankModules" value="$TpStyle.template_cfg.pages.rank_home.modules"}
{assign name="limit" value="$cfg['layout']['max_items']"}
<section class="{$TpStyle.dom_prefix}-rank-home">
{foreach $arrSlots as $i => $Slot}
{video:ranksort d_key="key" d_val="val"}
{assign name="listCfg" value="$TpStyle.template_cfg.list_layout[$Slot.layout_key]"}
{assign name="title" value="$Slot.title_text"}
{assign name="limit" value="$listCfg['layout']['max_items']"}
{video:ranklistexp count="$limit"
sort_type="$key"
sort_type="$Slot.sort_type"
d_key="key" d_val="Video" cache_life="3600" export_name="__LIST__" /}
{php}
$title = [
'primary' => $val.'排行榜',
'secondary' => '',
];
{/php}
{include file="module/list/title/_title_router" /}
{include file="module/list/shell/_shell_router" /}
{/video:ranksort}
{/foreach}
</section>
{/block}

View File

@@ -15,15 +15,15 @@ p_val="page_data" button_num="10" cache_life="3600" export_name="arrVideoRankLis
{/block}
{block name="title"}{site:replace code="VIDEO@GETVIDEORANKLIST@TITLE"}{/block}
{block name="keywords"}{site:replace code="VIDEO@GETVIDEORANKLIST@KEYWORDS"}{/block}
{block name="description"}{site:replace code="VIDEO@GETVIDEORANKLIST@DESCRIPTION"}{/block}
{block name="title"}{site:seotkd code="title" page="rank_list" /}{/block}
{block name="keywords"}{site:seotkd code="title" page="rank_list" /}{/block}
{block name="description"}{site:seotkd code="title" page="rank_list" /}{/block}
{block name="head"}
{// 社交媒体标签}
<meta property="og:title" content='{site:replace code="VIDEO@GETVIDEORANKLIST@TITLE"}' />
<meta property="og:description" content='{site:replace code="VIDEO@GETVIDEORANKLIST@DESCRIPTION"}' />
<meta property="og:title" content='{site:seotkd code="title" page="rank_list" /}' />
<meta property="og:description" content='{site:seotkd code="title" page="rank_list" /}' />
<meta property="og:url" content="https://{$DomainModel->d_domain}" />
<meta property="og:type" content="video.movie" />
@@ -36,8 +36,8 @@ p_val="page_data" button_num="10" cache_life="3600" export_name="arrVideoRankLis
"@type": "CollectionPage",
"name": "{$DomainModel->d_name} - 最新排行榜推荐",
"url": "https://{$DomainModel->d_domain}",
"headline": '{site:replace code="VIDEO@GETVIDEORANKLIST@TITLE"}',
"description": '{site:replace code="VIDEO@GETVIDEORANKLIST@DESCRIPTION"}',
"headline": '{site:seotkd code="title" page="rank_list" /}',
"description": '{site:seotkd code="title" page="rank_list" /}',
"potentialAction": {
"@type": "SearchAction",
"target": 'https://{$DomainModel->d_domain}{site:vsurl key="search_term_string" p="1"/}",

View File

@@ -1,8 +1,8 @@
{extend name="base" /}
{block name="get-data"}
{assign name="limit" value="$TpStyle.list_layout.search_list.layout.max_items"}
{assign name="listCfg" value="$TpStyle.list_layout.search_list"}
{assign name="limit" value="$TpStyle.template_cfg.list_layout.search_list.layout.max_items"}
{assign name="listCfg" value="$TpStyle.template_cfg.list_layout.search_list"}
{video:pagerexp page="$Request.get.page" limit="$limit"
key="$Request.get.keyword"
@@ -13,20 +13,24 @@ p_val="page_data" button_num="5" cache_life="3600" func="generateSearchPager" ex
{/block}
{block name="title"}{site:replace code="VIDEO@GETSEARCHVIDEO@TITLE"}{/block}
{block name="keywords"}{site:replace code="VIDEO@GETSEARCHVIDEO@KEYWORDS"}{/block}
{block name="description"}{site:replace code="VIDEO@GETSEARCHVIDEO@DESCRIPTION"}{/block}
{block name="title"}{site:seotkd code="title" page="search" /}{/block}
{block name="keywords"}{site:seotkd code="keywords" page="search" /}{/block}
{block name="description"}{site:seotkd code="description" page="search" /}{/block}
{block name="head"}
<meta property="og:title" content='{site:replace code="VIDEO@GETSEARCHVIDEO@TITLE"}'>
<meta property="og:description" content='{site:replace code="VIDEO@GETSEARCHVIDEO@DESCRIPTION"}'>
<meta name="robots" content="index,follow">
<link rel="canonical" href='https://{$DomainModel->d_domain}{site:vsurl key="$Request.get.keyword" p="1"/}'>
<meta property="og:title" content='{site:seotkd code="title" page="search" /}'>
<meta property="og:description" content='{site:seotkd code="description" page="search" /}'>
<meta property="og:url" content='https://{$DomainModel->d_domain}{site:vsurl key="search_term_string" p="1"/}'>
<meta property="og:type" content="website">
<meta property="og:site_name" content='{$DomainModel->d_name}'>
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content='{site:replace code="VIDEO@GETSEARCHVIDEO@TITLE"}'>
<meta name="twitter:description" content='{site:replace code="VIDEO@GETSEARCHVIDEO@DESCRIPTION"}'>
<meta name="twitter:title" content='{site:seotkd code="title" page="search" /}'>
<meta name="twitter:description" content='{site:seotkd code="description" page="search" /}'>
<meta name="twitter:image:alt" content="动作电影 搜索结果第1页">
{// 结构化数据}
@@ -50,7 +54,7 @@ p_val="page_data" button_num="5" cache_life="3600" func="generateSearchPager" ex
"name": "{$DomainModel->d_name} - {$DomainModel->d_logo_text}",
"url": "https://{$DomainModel->d_domain}",
"alternateName": "{$DomainModel->d_domain}",
"description": '{site:replace code="VIDEO@GETSEARCHVIDEO@DESCRIPTION"}',
"description": '{site:seotkd code="description" page="search" /}',
"mainEntity": {
"@type": "ItemList",
"itemListElement": [
@@ -62,7 +66,7 @@ p_val="page_data" button_num="5" cache_life="3600" func="generateSearchPager" ex
"item": {
"@type": "Movies",
"name": "{$Video.v_name}",
"url": 'https://{$DomainModel->d_domain}{site:vurl v_id='$vo.v_id' v_py='$vo.v_name_en'/}',
"url": 'https://{$DomainModel->d_domain}{site:vurl v_id="$Video.v_id" v_py="$Video.v_name_en"/}',
"description": "{$Video.v_description}",
"actor": [
{foreach $Video.v_actor as $strActorKey=>$strActor }
@@ -88,7 +92,6 @@ p_val="page_data" button_num="5" cache_life="3600" func="generateSearchPager" ex
</script>
{/block}
{block name="head-css"}
{/block}
@@ -99,19 +102,9 @@ p_val="page_data" button_num="5" cache_life="3600" func="generateSearchPager" ex
{block name="main"}
{php}
// 1. 读取冻结 cfg
$cfg = $TpStyle['list_layout']['search_list'];
$searchCfg = $TpStyle['template_cfg']['pages']['search']['top_block'];
// 2. 构建标题(不随机)
$title = [
'primary' => '',
'secondary' => '共 ' . $resData['p_data']['total'] . ' 部影片',
];
{/php}
{assign name="searchCfg" value="$TpStyle['template_cfg']['pages']['search']['top_block']"}
{assign name="Slot" value="$TpStyle['template_cfg']['pages']['search']['list_slot']"}
{assign name="title" value="$Slot.title_text"}
{include file="module/search/_search_header_router" /}

View File

@@ -1,26 +1,21 @@
{extend name="base" /}
{block name="get-data"}
{if $Request.route.intVId && $Request.route.intVForgeId}
{video:info v_id="$Request.route.intVId" v_key="arrVideo" v_fid="$Request.route.intVForgeId" export_name="arrVideo"/}
{elseif $Request.route.intVId}
{video:info v_id="$Request.route.intVId" v_key="arrVideo" export_name="arrVideo"/}
{else}
{video:info v_id="$DomainModel->info_id" n_key="arrVideo" export_name="arrVideo" /}
{/if}
{if $Request.route.intVId && $Request.route.intVForgeId}
{video:info v_id="$Request.route.intVId" v_key="arrVideo" v_fid="$Request.route.intVForgeId" export_name="arrVideo"/}
{elseif $Request.route.intVId}
{video:info v_id="$Request.route.intVId" v_key="arrVideo" export_name="arrVideo"/}
{else}
{video:info v_id="$DomainModel->info_id" n_key="arrVideo" export_name="arrVideo" /}
{/if}
{site:vciurl parent_category="$arrVideo.v_parent_category_en" export_name="strVciurl" /}
{site:vclurl parent_category="$arrVideo.v_parent_category_en"
{site:vciurl parent_category="$arrVideo.v_parent_category_en" export_name="strVciurl" /}
{site:vclurl parent_category="$arrVideo.v_parent_category_en"
category="$arrVideo.v_category_en"
area="all" lang="all" year="all" order="all" page="1"
export_name="strVclurl" /}
{/block}
{block name="main"}
{assign name="pageCfg" value="$TpStyle.template_cfg.pages.detail"}
{php}
$arrBreadcrumb = [
['title'=>'首页','url'=>'/'],
@@ -28,9 +23,165 @@
['title'=>$arrVideo['v_category'],'url'=>$strVclurl],
];
{/php}
<!-- 播放页:$pageCfg = $TpStyle['template_cfg']['pages']['play']; -->
{/block}
{block name="title"}{if $DomainModel->info_id == $Request.route.intVId || empty($Request.route.intVId)}{site:replace code="VIDEO@INDEX@INDEX@TITLE" /}{else/}{site:seotkd code="title" page="detail" /}{/if}{/block}
{block name="keywords"}{if $DomainModel->info_id == $Request.route.intVId || empty($Request.route.intVId)}{site:replace code="VIDEO@INDEX@INDEX@KEYWORDS" /}{else/}{site:seotkd code="keywords" page="detail" /}{/if}{/block}
{block name="description"}{if $DomainModel->info_id == $Request.route.intVId || empty($Request.route.intVId)}{site:replace code="VIDEO@INDEX@INDEX@DESCRIPTION" /}{else/}{site:seotkd code="description" page="detail" /}{/if}{/block}
{block name="head"}
<meta name="robots" content="index,follow">
{if $arrVideo.v_id}
<link rel="canonical" href='https://{$DomainModel->d_domain}{site:vurl v_id="$arrVideo.v_id" v_py="$arrVideo.v_name_en"/}'>
{/if}
{// Open Graph 协议用于Facebook、LinkedIn等}
<meta property="og:title" content='{site:seotkd code="title" page="detail" /}'>
<meta property="og:description" content='{site:seotkd code="description" page="detail" /}'>
{switch $arrVideo.v_parent_category_en }
{case 'dian-ying' }
<meta property="og:type" content="video.movie" />
{/case}
{case 'dian-shi-ju' }
<meta property="og:type" content="video.episode" />
{/case}
{case 'zong-yi' }
<meta property="og:type" content="video.tv_show" />
{/case}
{case 'dong-man' }
<meta property="og:type" content="video.episode" />
{/case}
{case 'duan-ju-da-quan' }
<meta property="og:type" content="video.episode" />
{/case}
{default /}
<meta property="og:type" content="video.movie" />
{/switch}
<meta property="og:url" content='https://{$DomainModel->d_domain}{site:vurl v_id="$arrVideo.v_id" v_py="$arrVideo.v_name_en"/}'>
<meta property="og:image" content="https://{$DomainModel->d_domain}{$arrVideo.v_pic}">
<meta property="og:site_name" content="{$DomainModel->d_name}">
<meta property="og:video:type" content="video/m3u8">
{// Twitter Card用于Twitter/X}
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{$arrVideo.v_name|raw} - {$arrVideo.v_category|default=''|raw}完整版在线观看 - {$DomainModel->d_name|raw}">
<meta name="twitter:description" content="{if !empty($arrVideo.v_description)}{$arrVideo.v_description|raw}{else/}{$DomainModel->d_name|raw}为你提供{$arrVideo.v_name|raw}在线播放与相关内容推荐。{/if}">
<meta name="twitter:image" content="{if stripos($arrVideo.v_pic,'http')===0}{$arrVideo.v_pic|raw}{else/}https://{$DomainModel->d_domain}{$arrVideo.v_pic|raw}{/if}">
{php}
// 你已有:$arrBreadcrumbtitle/url
// 这里补成绝对 URL避免 JSON-LD 用相对路径
$strBase = 'https://' . $DomainModel->d_domain;
$arrBreadcrumbLd = [];
foreach ($arrBreadcrumb as $intIdx => $arrIt) {
$strTitle = (string)($arrIt['title'] ?? '');
$strUrl = (string)($arrIt['url'] ?? '');
if ($strTitle === '' || $strUrl === '') {
continue;
}
// url 绝对化
if (stripos($strUrl, 'http') !== 0) {
if ($strUrl[0] !== '/') {
$strUrl = '/' . $strUrl;
}
$strUrl = $strBase . $strUrl;
}
$arrBreadcrumbLd[] = [
'@type' => 'ListItem',
'position' => (int)($intIdx + 1),
'name' => $strTitle,
'item' => $strUrl,
];
}
{/php}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": {php}echo json_encode($arrBreadcrumbLd, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);{/php}
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "VideoObject",
"name": "{$arrVideo.v_name|raw}",
"description": "{if !empty($arrVideo.v_description)}{$arrVideo.v_description|raw}{else/}暂无简介{/if}",
"thumbnailUrl": "{$arrVideo.v_pic|raw}",
"uploadDate": "{:date('Y-m-d')}",
"url": "https://{$DomainModel->d_domain}{site:vurl v_id="$arrVideo.v_id" v_py="$arrVideo.v_name_en"/}"
{if !empty($arrVideo.v_lang)},{/if}
{if !empty($arrVideo.v_lang)}
"inLanguage": [
{volist name="$arrVideo.v_lang" id="strVideoLang" key="index"}{if $index>1},{/if}"{$strVideoLang|raw}"{/volist}
]
{/if}
{if !empty($arrVideo.v_area)},{/if}
{if !empty($arrVideo.v_area)}
"contentLocation": [
{volist name="$arrVideo.v_area" id="strVideoArea" key="index"}{if $index>1},{/if}{
"@type": "Place",
"name": "{$strVideoArea|raw}"
}{/volist}
]
{/if}
{if !empty($arrVideo.v_director)},{/if}
{if !empty($arrVideo.v_director)}
"director": [
{volist name="$arrVideo.v_director" id="strVideoDirector" key="index"}{if $index>1},{/if}{
"@type": "Person",
"name": "{$strVideoDirector|raw}"
}{/volist}
]
{/if}
{if !empty($arrVideo.v_actor)},{/if}
{if !empty($arrVideo.v_actor)}
"actor": [
{volist name="$arrVideo.v_actor" id="strVideoActor" key="index"}{if $index>1},{/if}{
"@type": "Person",
"name": "{$strVideoActor|raw}"
}{/volist}
]
{/if}
{if !empty($arrVideo.v_score) && floatval($arrVideo.v_score)>0},{/if}
{if !empty($arrVideo.v_score) && floatval($arrVideo.v_score)>0}
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "{$arrVideo.v_score|raw}",
"ratingCount": 1
}
{/if},
"publisher": {
"@type": "Organization",
"name": "{$DomainModel->d_name|raw}"
}
}
</script>
{/block}
{block name="strPageCode"}
<?php $strPageCode = 'info'; ?>
{/block}
{block name="main"}
{assign name="pageCfg" value="$TpStyle.template_cfg.pages.detail"}
{include file="module/page/page_router" /}
{/block}

View File

@@ -1,30 +1,20 @@
{extend name="base" /}
{block name="get-data"}
{if $Request.route.intVId && $Request.route.intVForgeId}
{video:info v_id="$Request.route.intVId" v_key="arrVideo" v_fid="$Request.route.intVForgeId" export_name="arrVideo"/}
{elseif $Request.route.intVId}
{video:info v_id="$Request.route.intVId" v_key="arrVideo" export_name="arrVideo"/}
{else}
{video:info v_id="$DomainModel->info_id" n_key="arrVideo" export_name="arrVideo" /}
{/if}
{if $Request.route.intVId && $Request.route.intVForgeId}
{video:info v_id="$Request.route.intVId" v_key="arrVideo" v_fid="$Request.route.intVForgeId" export_name="arrVideo"/}
{elseif $Request.route.intVId}
{video:info v_id="$Request.route.intVId" v_key="arrVideo" export_name="arrVideo"/}
{else}
{video:info v_id="$DomainModel->info_id" n_key="arrVideo" export_name="arrVideo" /}
{/if}
{site:vciurl parent_category="$arrVideo.v_parent_category_en" export_name="strVciurl" /}
{site:vclurl parent_category="$arrVideo.v_parent_category_en"
{site:vciurl parent_category="$arrVideo.v_parent_category_en" export_name="strVciurl" /}
{site:vclurl parent_category="$arrVideo.v_parent_category_en"
category="$arrVideo.v_category_en"
area="all" lang="all" year="all" order="all" page="1"
export_name="strVclurl" /}
{/block}
{block name="head-css"}
<link rel="stylesheet" href="/public/video/DPlayer.min.css">
{/block}
{block name="main"}
{assign name="pageCfg" value="$TpStyle.template_cfg.pages.play"}
{php}
$arrBreadcrumb = [
['title'=>'首页','url'=>'/'],
@@ -32,11 +22,165 @@
['title'=>$arrVideo['v_category'],'url'=>$strVclurl],
];
{/php}
<!-- 播放页:$pageCfg = $TpStyle['template_cfg']['pages']['play']; -->
{/block}
{block name="title"}{site:seotkd code="title" page="play" /}{/block}
{block name="keywords"}{site:seotkd code="keywords" page="play" /}{/block}
{block name="description"}{site:seotkd code="description" page="play" /}{/block}
{block name="head"}
<meta name="robots" content="index,follow">
{if $Request.route.intVId }
<link rel="canonical" href='https://{$DomainModel->d_domain}{site:vpurl v_id="$arrVideo.v_id" v_py="$arrVideo.v_name_en" play_type="default" play_index="1" /}'>
{/if}
{// Open Graph 协议用于Facebook、LinkedIn等}
<meta property="og:title" content='{site:seotkd code="title" page="play" /}'>
<meta property="og:description" content='{site:seotkd code="description" page="play" /}'>
{switch $arrVideo.v_parent_category_en }
{case 'dian-ying' }
<meta property="og:type" content="video.movie" />
{/case}
{case 'dian-shi-ju' }
<meta property="og:type" content="video.episode" />
{/case}
{case 'zong-yi' }
<meta property="og:type" content="video.tv_show" />
{/case}
{case 'dong-man' }
<meta property="og:type" content="video.episode" />
{/case}
{case 'duan-ju-da-quan' }
<meta property="og:type" content="video.episode" />
{/case}
{default /}
<meta property="og:type" content="video.movie" />
{/switch}
<meta property="og:url" content='https://{$DomainModel->d_domain}{site:vurl v_id="$arrVideo.v_id" v_py="$arrVideo.v_name_en"/}'>
<meta property="og:image" content="https://{$DomainModel->d_domain}{$arrVideo.v_pic}">
<meta property="og:site_name" content="{$DomainModel->d_name}">
<meta property="og:video:type" content="video/m3u8">
{// Twitter Card用于Twitter/X}
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{$arrVideo.v_name|raw} - {$arrVideo.v_category|default=''|raw}完整版在线观看 - {$DomainModel->d_name|raw}">
<meta name="twitter:description" content="{if !empty($arrVideo.v_description)}{$arrVideo.v_description|raw}{else/}{$DomainModel->d_name|raw}为你提供{$arrVideo.v_name|raw}在线播放与相关内容推荐。{/if}">
<meta name="twitter:image" content="{if stripos($arrVideo.v_pic,'http')===0}{$arrVideo.v_pic|raw}{else/}https://{$DomainModel->d_domain}{$arrVideo.v_pic|raw}{/if}">
{php}
// 你已有:$arrBreadcrumbtitle/url
// 这里补成绝对 URL避免 JSON-LD 用相对路径
$strBase = 'https://' . $DomainModel->d_domain;
$arrBreadcrumbLd = [];
foreach ($arrBreadcrumb as $intIdx => $arrIt) {
$strTitle = (string)($arrIt['title'] ?? '');
$strUrl = (string)($arrIt['url'] ?? '');
if ($strTitle === '' || $strUrl === '') {
continue;
}
// url 绝对化
if (stripos($strUrl, 'http') !== 0) {
if ($strUrl[0] !== '/') {
$strUrl = '/' . $strUrl;
}
$strUrl = $strBase . $strUrl;
}
$arrBreadcrumbLd[] = [
'@type' => 'ListItem',
'position' => (int)($intIdx + 1),
'name' => $strTitle,
'item' => $strUrl,
];
}
{/php}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": {php}echo json_encode($arrBreadcrumbLd, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);{/php}
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "VideoObject",
"name": "{$arrVideo.v_name|raw}",
"description": "{if !empty($arrVideo.v_description)}{$arrVideo.v_description|raw}{else/}暂无简介{/if}",
"thumbnailUrl": "{$arrVideo.v_pic|raw}",
"uploadDate": "{:date('Y-m-d')}",
"url": "https://{$DomainModel->d_domain}{site:vurl v_id="$arrVideo.v_id" v_py="$arrVideo.v_name_en"/}"
{if !empty($arrVideo.v_lang)},{/if}
{if !empty($arrVideo.v_lang)}
"inLanguage": [
{volist name="$arrVideo.v_lang" id="strVideoLang" key="index"}{if $index>1},{/if}"{$strVideoLang|raw}"{/volist}
]
{/if}
{if !empty($arrVideo.v_area)},{/if}
{if !empty($arrVideo.v_area)}
"contentLocation": [
{volist name="$arrVideo.v_area" id="strVideoArea" key="index"}{if $index>1},{/if}{
"@type": "Place",
"name": "{$strVideoArea|raw}"
}{/volist}
]
{/if}
{if !empty($arrVideo.v_director)},{/if}
{if !empty($arrVideo.v_director)}
"director": [
{volist name="$arrVideo.v_director" id="strVideoDirector" key="index"}{if $index>1},{/if}{
"@type": "Person",
"name": "{$strVideoDirector|raw}"
}{/volist}
]
{/if}
{if !empty($arrVideo.v_actor)},{/if}
{if !empty($arrVideo.v_actor)}
"actor": [
{volist name="$arrVideo.v_actor" id="strVideoActor" key="index"}{if $index>1},{/if}{
"@type": "Person",
"name": "{$strVideoActor|raw}"
}{/volist}
]
{/if}
{if !empty($arrVideo.v_score) && floatval($arrVideo.v_score)>0},{/if}
{if !empty($arrVideo.v_score) && floatval($arrVideo.v_score)>0}
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "{$arrVideo.v_score|raw}",
"ratingCount": 1
}
{/if},
"publisher": {
"@type": "Organization",
"name": "{$DomainModel->d_name|raw}"
}
}
</script>
{/block}
{block name="strPageCode"}<?php $strPageCode = 'player'; ?>{/block}
{block name="head-css"}
<link rel="stylesheet" href="/public/video/DPlayer.min.css">
{/block}
{block name="main"}
{assign name="pageCfg" value="$TpStyle.template_cfg.pages.play"}
{include file="module/page/page_router" /}
<script>
const strMaxPlayHeight = '480px'
const strVideoId = `{$arrVideo.v_id}`;
@@ -59,16 +203,12 @@
var arrPlayUrl = {$arrVideo.v_play_url|json_encode|raw} ;
var strPlayUrl = ""
var boolIsPlayPage = true
</script>
{/block}
{block name="footer-js"}
<!-- <script src="https://cdn.staticfile.org/jquery/3.7.1/jquery.min.js"></script> -->
<script src="/public/jquery/jquery-3.7.1.min.js" type="module" charset="utf-8"></script>
<script src="https://cdn.staticfile.org/jquery/3.7.1/jquery.min.js"></script>
<script type="text/javascript" src="/public/video/hls.min.js" ></script>
<script type="text/javascript" src="/public/video/DPlayer.min.js" ></script>
<script type="text/javascript" src="/static/js/player/dplayer.init.js" ></script>
{/block}

View File

@@ -47,8 +47,8 @@ class ConverterMovel
'{strVideoDescription}' => '',
'{intVideoPlaySort}' => '1',
'{intPlayIndex}' => '1',
];
static public $arrDescription = [
@@ -137,7 +137,40 @@ class ConverterMovel
static public function convert(string $strSubject): string
{
$strSubject = str_replace(array_keys(self::$arrMap), array_values(self::$arrMap), $strSubject);
return str_replace(array_keys(self::$arrMap), array_values(self::$arrMap), $strSubject);
$strSubject = str_replace(array_keys(self::$arrMap), array_values(self::$arrMap), $strSubject);
return self::sanitizeMetaString($strSubject);
}
/**
* 清理 meta 类字符串:
* - 去掉换行 / 制表
* - 收敛连续分隔符(,, ||
* - 去掉分隔符两侧多余空格
* - 清理首尾分隔符
*/
static private function sanitizeMetaString(string $strSubject): string
{
// 1) 去掉换行与不可见空白(避免 meta content 出现折行)
$strSubject = str_replace(["\r\n", "\n", "\r", "\t"], ' ', $strSubject);
// 2) 收敛多空格
$strSubject = preg_replace('/\s{2,}/u', ' ', $strSubject) ?? $strSubject;
// 3) 清理分隔符两侧空格(只处理常见分隔符:英文逗号/中文逗号/竖线)
$strSubject = preg_replace('/\s*([,|])\s*/u', '$1', $strSubject) ?? $strSubject;
// 4) 收敛连续分隔符:",," "" "||" 以及 ",,," 这种
$strSubject = preg_replace('/([,|])(?:\1)+/u', '$1', $strSubject) ?? $strSubject;
// 5) 处理类似 ",,"(中间夹空格)的情况:", ,"
$strSubject = preg_replace('/([,|])(?:\s*\1)+/u', '$1', $strSubject) ?? $strSubject;
// 6) 去掉首尾分隔符与多余空格
$strSubject = trim($strSubject);
$strSubject = trim($strSubject, ",| ");
return $strSubject;
}
}

View File

@@ -14,6 +14,13 @@ use app\model\NovelClicksModel;
use app\model\NovelModel;
use app\common\helper\SiteStyle;
use app\common\helper\CssBuilder;
use app\common\helper\JsBuilder;
use app\common\helper\UrlBuilder;
use app\common\seo\SeoRenderer;
use app\common\CommentPool;
use app\common\PinlunVariant;
use think\facade\Request;
use think\facade\Config;
use think\exception\HttpException;
@@ -65,6 +72,18 @@ class SiteContext
*/
public $NovelClicksModel;
/**
* TpStyle
*
*/
public $TpStyle;
/**
* UrlBuilder
*
*/
public $UrlBuilder;
public function __construct()
{
$this->Request = request();
@@ -84,6 +103,9 @@ class SiteContext
$this->DomainModel = DomainModel::getDomainOnCacheByDomain($strDomain);
$this->TpStyle = SiteStyle::getConfig();
$this->UrlBuilder = new UrlBuilder($this->TpStyle);
if (empty($this->DomainModel)) {
throw new HttpException(404, 'Site config not Found');
}
@@ -142,12 +164,20 @@ class SiteContext
View::assign("strBookShelfUrlTemp", $strBookShelfUrlTemp);
View::assign("strUserUrlTemp", $strUserUrlTemp);
} else {
// $strPcUrlTemp = $this->DomainModel->getFomartSubject('VIDEO_PC_PATH_URL', '', false);
$strRankUrlTemp = $this->DomainModel->getFomartSubject('VIDEO_RANK_INDEX_URL', '', false);
$strSearchListUrlTemp = $this->DomainModel->getFomartSubject('VIDEO_SEARCH_LIST_URL', '', false);
$strHistoryUrlTemp = $this->DomainModel->getFomartSubject('VIDEO_HISTORY_LIST_URL', '', false);
$strYouQingLiangJieTemp = $this->DomainModel->getFomartSubject('YOUQING_LIANJIE', '', false);
View::assign("strPcPath", '');
if ($this->TemplatesModel['t_code'] == 'videoGpt1') {
$strRankUrlTemp = $this->UrlBuilder->rankIndex();
$strSearchListUrlTemp = $this->UrlBuilder->searchEntry();
$strHistoryUrlTemp = $this->UrlBuilder->history();
} else {
$strRankUrlTemp = $this->DomainModel->getFomartSubject('VIDEO_RANK_INDEX_URL', '', false);
$strSearchListUrlTemp = $this->DomainModel->getFomartSubject('VIDEO_SEARCH_LIST_URL', '', false);
$strHistoryUrlTemp = $this->DomainModel->getFomartSubject('VIDEO_HISTORY_LIST_URL', '', false);
}
View::assign("strRankUrlTemp", $strRankUrlTemp);
View::assign("strSearchListUrlTemp", $strSearchListUrlTemp);
View::assign("strHistoryUrlTemp", $strHistoryUrlTemp);
@@ -155,33 +185,34 @@ class SiteContext
}
// 视频站点需要信息
// $strVideoCategoryIndexUrlTemp = $this->DomainModel->getFomartSubject('VIDEO_CATEGORY_INDEX_URL', '', false);
// $strVideoSearchListUrlTemp = $this->DomainModel->getFomartSubject('VIDEO_SEARCH_LIST_URL', '', false);
// $strVideoHistoryUrlTemp = $this->DomainModel->getFomartSubject('VIDEO_HISTORY_LIST_URL', '', false);
// View::assign("strVideoCategoryIndexUrlTemp", $strVideoCategoryIndexUrlTemp);
// View::assign("strVideoSearchListUrlTemp", $strVideoSearchListUrlTemp);
// View::assign("strVideoHistoryUrlTemp", $strVideoHistoryUrlTemp);
// var_dump($this->DomainModel->t_cfg);
$strEmail = SystemConfigModel::getValByCode('YOU_XIANG');
// 1. 站点 DNA
$TpStyle = SiteStyle::getConfig();
$TpStyle = $this->TpStyle;
// 3. 构建本域名 CSS合并并替换 __PFX__
$cssUrl = CssBuilder::build(
$strCssUrl = CssBuilder::build(
$TpStyle['css_files'],
$TpStyle['dom_prefix'],
$TpStyle['static_hash']
);
$strJsUrl = JsBuilder::build(
$TpStyle['js_files'] ?? [],
(string)$TpStyle['dom_prefix'],
(string)$TpStyle['static_hash']
);
// 4. 模板变量注入
View::assign('TpStyle', $TpStyle);
View::assign("TpTpl", $TpStyle['templates']);
View::assign('TpCss', $cssUrl);
View::assign('strTpCss', $strCssUrl);
View::assign('strTpJs', $strJsUrl);
View::assign('strEmail', $strEmail);
$vod_list = $this->DomainModel;
View::assign('vod_list',$vod_list);
// View::assign('Url', new UrlBuilder($TpStyle));
$vod_list = $this->DomainModel;
View::assign('vod_list', $vod_list);
View::assign('Request', $this->Request);
View::assign('DomainModel', $this->DomainModel);
@@ -702,4 +733,75 @@ class SiteContext
return $this->Request->ip(); // 备用
}
/**
* SEO 输出统一入口(给模板标签用)
*
* @param string $strCode title | keywords | description
* @return string
*/
public function getSeoTkd(string $strCode, string $strPage): string
{
// TpStyle 已在 initCfg() 中注入
$TpStyle = $this->TpStyle;
if (empty($TpStyle)) {
return '';
}
// 1⃣ 选 SEO 模板
$renderer = new SeoRenderer($TpStyle);
$tpl = $renderer->getTemplate($strCode, $strPage);
if ($tpl === '') {
return '';
}
// var_dump($tpl);
// 2⃣ 统一走 Converter你现有系统
return ConverterMovel::convert($tpl);
}
public function getTemplate(): string
{
$strDomain = $this->Request->rootDomain();
$this->DomainModel = DomainModel::getDomainOnCacheByDomain($strDomain);
if (empty($this->DomainModel)) {
throw new HttpException(404, 'Site config not Found');
}
$this->TemplatesModel = TemplatesModel::getTemplateOnCacheByTId($this->DomainModel->t_id);
if (empty($this->TemplatesModel)) {
throw new HttpException(500, 'Site template not Found');
}
return $this->TemplatesModel['t_code'];
}
public function getPinlunData(int $intVideoId): array
{
$strDomain = $this->DomainModel->d_domain ?? request()->domain();
// 兜底:如果上下文没有 vo至少保证有 v_id占位符会降级
if (empty($vo) || intval($vo['v_id'] ?? 0) !== $intVideoId) {
$vo = ['v_id' => $intVideoId];
}
// // 冻结 cfg你也可以改成 domainSeed / pageSeed这里用你现有 seed
$arrPinlunCfg = $this->TpStyle['template_cfg']['pages']['detail']['pinlun'];
$arrPinlun = CommentPool::build(
$strDomain,
$intVideoId,
$arrPinlunCfg,
[
'v_name' => ConverterMovel::getVal('strVideoName') ?? '',
'v_actor' => ConverterMovel::getVal('strVideoActor') ?? [],
'v_director' => ConverterMovel::getVal('strVideoDirector') ?? [],
]
);
return [
'arrPinlun' => $arrPinlun,
];
}
}

View File

@@ -334,7 +334,7 @@ class StaticConfig
}
/**
* getNovelCategoryFilter
* 获取所有分类 一维数组1级+2级
*
* @return array
*/
@@ -344,7 +344,7 @@ class StaticConfig
}
/**
* getVideoCategoryTypeFilter
* 获取自定义所有分类 二维数组1级>2级
*
* @return array
*/
@@ -352,4 +352,5 @@ class StaticConfig
{
return VideoCategoryModel::getCustomCategory($strType);
}
}

View File

@@ -11,6 +11,9 @@ use app\model\VideoClicksModel;
use app\model\VideoModel;
use template\page\CusteomPage02;
use think\exception\HttpException;
use app\common\helper\SiteStyle;
use app\common\helper\UrlBuilder;
class VideoService
{
@@ -50,13 +53,19 @@ class VideoService
*/
public function getVideoCategoryIndexUrl(string $strParentCategory): string
{
$strKey = 'VIDEO_CATEGORY_INDEX_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'strParentCategory' => !empty($strParentCategory) ? $strParentCategory : '',
]);
$strUrl = (string)($strUrl ?? '');
$strUrl = preg_replace('#/{2,}#', '/', $strUrl);
return (string)$strUrl;
$strTmpCode = $this->SiteContext->TemplatesModel['t_code'];
if ($strTmpCode == 'videoGpt1') {
return $this->SiteContext->UrlBuilder->categoryParent($strParentCategory);
} else {
$strKey = 'VIDEO_CATEGORY_INDEX_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'strParentCategory' => !empty($strParentCategory) ? $strParentCategory : '',
]);
$strUrl = (string)($strUrl ?? '');
$strUrl = preg_replace('#/{2,}#', '/', $strUrl);
return (string)$strUrl;
}
}
@@ -70,31 +79,43 @@ class VideoService
*/
public function getVideoInfoUrl(int $intVId, string $strPinYin): string
{
$strKey = 'VIDEO_INFO_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'intVId' => $intVId,
'strPinYin' => $strPinYin
]);
return (string)$strUrl;
$strTmpCode = $this->SiteContext->TemplatesModel['t_code'];
if ($strTmpCode == 'videoGpt1') {
return $this->SiteContext->UrlBuilder->detail($strPinYin, $intVId);
} else {
$strKey = 'VIDEO_INFO_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'intVId' => $intVId,
'strPinYin' => $strPinYin
]);
return (string)$strUrl;
}
}
/**
* 伪造视频
*
* @param integer $intVId
* @param string $intPinYin
* @param string $strPinYin
* @param integer $intVForgeId
* @return string
*/
public function getForgeVideoInfoUrl(int $intVId, string $intPinYin, int $intVForgeId): string
public function getForgeVideoInfoUrl(int $intVId, string $strPinYin, int $intVForgeId): string
{
$strKey = 'FORGE_VIDEO_INFO_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'intVId' => $intVId,
'strPinYin' => $intPinYin,
'intVForgeId' => $intVForgeId,
]);
return (string)$strUrl;
$strTmpCode = $this->SiteContext->TemplatesModel['t_code'];
if ($strTmpCode == 'videoGpt1') {
return $this->SiteContext->UrlBuilder->detailForge($strPinYin, $intVId, $intVForgeId);
} else {
$strKey = 'FORGE_VIDEO_INFO_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'intVId' => $intVId,
'strPinYin' => $strPinYin,
'intVForgeId' => $intVForgeId,
]);
return (string)$strUrl;
}
}
/**
@@ -108,14 +129,20 @@ class VideoService
*/
public function getVideoPlayUrl(int $intVId, string $strPinYin, string $strPlayType, int $intPlayIndex): string
{
$strKey = 'VIDEO_PLAY_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'intVId' => $intVId,
'strPinYin' => $strPinYin,
'strPlayType' => $strPlayType,
'intPlayIndex' => $intPlayIndex,
]);
return (string)$strUrl;
$strTmpCode = $this->SiteContext->TemplatesModel['t_code'];
if ($strTmpCode == 'videoGpt1') {
return $this->SiteContext->UrlBuilder->play($strPinYin, $intVId, $strPlayType, $intPlayIndex);
} else {
$strKey = 'VIDEO_PLAY_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'intVId' => $intVId,
'strPinYin' => $strPinYin,
'strPlayType' => $strPlayType,
'intPlayIndex' => $intPlayIndex,
]);
return (string)$strUrl;
}
}
@@ -133,19 +160,25 @@ class VideoService
*/
public function getVideoCategoryUrl(string|NULL $strCategory, string|NULL $strParentCategory, string|NULL $strArea, int|string|NULL $strLang, int|string|NULL $strYear, int|string|NULL $strOrder, int|string|NULL $intPage): string
{
$strKey = 'VIDEO_CATEGORY_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'strCategory' => !empty($strCategory) ? $strCategory : 'all',
'strParentCategory' => !empty($strParentCategory) ? $strParentCategory : 'all',
'strArea' => !empty($strCategory) ? $strArea : 'all',
'strLang' => !empty($strCategory) ? $strLang : 'all',
'strYear' => !empty($strCategory) ? $strYear : 'all',
'strOrder' => !empty($strOrder) ? $strOrder : 'all',
'intPage' => $intPage ?? 1,
]);
$strUrl = (string)($strUrl ?? '');
$strUrl = preg_replace('#/{2,}#', '/', $strUrl);
return (string)$strUrl;
$strTmpCode = $this->SiteContext->TemplatesModel['t_code'];
if ($strTmpCode == 'videoGpt1') {
return $this->SiteContext->UrlBuilder->categoryChild($strParentCategory, $strCategory, $intPage);
} else {
$strKey = 'VIDEO_CATEGORY_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'strCategory' => !empty($strCategory) ? $strCategory : 'all',
'strParentCategory' => !empty($strParentCategory) ? $strParentCategory : 'all',
'strArea' => !empty($strCategory) ? $strArea : 'all',
'strLang' => !empty($strCategory) ? $strLang : 'all',
'strYear' => !empty($strCategory) ? $strYear : 'all',
'strOrder' => !empty($strOrder) ? $strOrder : 'all',
'intPage' => $intPage ?? 1,
]);
$strUrl = (string)($strUrl ?? '');
$strUrl = preg_replace('#/{2,}#', '/', $strUrl);
return (string)$strUrl;
}
}
/**
@@ -159,17 +192,22 @@ class VideoService
*/
public function getVideoRankUrl(string $strCategory, string $strParentCategory, string $strSortType, int $intPage): string
{
$strTmpCode = $this->SiteContext->TemplatesModel['t_code'];
$strKey = 'VIDEO_RANK_LIST_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'strCategory' => !empty($strCategory) ? $strCategory : 'all',
'strParentCategory' => !empty($strParentCategory) ? $strParentCategory : 'all',
'strSortType' => !empty($strSortType) ? $strSortType : 'all',
'intPage' => $intPage ?? 1,
]);
$strUrl = (string)($strUrl ?? '');
$strUrl = preg_replace('#/{2,}#', '/', $strUrl);
return (string)$strUrl;
if ($strTmpCode == 'videoGpt1') {
return $this->SiteContext->UrlBuilder->rankList($strSortType);
} else {
$strKey = 'VIDEO_RANK_LIST_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'strCategory' => !empty($strCategory) ? $strCategory : 'all',
'strParentCategory' => !empty($strParentCategory) ? $strParentCategory : 'all',
'strSortType' => !empty($strSortType) ? $strSortType : 'all',
'intPage' => $intPage ?? 1,
]);
$strUrl = (string)($strUrl ?? '');
$strUrl = preg_replace('#/{2,}#', '/', $strUrl);
return (string)$strUrl;
}
}
@@ -203,12 +241,18 @@ class VideoService
*/
public function getVideoSearchUrl($strKeyWords, $intPage = 1): string
{
$strKey = 'VIDEO_SEARCH_LIST_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'intPage' => $intPage,
'strSearchKeywords' => $strKeyWords
]);
return (string)$strUrl;
$strTmpCode = $this->SiteContext->TemplatesModel['t_code'];
if ($strTmpCode == 'videoGpt1') {
return $this->SiteContext->UrlBuilder->searchResult($strKeyWords);
} else {
$strKey = 'VIDEO_SEARCH_LIST_URL';
$strUrl = $this->SiteContext->DomainModel->getFomartUrl($strKey, [
'intPage' => $intPage,
'strSearchKeywords' => $strKeyWords
]);
return (string)$strUrl;
}
}
/**
@@ -608,6 +652,8 @@ class VideoService
}
// 更新值
$arrAllVideoClass = StaticConfig::getVideoCategoryFilter();
$strNCategory = $arrAllVideoClass[$strVCategoryEn];
ConverterMovel::setVal([
'intPage' => $intPage,
@@ -746,4 +792,137 @@ class VideoService
return $arrVideo;
}
/**
* 获取 播放线路-中文
*
* @param string $strCode
* @return string
*/
public function getConverterPlayLineVal(string $strCode): string
{
$strCode = strtolower(trim((string)$strCode));
if ($strCode === '') {
return '默认';
}
// 线路映射(可持续扩展)
$arrMap = [
'maotai' => '茅台',
'douban' => '豆瓣',
'youzhi' => '优质',
'default' => '默认',
'vip' => 'VIP线路',
];
if (isset($arrMap[$strCode])) {
return $arrMap[$strCode];
}
// 标准化(去空格)
$strNorm = preg_replace('/\s+/', '', $strCode);
if ($strNorm === '') {
return '默认';
}
// yun-2 / yun_2
if (preg_match('/^([a-z]+)[\-_](\d+)$/', $strNorm, $arrMatch)) {
$strPrefix = $arrMatch[1];
$intNum = (int)$arrMatch[2];
$strPrefixName = $arrMap[$strPrefix] ?? strtoupper($strPrefix);
return $strPrefixName . ' ' . $intNum;
}
// yun3 / vip2
if (preg_match('/^([a-z]+)(\d+)$/', $strNorm, $arrMatch)) {
$strPrefix = $arrMatch[1];
$intNum = (int)$arrMatch[2];
$strPrefixName = $arrMap[$strPrefix] ?? strtoupper($strPrefix);
return $strPrefixName . ' ' . $intNum;
}
// 未命中变得更可读abc-def → Abc Def
$strHuman = preg_replace('/[\-_]+/', ' ', $strNorm);
$strHuman = trim((string)$strHuman);
if ($strHuman !== '') {
return ucwords($strHuman);
}
return '默认';
}
/**
* 获取图片 alt稳定、域名级差异、同片稳定
*
* @param array $arrTpStyle
* @param array|object $arrVideo 支持 array / BSONDocument
* @param string $strSlotType detail_cover | list_poster ...
* @param string $strItemType poster | media | rank ...
* @return string
*/
public function getVideoImgAlt(array $arrTpStyle, $arrVideo, string $strSlotType = 'list_poster', string $strItemType = 'poster'): string
{
$arrVideo = $this->toArraySafe($arrVideo);
return SiteStyle::buildImgAlt($arrTpStyle, $arrVideo, $strSlotType, $strItemType);
}
/**
* 获取详情页“防薄内容”模块数据(稳定、域名级差异、同片稳定)
*
* @param array $arrTpStyle
* @param array $arrVideo
* @return array
*/
public function getVideoDetailSeoAddon(array $arrTpStyle, array $arrVideo): array
{
return SiteStyle::buildDetailSeoAddon($arrTpStyle, $arrVideo);
}
/**
* BSONDocument / 对象 / array 统一转数组(递归)
*/
private function toArraySafe($mixVal): array
{
if (is_array($mixVal)) return $mixVal;
// MongoDB BSONDocument / BSONArray 通常实现了 getArrayCopy 或 jsonSerialize
if (is_object($mixVal)) {
if (method_exists($mixVal, 'getArrayCopy')) {
return $this->toArrayDeep($mixVal->getArrayCopy());
}
if ($mixVal instanceof \JsonSerializable) {
$tmp = $mixVal->jsonSerialize();
return $this->toArrayDeep(is_array($tmp) ? $tmp : (array)$tmp);
}
return $this->toArrayDeep((array)$mixVal);
}
return [];
}
private function toArrayDeep($mixVal)
{
if (!is_array($mixVal)) return $mixVal;
foreach ($mixVal as $k => $v) {
if (is_object($v)) {
if (method_exists($v, 'getArrayCopy')) {
$mixVal[$k] = $this->toArrayDeep($v->getArrayCopy());
} elseif ($v instanceof \JsonSerializable) {
$tmp = $v->jsonSerialize();
$mixVal[$k] = $this->toArrayDeep(is_array($tmp) ? $tmp : (array)$tmp);
} else {
$mixVal[$k] = $this->toArrayDeep((array)$v);
}
} elseif (is_array($v)) {
$mixVal[$k] = $this->toArrayDeep($v);
}
}
return $mixVal;
}
}

View File

@@ -10,6 +10,8 @@ use app\model\VideoCategoryModel;
use app\services\StaticConfig;
use microserver\ProcessSanitizer;
use microserver\QueueManage;
use app\model\TemplatesModel;
use app\common\helper\SiteStyle;
class VideoSiteMapLogic
{
@@ -159,6 +161,19 @@ class VideoSiteMapLogic
mkdir($strDomainDir);
}
// 通过域名获取对应的模板
// $TemplatesModel = TemplatesModel::getTemplateOnCacheByTId($DomainModel->t_id);
// if (empty($TemplatesModel)) {
// $TemplatesModel = 'videoGpt1';
// }
// // 判断如果是gpt 模板 则 先获取当前域名的 siteStyle方便下面拿 url模板
// if ($TemplatesModel == 'videoGpt1') {
// $arrTpStyle = SiteStyle::getConfig($DomainModel->d_domain);
// $arrUrlFamily = $arrTpStyle['template_cfg']['url_family'];
// }
$arrUrlFamily = $this->getGptArrUrlTmp($DomainModel);
$strHead = <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
@@ -195,7 +210,13 @@ EOF;
'strPinYin' => $Video->v_name_en,
];
$strUri = $DomainModel->getFomartUrlEx($strKey, $strDomain, $strController, $strAction, $arrArgs);
if ($arrUrlFamily && !empty($arrUrlFamily)) {
$strPattern = $arrUrlFamily['detail']['pattern'];
$strUri = buildUrlFromPattern($strPattern, $arrArgs);
} else {
$strUri = $DomainModel->getFomartUrlEx($strKey, $strDomain, $strController, $strAction, $arrArgs);
}
$strUrl = sprintf("https://www.%s%s", $DomainModel->d_domain, $strUri);
$strPriority = '0.8';
$strContent = sprintf($strTemplate, $strUrl, $strPriority);
@@ -266,10 +287,17 @@ EOF;
if (is_dir($strDomainDir) == false) {
mkdir($strDomainDir);
}
$strMapIndexFile = $strDomainDir . '/sitemap-main.xml';
$strRankIndexUri = $DomainModel->getFomartUrlEx("VIDEO_RANK_INDEX_URL", $DomainModel->d_domain, "", "", []);
$arrUrlFamily = $this->getGptArrUrlTmp($DomainModel);
if ($arrUrlFamily && !empty($arrUrlFamily)) {
$strPattern = $arrUrlFamily['rank_index']['pattern'];
$strRankIndexUri = buildUrlFromPattern($strPattern, []);
} else {
$strRankIndexUri = $DomainModel->getFomartUrlEx("VIDEO_RANK_INDEX_URL", $DomainModel->d_domain, "", "", []);
}
$strRankIndexUrl = sprintf("https://www.%s%s", $DomainModel->d_domain, $strRankIndexUri);
$strContent = <<<EOF
@@ -299,9 +327,16 @@ EOF;
$strAction = "";
$arrArgs = [
'strParentCategory' => $arrParentCategory['v_category_en'],
'intParentId' => $arrParentCategory['v_category_en'],
];
$strUri = $DomainModel->getFomartUrlEx($strKey, $strDomain, $strController, $strAction, $arrArgs);
if ($arrUrlFamily && !empty($arrUrlFamily)) {
$strPattern = $arrUrlFamily['category_parent']['pattern'];
$strUri = buildUrlFromPattern($strPattern, $arrArgs);
} else {
$strUri = $DomainModel->getFomartUrlEx($strKey, $strDomain, $strController, $strAction, $arrArgs);
}
$strUrl = sprintf("https://www.%s%s", $DomainModel->d_domain, $strUri);
@@ -331,15 +366,22 @@ EOF;
$strAction = "";
$arrArgs = [
'strParentCategory' => $arrParentCategory['v_category_en'],
'intParentId' => $arrParentCategory['v_category_en'],
'strCategory' => $arrChildrenCategory['v_category_en'],
'intCategoryId' => $arrChildrenCategory['v_category_en'],
'strYear' => 'all',
'strArea' => 'all',
'strOrder' => $strSortKey,
'strLang' => 'all',
'intPage' => 1,
];
if ($arrUrlFamily && !empty($arrUrlFamily)) {
$strUri = $DomainModel->getFomartUrlEx($strKey, $strDomain, $strController, $strAction, $arrArgs);
$strPattern = $arrUrlFamily['category_child']['pattern'];
$strUri = buildUrlFromPattern($strPattern, $arrArgs);
} else {
$strUri = $DomainModel->getFomartUrlEx($strKey, $strDomain, $strController, $strAction, $arrArgs);
}
$strUrl = sprintf("https://www.%s%s", $DomainModel->d_domain, $strUri);
$strContent = <<<EOF
<url>
@@ -372,7 +414,13 @@ EOF;
'strSortType' => $strSortKey,
];
$strUri = $DomainModel->getFomartUrlEx($strKey, $strDomain, $strController, $strAction, $arrArgs);
if ($arrUrlFamily && !empty($arrUrlFamily)) {
$strPattern = $arrUrlFamily['rank_list']['pattern'];
$strUri = buildUrlFromPattern($strPattern, $arrArgs);
} else {
$strUri = $DomainModel->getFomartUrlEx($strKey, $strDomain, $strController, $strAction, $arrArgs);
}
$strUrl = sprintf("https://www.%s%s", $DomainModel->d_domain, $strUri);
@@ -489,6 +537,8 @@ EOF;
foreach ($this->getDomain() as $DomainModel) {
$arrUrlFamily = $this->getGptArrUrlTmp($DomainModel);
$strDomainDir = rtrim($this->strSiteMapPath, '/') . '/' . $DomainModel->d_domain;
if (!is_dir($strDomainDir)) {
@@ -510,17 +560,23 @@ EOF;
$isFirst = true;
foreach ($this->fetchVideosByBatch($intStart, $this->intPageSize) as $Video) {
$arrArgs = [
'intVId' => $Video->v_id,
'strPinYin' => $Video->v_name_en,
];
if ($arrUrlFamily && !empty($arrUrlFamily)) {
$strUri = $DomainModel->getFomartUrlEx(
"VIDEO_INFO_URL",
$DomainModel->d_domain,
'',
'',
[
'intVId' => $Video->v_id,
'strPinYin' => $Video->v_name_en,
]
);
$strPattern = $arrUrlFamily['detail']['pattern'];
$strUri = buildUrlFromPattern($strPattern, $arrArgs);
} else {
$strUri = $DomainModel->getFomartUrlEx(
"VIDEO_INFO_URL",
$DomainModel->d_domain,
'',
'',
$arrArgs
);
}
$fullUrl = 'https://www.' . $DomainModel->d_domain . $strUri;
@@ -572,4 +628,29 @@ EOF;
echo "[JSON] done {$finalFile}\n";
}
}
/**
* Undocumented function
*
* @param [type] $DomainModel
* @return void
*/
public function getGptArrUrlTmp($DomainModel)
{
// 通过域名获取对应的模板
$arrUrlFamily = [];
$TemplatesModel = TemplatesModel::getTemplateOnCacheByTId($DomainModel->t_id);
if (empty($TemplatesModel)) {
$TemplatesModel = 'videoGpt1';
}
// 判断如果是gpt 模板 则 先获取当前域名的 siteStyle方便下面拿 url模板
if ($TemplatesModel->t_code == 'videoGpt1') {
$arrTpStyle = SiteStyle::getConfig(null, $DomainModel->d_domain);
$arrUrlFamily = $arrTpStyle['template_cfg']['url_family'];
}
return $arrUrlFamily;
}
}