Merge branch 'dev' of ssh://git.bgbg.live:18150/root/SEONexus into dev

This commit is contained in:
Default
2025-04-22 17:43:56 +08:00
67 changed files with 2328 additions and 947 deletions

View File

@@ -13,6 +13,49 @@ Route::get('/article/fenlei/:category', function (\think\Request $Request, SiteC
return view('test/test01/index.html');
});
/**
* Sitemap
*/
Route::get('/robots', function (\think\Request $Request, SiteContext $SiteContext) {
return view('sitemap/robots.txt');
})->ext('txt');
/**
* Sitemap 索引文件
*/
Route::get('/sitemap_index', function (\think\Request $Request, SiteContext $SiteContext) {
return view('sitemap/sitemap_index.xml');
})->ext('xml');
/**
* 首页、分类列表、排行榜、男生/女生频道。
*/
Route::get('/sitemap-main', function (\think\Request $Request, SiteContext $SiteContext) {
return view('sitemap/sitemap-main.xml');
})->ext('xml');
/**
* 小说目录页面。
*/
Route::get('/sitemap-books-catalog-:page', function (\think\Request $Request, SiteContext $SiteContext) {
return view('sitemap/sitemap-books-catalog.xml');
})->ext('xml');
/**
* 小说详情页面。
*/
Route::get('/sitemap-books-:page', function (\think\Request $Request, SiteContext $SiteContext) {
return view('sitemap/sitemap-books.xml');
})->ext('xml');
/**
* 章节页面(如果包含)
*/
Route::get('/sitemap-chapters-:page', function (\think\Request $Request, SiteContext $SiteContext) {
return view('sitemap/sitemap-chapters.xml');
})->ext('xml');
/**
@@ -59,12 +102,12 @@ $arrRoutes = [
// 伪小说详情相关路径
'kan-novel' => [
'/kan-xiaoshuo/:name-:intNovelId-:n_forge_id',
'/show-novel/:name-:intNovelId-:n_forge_id',
'/seo-book/:name-:intNovelId-:n_forge_id',
'/show-xiaoshuo-:name-:intNovelId-:n_forge_id',
'/see-novel-:name-:intNovelId-:n_forge_id',
'/good-book-:name-:intNovelId-:n_forge_id',
'/kan-xiaoshuo/:name-:intNovelId-:intForgeId',
'/show-novel/:name-:intNovelId-:intForgeId',
'/seo-book/:name-:intNovelId-:intForgeId',
'/show-xiaoshuo-:name-:intNovelId-:intForgeId',
'/see-novel-:name-:intNovelId-:intForgeId',
'/good-book-:name-:intNovelId-:intForgeId',
],
// 小说详情相关路径
@@ -85,7 +128,6 @@ $arrRoutes = [
* 完整路由
* 使用: {site:nflurl gender="$strGender" category="$CategoryPinyin" status="all" order="all" page="1"/}
*/
// '/shuku/:strGender?/:strCategory?/:strStatus?/:strOrder?/page:intPage?',
'/shuku/:strGender/:strCategory/:strStatus/:strOrder/page:intPage',
'/books/:strGender/:strCategory/:strStatus/:strOrder/page:intPage',
'/library/:strGender/:strCategory/:strStatus/:strOrder/page:intPage',
@@ -175,6 +217,27 @@ $arrRoutes = [
'/class/index',
'/category/index',
],
// 排行榜列表url
'rank-info' => [
/**
* /paihang/nansheng-xiaoshuo/all/all/all/page1
* 使用: {site:nflurl gender="$strGender" category="$CategoryPinyin" status="all" order="all" page="1"/}
*/
'/paihang/:strGender/:strCategory/:strStatus/:strOrder/page:intPage',
'/rank/:strGender/:strCategory/:strStatus/:strOrder/page:intPage',
'/top/:strGender/:strCategory/:strStatus/:strOrder/page:intPage',
'/ranks/:strGender/:strCategory/:strStatus/:strOrder/page:intPage',
'/phb/:strGender/:strCategory/:strStatus/:strOrder/page:intPage',
'/paihangbang/:strGender/:strCategory/:strStatus/:strOrder/page:intPage',
'/paihang/:strCategory/:strStatus/:strOrder/page:intPage',
'/rank/:strCategory/:strStatus/:strOrder/page:intPage',
'/top/:strCategory/:strStatus/:strOrder/page:intPage',
'/ranks/:strCategory/:strStatus/:strOrder/page:intPage',
'/phb/:strCategory/:strStatus/:strOrder/page:intPage',
'/paihangbang/:strCategory/:strStatus/:strOrder/page:intPage',
],
//排行榜
'rank' => ['/paihang/all', '/rank/all', '/paihang-quan', '/top/all', '/paihang-bang', '/ranks/all'],
// 男生
@@ -211,9 +274,9 @@ foreach ($arrRoutes['prefixes'] as $platform => $prefixes) {
switch ($key) {
case 'latest':
//最新章节
$strView = 'pc/getNovelCatalog.html';
$strView = 'pc/getNovelChapter.html';
if ($platform == 'h5') {
$strView = 'novel/getNovelCatalog.html';
$strView = 'novel/getNovelChapter.html';
}
Route::get($strRoute, function () use ($strView) {
return view($strView);
@@ -242,7 +305,7 @@ foreach ($arrRoutes['prefixes'] as $platform => $prefixes) {
Route::get($strRoute, function () use ($strView) {
return view($strView);
})
->pattern(['intNovelId' => '\d+', 'n_forge_id' => '\d+', 'name' => '[\w-]+',]);
->pattern(['intNovelId' => '\d+', 'intForgeId' => '\d+', 'name' => '[\w-]+',]);
break;
case 'novel':
@@ -284,8 +347,7 @@ foreach ($arrRoutes['prefixes'] as $platform => $prefixes) {
'strStatus' => '(all|lianzai|wanjie)?', // 允许空值
'strOrder' => '[a-z\-]*', // 允许空值
'intPage' => '\d*', // 允许空值
// 'strCategory' => 'all|xuanhuan-xiuzhen|junshi-xiaoshuo|wangyou-xiaoshuo|kehuan-xiaoshuo|zhongsheng-chuanyue|dushi-xiaoshuo|lingyi-xiaoshuo|yanqing-xiaoshuo|qita-xiaoshuo',
// 'strCategory' => 'all|xuanhuan-xiuzhen|junshi-xiaoshuo|wangyou-xiaoshuo|kehuan-xiaoshuo|hongsheng-chuanyue|dushi-xiaoshuo|lingyi-xiaoshuo|yanqing-xiaoshuo|qita-xiaoshuo',
]);
break;
@@ -311,7 +373,24 @@ foreach ($arrRoutes['prefixes'] as $platform => $prefixes) {
return view($strView);
});
break;
case 'rank-info':
//排行榜
$strView = 'pc/getNovelRank.html';
if ($platform == 'h5') {
$strView = 'novel/getNovelRank.html';
}
Route::get($strRoute, function () use ($strView) {
return view($strView);
})->pattern([
'strGender' => '[a-z\-]*', // 允许空值
'strCategory' => '[a-z\-]*', // 允许空值
'strStatus' => '(all|lianzai|wanjie)?', // 允许空值
'strOrder' => '[a-z\-]*', // 允许空值
'intPage' => '\d*', // 允许空值
]);
break;
case 'boys':
//男生
$strView = 'pc/getNovelChannel.html';

View File

@@ -1,5 +1,17 @@
{extend name="baseH5" /}
{block name="get-data"}
{novel:pagerexp page="$Request.get.page" limit="30"
n_category="$Request.route.strCategory"
sort_type="$Request.route.strOrder"
n_status="$Request.route.strStatus" d_key="d_key"
d_key="d_key"
d_val="Novel" n_num="total"
button_num="5" cache_life="86400" func="generateCategoryPager" export_name="resData" /}
{site:grm page_code="h5_novel_library" diff="$resData.p_data.page" num="40" g_key="arrGrm" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETLIBRARY@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETLIBRARY@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETLIBRARY@DESCRIPTION"}{/block}
@@ -48,7 +60,7 @@
{block name="logo-html"}
<h1 class="bookname">
<a href="/"
style="color:#ffffff">{$DomainModel->d_name}</a>-{$Request.route.strCategory}{$Request.route.strOrder}{$Request.route.strStatus}免费阅读
style="color:#ffffff">{$DomainModel->d_name}</a>-{site:getval code="strNovelCategoryName" /}{site:getval code="strNovelOrder" /}{site:getval code="strNovelStatus" /}免费阅读
</h1>
{/block}
@@ -56,15 +68,6 @@
{block name="main"}
{novel:pagerexp page="$Request.get.page" limit="30"
n_category="$Request.route.strCategory"
sort_type="$Request.route.strOrder"
n_status="$Request.route.strStatus" d_key="d_key"
d_key="d_key"
d_val="Novel" n_num="total"
button_num="5" cache_life="86400" func="generateCategoryPager" export_name="resData" /}
{site:grm page_code="h5_novel_library" diff="$resData.p_data.page" num="40" g_key="arrGrm" /}
<p class="site-description">{$strDescription??''}</p>

View File

@@ -1,6 +1,7 @@
{extend name="baseH5" /}
{block name="get-data"}
{site:grm page_code="h5_novel_chapter" diff="$Request.url" num="20" g_key="arrGrm" /}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="0" /}
{chapter:info n_id="$Request.route.intNovelId" c_sort_num="$Request.route.intChapterSort"
@@ -130,7 +131,7 @@ c_page="$Request.route.intChapterPage" c_key="arrChapter" /}
</div>
</div>
<div class="content">
<h1 id="chaptername" class="chaptername">{$arrNovel.n_name}(第{$arrChapter.c_sort_num}页)</h1>
<h2 id="chaptername" class="chaptername">{$arrChapter.c_name}</h2>
<div class="chapter-page-btn">
{$arrGrm[1]|raw}
<ul>

View File

@@ -2,7 +2,7 @@ $Novel.n_id{extend name="baseH5" /}
{block name="get-data"}
{if $Request.route.intNovelId}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="0" /}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="$Request.route.intForgeId" /}
{else}
{novel:info n_id="$DomainModel->info_id" n_key="arrNovel" n_forge_id="0" /}
{/if}

View File

@@ -1,4 +1,15 @@
{extend name="baseH5" /}
{block name="get-data"}
{novel:pagerexp page="$Request.get.page" limit="30"
key="$Request.get.keyword"
d_key="d_key"
d_val="Novel"
p_val="page_data" button_num="10" cache_life="86400" func="generateSearchPager" export_name="resData" /}
{site:grm page_code="h5_novel_search" diff="$Request.url" num="30" g_key="arrGrm" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETSEARCHNOVEL@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETSEARCHNOVEL@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETSEARCHNOVEL@DESCRIPTION"}{/block}
@@ -48,13 +59,7 @@
{block name="main"}
{novel:pagerexp page="$Request.get.page" limit="30"
key="$Request.get.keyword"
d_key="d_key"
d_val="Novel"
p_val="page_data" button_num="10" cache_life="86400" func="generateSearchPager" export_name="resData" /}
{site:grm page_code="h5_novel_search" diff="$Request.url" num="30" g_key="arrGrm" /}
<div class="wrap-box">
<h1><span>{$Request.get.keyword}</span>搜索结果 - {$DomainModel->d_name} 第{$resData.p_data.page}页</h1>

View File

@@ -1,5 +1,16 @@
{extend name="basePc" /}
{block name="get-data"}
{novel:pagerexp page="$Request.get.page" limit="30"
n_category="$Request.route.strCategory"
sort_type="$Request.route.strOrder"
n_status="$Request.route.strStatus" d_key="d_key"
d_key="d_key"
d_val="Novel" n_num="total"
button_num="10" cache_life="86400" func="generateCategoryPager" export_name="resData" /}
{site:grm page_code="pc_novel_library" diff="$resData.p_data.page" num="70" g_key="arrGrm" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETLIBRARY@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETLIBRARY@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETLIBRARY@DESCRIPTION"}{/block}
@@ -58,15 +69,7 @@
{block name="main"}
{novel:pagerexp page="$Request.get.page" limit="30"
n_category="$Request.route.strCategory"
sort_type="$Request.route.strOrder"
n_status="$Request.route.strStatus" d_key="d_key"
d_key="d_key"
d_val="Novel" n_num="total"
button_num="10" cache_life="86400" func="generateCategoryPager" export_name="resData" /}
{site:grm page_code="pc_novel_library" diff="$resData.p_data.page" num="70" g_key="arrGrm" /}
<div class="container">

View File

@@ -1,7 +1,8 @@
{extend name="basePc" /}
{block name="get-data"}
{site:grm page_code="pc_novel_chapter" diff="$Request.url" num="20" g_key="arrGrm" /}
{site:grm page_code="pc_novel_chapter" diff="$Request.url" num="60" g_key="arrGrm" /}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="0" /}
{chapter:info n_id="$Request.route.intNovelId" c_sort_num="$Request.route.intChapterSort"
c_page="$Request.route.intChapterPage" c_key="arrChapter" /}
@@ -92,11 +93,11 @@ c_page="$Request.route.intChapterPage" c_key="arrChapter" /}
<a href="{$strPcPath}/">{$DomainModel->d_name}</a>&gt;<a
href='{$strPcPath}{site:nurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" /}'>{$arrNovel.n_name}</a>
&gt;
{$arrNovel.n_name}(第{$arrChapter.c_sort_num}页)
{$arrChapter.c_name}
</h2>
{$arrGrm[2]|raw}
<div class="word_read">
<h3>{$arrNovel.n_name}{$arrChapter['c_sort_num']}</h3>
<h3>{$arrNovel.n_name}{$arrChapter['c_name']}</h3>
<div class="read_btn">
{if $arrChapter && $arrChapter.c_sort_num && $arrChapter.c_sort_num == 1}
<a id="j_chapterPrev" href="javascript:void(0);">上一页</a>

View File

@@ -2,7 +2,7 @@
{block name="get-data"}
{if $Request.route.intNovelId}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="0" /}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="$Request.route.intForgeId" /}
{else}
{novel:info n_id="$DomainModel->info_id" n_key="arrNovel" n_forge_id="0" /}
{/if}
@@ -164,7 +164,7 @@
<li>
{$arrGrm[$d_key]|raw}
<a
href='{$strPcPath}{site:nurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" /}'>{$Chapter.c_name}</a>
href='{$strPcPath}{site:cpurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" c_sort="$Chapter.c_sort_num" c_page="0"/}'>{$Chapter.c_name}</a>
</li>
{/chapter:list}
</ul>
@@ -174,7 +174,7 @@
<li>
{$arrGrm[$d_key+10]|raw}
<a
href='{$strPcPath}{site:nurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" /}'>{$Chapter.c_name}</a>
href='{$strPcPath}{site:cpurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" c_sort="$Chapter.c_sort_num" c_page="0"/}'>{$Chapter.c_name}</a>
</li>
{/chapter:list}
</ul><a

View File

@@ -1,4 +1,14 @@
{extend name="basePc" /}
{block name="get-data"}
{novel:pagerexp page="$Request.get.page" limit="30"
key="$Request.get.keyword"
d_key="d_key"
d_val="Novel" n_num="total"
p_val="page_data" button_num="10" cache_life="86400" func="generateSearchPager" export_name="resData" /}
{site:grm page_code="pc_novel_search" diff="$Request.url" num="30" g_key="arrGrm" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETSEARCHNOVEL@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETSEARCHNOVEL@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETSEARCHNOVEL@DESCRIPTION"}{/block}
@@ -45,13 +55,7 @@
{block name="main"}
{novel:pagerexp page="$Request.get.page" limit="30"
key="$Request.get.keyword"
d_key="d_key"
d_val="Novel" n_num="total"
p_val="page_data" button_num="10" cache_life="86400" func="generateSearchPager" export_name="resData" /}
{site:grm page_code="pc_novel_search" diff="$Request.url" num="30" g_key="arrGrm" /}
<div class="container">
<div class="row">

View File

@@ -0,0 +1,294 @@
对于一个小说站点(如你提到的包含首页、分类列表、排行榜、男生/女生频道、详情页面、章节页面、目录页面等),配置 Sitemap 时需要根据页面类型的重要性和 SEO 目标选择性地包含 URL并合理组织以优化搜索引擎抓取和索引。以下是针对小说站点特点的 Sitemap 配置建议,包括哪些页面应该包含、如何处理大量 URL以及相关的最佳实践。
---
### 一、小说站点页面类型分析
根据你提供的信息,小说站点的页面类型可以分为以下几类,每类页面的 SEO 价值和是否需要包含在 Sitemap 中有所不同:
| 页面类型 | 描述 | SEO 价值 | 是否包含在 Sitemap |
|------------------|----------------------------------------------------------------------|---------------------------------------|--------------------|
| **首页** | 网站主入口,通常包含推荐小说、导航等。 | 高(核心流量入口) | 是 |
| **分类列表** | 按题材、类型(如玄幻、言情)展示小说列表,可能有多页(如 `page=2`)。| 高(引导用户到具体小说) | 是(仅包含主页面) |
| **排行榜** | 热门小说排行,可能按日、周、月或类型(如男生/女生)排序。 | 中到高(吸引点击,动态更新) | 是(视情况精选) |
| **男生/女生频道**| 针对不同用户群的分类页面(如男生玄幻、女生穿越)。 | 高(细分用户需求) | 是 |
| **详情页面** | 小说详情页,包含简介、封面、目录链接等。 | 高(核心转化页面) | 是 |
| **章节页面** | 小说具体章节内容,通常数量庞大。 | 中到低内容分散SEO 价值有限) | 视情况(可选) |
| **目录页面** | 小说章节列表,汇总所有章节链接。 | 中便于用户导航SEO 价值中等) | 是 |
---
### 二、Sitemap 配置策略
#### 1. 哪些 URL 应该包含?
基于小说站点的特点,建议优先包含以下页面:
- **首页**
- 包含站点的唯一首页 URL`https://www.example.com/`)。
- 设置高优先级(如 `<priority>1.0</priority>`)和频繁更新(如 `<changefreq>daily</changefreq>`)。
- **分类列表(主页面)**
- 包含每个分类的主页面(如 `https://www.example.com/category/xuanhuan`)。
- 排除分页 URL`https://www.example.com/category/xuanhuan?page=2`),因为分页内容重复且 SEO 价值低。
- 示例:玄幻、言情、历史等分类页面。
- **男生/女生频道**
- 包含频道主页(如 `https://www.example.com/male``https://www.example.com/female`)。
- 如果频道下有子分类(如男生玄幻、女生穿越),也应包含。
- **排行榜(精选)**
- 包含主要排行榜页面(如 `https://www.example.com/rank/hot``https://www.example.com/rank/male`)。
- 如果排行榜页面频繁更新(如每日排行),可设置 `<changefreq>daily</changefreq>`
- 排除次要或动态参数页面(如 `?sort=week`),避免重复内容。
- **详情页面**
- 包含所有小说详情页面(如 `https://www.example.com/book/123`)。
- 这些页面是 SEO 的核心,吸引搜索流量(如用户搜索小说名)。
- 使用 `<lastmod>` 反映小说更新时间,提示搜索引擎重新抓取。
- **目录页面**
- 包含每个小说的目录页面(如 `https://www.example.com/book/123/chapters`)。
- 目录页面便于用户导航,且可能被搜索引擎索引为长尾关键词(如“小说名 章节列表”)。
- **章节页面(可选)**
- **不建议全部包含**小说章节页面数量庞大可能数十万到数百万SEO 价值较低(用户很少通过搜索直接进入具体章节)。
- **可选策略**
- 只包含最新章节(如最近 30 天的章节),吸引搜索引擎抓取更新内容。
- 只包含热门小说的前几章(如前 10 章),作为引流入口。
- 如果包含,设置较低优先级(如 `<priority>0.3</priority>`)。
#### 2. 哪些 URL 应该排除?
- **分页 URL**:如分类列表的 `?page=2`,重复内容无 SEO 价值。
- **动态参数 URL**:如 `?sort=latest``?utm_source=...`,应规范化到标准 URL。
- **不可索引页面**
- 已设置 `<meta name="robots" content="noindex">` 的页面。
-`robots.txt` 屏蔽的页面(如 `Disallow: /user/`)。
- **用户生成内容**
- 如评论页、用户个人中心、搜索结果页(`?q=keyword`)。
- **临时页面**
- 如促销活动页、测试页面。
- **错误页面**:如 404、500 页面。
---
### 三、处理大量 URL 的策略
小说站点通常有大量 URL尤其是章节页面可能超过 Sitemap 的限制50,000 条 URL 或 50MB。以下是应对方法
#### 1. 使用 Sitemap 索引文件
- 将 URL 分组到多个子 Sitemap 文件(如 `sitemap-books.xml``sitemap-chapters.xml`),每文件不超过 50,000 条 URL。
- 创建一个 Sitemap 索引文件(如 `sitemap_index.xml`)引用所有子 Sitemap。
- 示例:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://www.example.com/sitemap-main.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-books.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-chapters.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
</sitemapindex>
```
#### 2. 分组策略
- **按页面类型分组**
- `sitemap-main.xml`:首页、分类列表、排行榜、男生/女生频道。
- `sitemap-books.xml`:小说详情页面和目录页面。
- `sitemap-chapters.xml`:章节页面(如果包含)。
- **按更新频率分组**
- 频繁更新的页面(如排行榜、最新章节)单独分组,设置 `<changefreq>daily</changefreq>`。
- **按小说分组**
- 为每部小说生成单独的 Sitemap如 `sitemap-book123.xml`),包含其详情页、目录页和部分章节页。
#### 3. 动态生成 Sitemap
- **脚本生成**
- 使用 Python、PHP 等脚本从数据库查询 URL生成 Sitemap 文件。
- 示例Python参考前文
```python
from lxml import etree
import datetime
# 模拟数据库查询
urls = [
{'loc': 'https://www.example.com/', 'lastmod': '2025-04-21', 'changefreq': 'daily', 'priority': '1.0'},
{'loc': 'https://www.example.com/book/123', 'lastmod': '2025-04-21', 'changefreq': 'weekly', 'priority': '0.8'},
{'loc': 'https://www.example.com/book/123/chapters', 'lastmod': '2025-04-21', 'changefreq': 'weekly', 'priority': '0.6'},
]
urlset = etree.Element("urlset", xmlns="http://www.sitemaps.org/schemas/sitemap/0.9")
for url in urls:
url_element = etree.SubElement(urlset, "url")
loc = etree.SubElement(url_element, "loc")
loc.text = url['loc']
lastmod = etree.SubElement(url_element, "lastmod")
lastmod.text = url['lastmod']
changefreq = etree.SubElement(url_element, "changefreq")
changefreq.text = url['changefreq']
priority = etree.SubElement(url_element, "priority")
priority.text = url['priority']
tree = etree.ElementTree(urlset)
tree.write("sitemap-main.xml", pretty_print=True, xml_declaration=True, encoding="UTF-8")
```
- **定时任务**
- 使用 cron 任务每天或每周生成 Sitemap上传到根目录。
- 示例Linux cron
```bash
0 2 * * * python3 /path/to/generate_sitemap.py
```
- **触发式更新**
- 在小说更新(如新章节发布)时,触发脚本更新相关 Sitemap。
#### 4. 伪静态 Sitemap
- 配置服务器将 `sitemap_index.xml` 等请求重定向到动态脚本,实时生成 XML 内容。
- 示例Apache + PHP参考前文
```apache
RewriteEngine On
RewriteRule ^sitemap_index\.xml$ sitemap_index.php [L]
```
---
### 四、robots.txt 配置
在 `robots.txt` 中声明 Sitemap 索引文件,使用绝对路径:
```txt
User-agent: *
Disallow: /user/
Disallow: /search/
Sitemap: https://www.example.com/sitemap_index.xml
```
- 确保不通过 `Disallow` 屏蔽 Sitemap 文件。
- 如果 Sitemap 托管在 CDN如 `https://cdn.example.com/sitemap_index.xml`),在 `robots.txt` 中使用 CDN 地址,并验证所有权。
---
### 五、SEO 优化建议
1. **优先级设置**
- 首页:`<priority>1.0</priority>`
- 分类/频道/详情页:`<priority>0.8</priority>`
- 目录页:`<priority>0.6</priority>`
- 章节页(若包含):`<priority>0.3</priority>`
2. **更新频率**
- 首页、排行榜:`<changefreq>daily</changefreq>`
- 分类/频道/详情/目录页:`<changefreq>weekly</changefreq>`
- 章节页:`<changefreq>monthly</changefreq>`(或 `never` 如果不频繁更新)
3. **规范化 URL**
- 确保只包含规范 URL如 `https://www.example.com/book/123` 而非 `http://example.com/book/123`)。
- 使用 `<link rel="canonical">` 或 Sitemap 统一规范版本。
4. **避免重复内容**
- 排除带参数的 URL如 `?sort=latest`)。
- 如果男生/女生频道与分类列表有重复内容,选择主要入口包含在 Sitemap 中。
5. **图片 Sitemap可选**
- 为小说封面图片创建图片 Sitemap优化图片搜索排名。
- 示例:
```xml
<url>
<loc>https://www.example.com/book/123</loc>
<image:image>
<image:loc>https://www.example.com/images/book123.jpg</image:loc>
<image:title>小说封面</image:title>
</image:image>
</url>
```
---
### 六、注意事项
1. **章节页面数量庞大**
- 如果每部小说有数百章节,章节页面可能占主导。建议只包含最新或热门章节,或完全排除章节页面,依靠目录页面引导爬虫。
2. **抓取预算**
- 小说站点 URL 数量多,需优化 Sitemap 避免浪费搜索引擎的抓取预算。
3. **动态更新**
- 小说站点内容更新频繁(如新章节发布),建议动态生成 Sitemap 或频繁更新。
4. **验证 Sitemap**
- 提交 `sitemap_index.xml` 到 Google Search Console、Bing Webmaster Tools检查是否被正确解析。
- 使用 GSC 的“索引覆盖率”报告,确认重要页面(如详情页)是否被索引。
---
### 七、示例 Sitemap 配置
#### 索引文件(`sitemap_index.xml`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://www.example.com/sitemap-main.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-books.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
</sitemapindex>
```
#### 主 Sitemap`sitemap-main.xml`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.example.com/</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.example.com/category/xuanhuan</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://www.example.com/male</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://www.example.com/rank/hot</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>daily</changefreq>
<priority>0.7</priority>
</url>
</urlset>
```
#### 小说 Sitemap`sitemap-books.xml`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.example.com/book/123</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://www.example.com/book/123/chapters</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.6</priority>
</url>
</urlset>
```
---
### 八、结论
- **不需包含所有 URL**:小说站点应优先包含首页、分类列表、男生/女生频道、排行榜、详情页面和目录页面。章节页面可根据需要部分包含或完全排除。
- **精选策略**:重点包含 SEO 价值高的页面(如详情页),排除分页、动态参数、低价值页面。
- **大型站点处理**:使用 Sitemap 索引文件和子 Sitemap按页面类型分组动态生成以应对大量 URL。
- **SEO 优化**:设置合理的 `<priority>` 和 `<changefreq>`,定期更新 Sitemap验证索引效果。
如果你需要针对小说站点的具体脚本(生成 Sitemap 或伪静态配置、CMS 插件推荐,或其他细节(如图片 Sitemap、robots.txt 优化),请告诉我!

View File

@@ -0,0 +1,3 @@
User-agent: *
Disallow:
Sitemap: https://{$DomainModel->d_domain}/sitemap_index.xml

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<!-- // TODO 根据分页查询,按顺序 每页 50000个小说 -->
{novel:pagerexp page="$Request.get.page" limit="50000"
d_key="key"
d_val="Novel"
p_val="page_data" button_num="10" cache_life="86400" func="generateSearchPager" export_name="resData" /}
{foreach $resData.data as $key=>$Novel}
<url>
<loc>https://www.{$DomainModel->d_domain}{site:nclurl n_id="$Novel.n_id" n_py="$Novel.n_name_pinyin" order="zheng" page="1"/}</loc>
<lastmod>{:date('Y-m-d')}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
{/foreach}
<!-- 最多 50,000 个 <url> 条目 -->
</urlset>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<!-- // TODO 根据分页查询,按顺序 每页 50000个小说 -->
{novel:pagerexp page="$Request.get.page" limit="50000"
d_key="key"
d_val="Novel"
p_val="page_data" button_num="10" cache_life="86400" func="generateSearchPager" export_name="resData" /}
{foreach $resData.data as $key=>$Novel}
<url>
<loc>https://www.{$DomainModel->d_domain}{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}</loc>
<lastmod>{:date('Y-m-d')}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
{/foreach}
<!-- 最多 50,000 个 <url> 条目 -->
</urlset>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<!-- // TODO 根据分页 查询最新 50000条章节 -->
<url>
<loc>https://www.{$DomainModel->d_domain}/chapters1</loc>
<lastmod>{:date('Y-m-d')}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.6</priority>
</url>
<!-- 最多 50,000 个 <url> 条目 -->
</urlset>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.{$DomainModel->d_domain}/</loc>
<lastmod>{:date('Y-m-d')}</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<!-- 分类 -->
{novel:category d_key="strCategoryPinyin" d_val="strCategoryName"}
<!-- 排序 -->
{novel:sort d_key="sort_key" d_val="strSortName"}
<!-- 状态 -->
{novel:status d_key="status_key" d_val="strStatusName"}
<url>
<loc>https://www.{$DomainModel->d_domain}{site:nflurl category="$strCategoryPinyin" order="$sort_key" status="$status_key" /}</loc>
<lastmod>{:date('Y-m-d')}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
{/novel:status}
{/novel:sort}
{/novel:category}
<!-- 注意 所有链接不要分页,有分页的取第一页即可 -->
</urlset>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://www.{$DomainModel->d_domain}/sitemap-main.xml</loc>
<lastmod>{:date('Y-m-d')}</lastmod>
</sitemap>
<!-- TODO 小说总数量/50000 得出 sitemap-books一共有多少个 -->
<sitemap>
<loc>https://www.{$DomainModel->d_domain}/sitemap-books-1.xml</loc>
<lastmod>{:date('Y-m-d')}</lastmod>
</sitemap>
<sitemap>
<loc>https://www.{$DomainModel->d_domain}/sitemap-books-2.xml</loc>
<lastmod>{:date('Y-m-d')}</lastmod>
</sitemap>
<!-- TODO 小说总数量/50000 得出 sitemap-books-catalog一共有多少个,每个小说只取一个目录链接,分页不需要加入去 -->
<sitemap>
<loc>https://www.{$DomainModel->d_domain}/sitemap-books-catalog-1.xml</loc>
<lastmod>{:date('Y-m-d')}</lastmod>
</sitemap>
<sitemap>
<loc>https://www.{$DomainModel->d_domain}/sitemap-books-catalog-2.xml</loc>
<lastmod>{:date('Y-m-d')}</lastmod>
</sitemap>
<!-- ...小说章节取最新50w条 这里生成10个索引文件即可 -->
{for start="1" end="11"}
<sitemap>
<loc>https://www.{$DomainModel->d_domain}/sitemap-chapters-{$i}.xml</loc>
<lastmod>{:date('Y-m-d')}</lastmod>
</sitemap>
{/for}
</sitemapindex>

View File

@@ -1,4 +1,6 @@
{site:helper func="initHomeTKD" /}
<!-- {site:getval func="strSiteName" /} -->
<!-- {site:helper func="initHomeTKD" /} -->
<!-- {site:forgelist count="3" d_key="d_key" d_val="novel" cache_life="1000"}

View File

@@ -1,5 +1,16 @@
{extend name="baseH5" /}
{block name="get-data"}
{novel:pagerexp page="$Request.get.page" limit="30"
n_category="$Request.route.strCategory"
n_sex="$Request.route.strGender"
n_status="$Request.route.strStatus"
d_key="d_key"
button_num="10" cache_life="86400" func="generateCategoryPager" export_name="resData" /}
{site:grm page_code="pc_novel_library" diff="$resData.p_data.page" num="70" g_key="arrGrm" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETLIBRARY@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETLIBRARY@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETLIBRARY@DESCRIPTION"}{/block}
@@ -45,7 +56,7 @@
{block name="logo-html"}
<h1 class="logo">
<a href="/">{$DomainModel->d_name}-{$Request.route.strGender}{$Request.route.strCategory}{$Request.route.strStatus}免费阅读</a>
<a href="/">{$DomainModel->d_name}-{site:getval code="strNovelSex" /}{site:getval code="strNovelCategoryName" /}{site:getval code="strNovelStatus" /}免费阅读</a>
</h1>
{/block}
@@ -55,14 +66,7 @@
{block name="main"}
{novel:pagerexp page="$Request.get.page" limit="30"
n_category="$Request.route.strCategory"
n_sex="$Request.route.strGender"
n_status="$Request.route.strStatus"
d_key="d_key"
button_num="10" cache_life="86400" func="generateCategoryPager" export_name="resData" /}
{site:grm page_code="pc_novel_library" diff="$resData.p_data.page" num="70" g_key="arrGrm" /}
<div class="wrap">
<p class="site-description">{site:replace code="NOVEL@GETLIBRARY@DESCRIPTION"}</p>

View File

@@ -1,13 +1,17 @@
{extend name="baseH5" /}
{block name="get-data"}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="0" /}
{site:grm page_code="h5_novel_catalog " diff="$Request.url" num="120" g_key="arrGrm" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETNOVELCATALOG@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETNOVELCATALOG@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETNOVELCATALOG@DESCRIPTION"}{/block}
{block name="head"}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="0" /}
{site:grm page_code="h5_novel_catalog " diff="$Request.url" num="120" g_key="arrGrm" /}
<!-- 社交媒体标签 -->
<meta property="og:title" content="{$arrNovel['n_name']??'未知小说'}" />

View File

@@ -1,5 +1,9 @@
{extend name="baseH5" /}
{block name="get-data"}
{site:helper func="initSexTKD" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETNOVELCHANNEL@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETNOVELCHANNEL@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETNOVELCHANNEL@DESCRIPTION"}{/block}

View File

@@ -2,7 +2,7 @@
{block name="get-data"}
{if $Request.route.intNovelId}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="0" /}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="$Request.route.intForgeId" /}
{else}
{novel:info n_id="$DomainModel->info_id" n_key="arrNovel" n_forge_id="0" /}
{/if}
@@ -191,7 +191,9 @@
</p>
<p class="xianglingtuijian">相邻推荐:
{volist name="arrNovel.n_forge_novel" id="ForgeNovel" key="key"}
{if $key < 100}
{$arrGrm[$key+20]|raw}
{/if}
<a
href='{site:nnurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" n_fid="$ForgeNovel.n_forge_id"/}'>{$ForgeNovel.n_forge_title}</a>
{/volist}
@@ -210,9 +212,11 @@
</div>
<div class="attentions">
<ul class="clearfix">
{chapter:list count="10" sort_type="dao" n_id="$arrNovel.n_id" d_key="d_key" d_val="Chapter" cache_life="86400"}
{chapter:list count="10" sort_type="dao" n_id="$arrNovel.n_id" d_key="key" d_val="Chapter" cache_life="86400"}
<li>
{$arrGrm[$key]|raw}
{if $key < 100}
{$arrGrm[$key+20]|raw}
{/if}
<a href='{site:cpurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" c_sort="$Chapter.c_sort_num" c_page="0"/}'
title="{$arrNovel.n_name}-{$Chapter.c_name}">{$Chapter.c_name}</a>
</li>

View File

@@ -1,5 +1,9 @@
{extend name="baseH5" /}
{block name="get-data"}
{site:helper func="initSexTKD" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETNOVELRANK@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETNOVELRANK@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETNOVELRANK@DESCRIPTION"}{/block}

View File

@@ -1,11 +1,24 @@
{extend name="basePc" /}
{block name="title"}{$strTitle??''}{/block}
{block name="keywords"}{$strKeywords??''}{/block}
{block name="description"}{$strDescription??''}{/block}
{block name="get-data"}
{if $Request.route.intNovelId}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="0" /}
{else}
{novel:info n_id="$DomainModel->info_id" n_key="arrNovel" n_forge_id="0" /}
{/if}
{site:grm page_code="h5_novel_info" diff="$arrNovel.n_id" num="120" g_key="arrGrm" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETNOVELINFO@TITLE" diff="$Request.route.intNovelId" /}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETNOVELINFO@KEYWORDS" diff="$Request.route.intNovelId"}{/block}
{block name="description"}{site:replace code="NOVEL@GETNOVELINFO@DESCRIPTION" diff="$Request.route.intNovelId"}{/block}
{block name="head"}
<!-- 社交媒体标签 -->
<meta property="og:title" content="{$arrNovel['n_name']??'未知小说'}" />
<meta property="og:description" content="{$strDescription??'暂无简介'}" />
<meta property="og:description" content='{site:replace code="NOVEL@GETNOVELINFO@DESCRIPTION" diff="$Request.route.intNovelId" }' />
<meta property="og:url"
content='https://{$DomainModel->d_domain}{site:nurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" /}' />
<meta property="og:type" content="book" />
@@ -15,46 +28,47 @@
<meta property="og:novel:author" content="{$arrNovel.n_author ?? ''}">
<meta property="og:novel:book_name" content="{$arrNovel.n_name ?? ''}">
<meta property="og:novel:read_url"
content="https://{$DomainModel->d_domain}{$strPcPath}/xiaoshuo/{$arrNovel.n_name_pinyin}-{$arrNovel.n_id}/zhang-1">
content='https://{$DomainModel->d_domain}{$strPcPath}{site:cpurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" c_sort="$arrNovel.intFirstChapterSort"/}'>
<meta property="og:novel:status" content="{$arrNovel.n_status ?? ''}">
<meta property="og:novel:update_time" content="{$arrNovel.n_update_time ?? ''}">
<meta property="og:novel:latest_chapter_name" content="{$arrLatestChapter.c_name ?? ''}">
<meta property="og:novel:latest_chapter_name" content="{$arrNovel.n_latest_chapter_name ?? ''}">
<meta property="og:novel:latest_chapter_url"
content="https://{$DomainModel->d_domain}{$strPcPath}/xiaoshuo/{$arrNovel.n_name_pinyin}-{$arrNovel.n_id}/zhang-{$arrLatestChapter.c_sort_num ?? 1}">
content='https://{$DomainModel->d_domain}{$strPcPath}{site:lcpurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" /}'>
<!-- 可选:支持 Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="{$arrNovel['n_name'] ?? '未知小说'}" />
<meta name="twitter:description" content="{$strDescription ?? '暂无简介'}" />
<meta name="twitter:description" content='{site:replace code="NOVEL@GETNOVELINFO@DESCRIPTION" diff="$Request.route.intNovelId" }' />
<meta name="twitter:image" content="{$arrNovel.n_cover_path ?? ''}" />
<!-- 结构化数据 -->
<script type="application/ld+json">
{
"@context": 'https://{$DomainModel->d_domain}/{site:nurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" /}',
"@type": "book",
"name": "{$arrNovel['n_name'] ?? '未知小说'}",
"description": "{$arrNovel['n_description'] ??'暂无简介'}",
"author": {
"@type": "Person",
"name": "{$arrNovel['n_author'] ??'佚名'}"
},
"publisher": {
"@type": "Organization",
"name": "{$DomainModel->d_name}",
"url": "https://{$DomainModel->d_domain}"
},
"datePublished": "{$arrNovel['n_update_time'] ?? time()}",
"image": "{$Novel.n_cover_path ?? ''}",
"url": '{site:nurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" /}',
"genre": "{$arrNovel.n_category ??''}",
"inLanguage": "zh-CN",
"bookFormat": "https://{$DomainModel->d_domain}/EBook",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.5",
"reviewCount": "100",
},
}
</script>
{
"@context": "https://schema.org",
"@type": "Book",
"name": "{$arrNovel['n_name'] ?? '未知小说'}",
"description": "{$arrNovel['n_description'] ??'暂无简介'}",
"author": {
"@type": "Person",
"name": "{$arrNovel['n_author'] ??'佚名'}"
},
"publisher": {
"@type": "Organization",
"name": "{$DomainModel->d_name}",
"url": "https://{$DomainModel->d_domain}"
},
"datePublished": "{$arrNovel['n_update_time'] ?? time()}",
"image": "{$arrNovel.n_cover_path ?? ''}",
"url": 'https://{$DomainModel->d_domain}{site:nurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" /}',
"genre": "{$arrNovel.n_category ??''}",
"inLanguage": "zh-CN",
"bookFormat": "https://{$DomainModel->d_domain}/EBook",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.5",
"reviewCount": "100",
},
}
</script>
{/block}
{block name="head-css"}

View File

@@ -1,5 +1,17 @@
{extend name="basePc" /}
{block name="get-data"}
{novel:pagerexp page="$Request.get.page" limit="30"
n_category="$Request.route.strCategory"
n_sex="$Request.route.strGender"
n_status="$Request.route.strStatus"
d_key="d_key"
button_num="10" cache_life="86400" func="generateCategoryPager" export_name="resData" /}
{site:grm page_code="pc_novel_library" diff="$resData.p_data.page" num="70" g_key="arrGrm" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETLIBRARY@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETLIBRARY@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETLIBRARY@DESCRIPTION"}{/block}
@@ -66,14 +78,7 @@
{block name="main"}
{novel:pagerexp page="$Request.get.page" limit="30"
n_category="$Request.route.strCategory"
n_sex="$Request.route.strGender"
n_status="$Request.route.strStatus"
d_key="d_key"
button_num="10" cache_life="86400" func="generateCategoryPager" export_name="resData" /}
{site:grm page_code="pc_novel_library" diff="$resData.p_data.page" num="70" g_key="arrGrm" /}
<div class="content">
<nav class="breadcrumb" aria-label="breadcrumb">

View File

@@ -1,5 +1,7 @@
{extend name="basePc" /}
{block name="get-data"}
{site:helper func="initSexTKD" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETNOVELCHANNEL@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETNOVELCHANNEL@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETNOVELCHANNEL@DESCRIPTION"}{/block}

View File

@@ -2,7 +2,7 @@
{block name="get-data"}
{if $Request.route.intNovelId}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="0" /}
{novel:info n_id="$Request.route.intNovelId" n_key="arrNovel" n_forge_id="$Request.route.intForgeId" /}
{else}
{novel:info n_id="$DomainModel->info_id" n_key="arrNovel" n_forge_id="0" /}
{/if}
@@ -225,7 +225,7 @@
</div>
<div class="pl_con">
{volist name="arrNovel.n_forge_novel" id="ForgeNovel" key="key"}
{if $key<20 } {$arrGrm[$key+20]|raw} {/if} <a
{if $key<100 } {$arrGrm[$key+20]|raw} {/if} <a
href='{$strPcPath}{site:nnurl n_id="$arrNovel.n_id" n_py="$arrNovel.n_name_pinyin" n_fid="$ForgeNovel.n_forge_id"/}'
class="red">{$ForgeNovel.n_forge_title}</a>
{/volist}

View File

@@ -1,5 +1,11 @@
{extend name="basePc" /}
{block name="get-data"}
{site:helper func="initSexTKD" /}
{site:grm page_code="h5_rank" diff="0" num="100" g_key="arrGrm" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETNOVELRANK@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETNOVELRANK@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETNOVELRANK@DESCRIPTION"}{/block}
@@ -41,8 +47,6 @@
{block name="main"}
{site:grm page_code="h5_rank" diff="0" num="100" g_key="arrGrm" /}
<div class="content content_back">
<nav class="breadcrumb" aria-label="breadcrumb">

View File

@@ -1,5 +1,14 @@
{extend name="basePc" /}
{block name="get-data"}
{novel:pagerexp page="$Request.get.page" limit="30"
key="$Request.get.keyword"
d_key="d_key"
d_val="Novel" n_num="total"
p_val="page_data" button_num="10" cache_life="86400" func="generateSearchPager" export_name="resData" /}
{site:grm page_code="pc_novel_search" diff="$Request.url" num="30" g_key="arrGrm" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETSEARCHNOVEL@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETSEARCHNOVEL@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETSEARCHNOVEL@DESCRIPTION"}{/block}
@@ -50,14 +59,6 @@
{block name="main"}
{novel:pagerexp page="$Request.get.page" limit="30"
key="$Request.get.keyword"
d_key="d_key"
d_val="Novel" n_num="total"
p_val="page_data" button_num="10" cache_life="86400" func="generateSearchPager" export_name="resData" /}
{site:grm page_code="pc_novel_search" diff="$Request.url" num="30" g_key="arrGrm" /}
<div class="content">
<div class="find">

View File

@@ -19,7 +19,7 @@
<a href="/site.txt">网站地图</a>
{site:forgelist count="30" d_key="d_key" d_val="ForgeNovel" cache_life="86400"}
<a
href='{$strPcPath}{site:nnurl n_id="$ForgeNovel.n_id" n_py="$ForgeNovel.n_name_pinyin" n_fid="$ForgeNovel.n_forge_id"/}'>
href='{site:nnurl n_id="$ForgeNovel.n_id" n_py="$ForgeNovel.n_name_pinyin" n_fid="$ForgeNovel.n_forge_id"/}'>
{$ForgeNovel.n_forge_title}
</a>
{/site:forgelist}

View File

@@ -0,0 +1,294 @@
对于一个小说站点(如你提到的包含首页、分类列表、排行榜、男生/女生频道、详情页面、章节页面、目录页面等),配置 Sitemap 时需要根据页面类型的重要性和 SEO 目标选择性地包含 URL并合理组织以优化搜索引擎抓取和索引。以下是针对小说站点特点的 Sitemap 配置建议,包括哪些页面应该包含、如何处理大量 URL以及相关的最佳实践。
---
### 一、小说站点页面类型分析
根据你提供的信息,小说站点的页面类型可以分为以下几类,每类页面的 SEO 价值和是否需要包含在 Sitemap 中有所不同:
| 页面类型 | 描述 | SEO 价值 | 是否包含在 Sitemap |
|------------------|----------------------------------------------------------------------|---------------------------------------|--------------------|
| **首页** | 网站主入口,通常包含推荐小说、导航等。 | 高(核心流量入口) | 是 |
| **分类列表** | 按题材、类型(如玄幻、言情)展示小说列表,可能有多页(如 `page=2`)。| 高(引导用户到具体小说) | 是(仅包含主页面) |
| **排行榜** | 热门小说排行,可能按日、周、月或类型(如男生/女生)排序。 | 中到高(吸引点击,动态更新) | 是(视情况精选) |
| **男生/女生频道**| 针对不同用户群的分类页面(如男生玄幻、女生穿越)。 | 高(细分用户需求) | 是 |
| **详情页面** | 小说详情页,包含简介、封面、目录链接等。 | 高(核心转化页面) | 是 |
| **章节页面** | 小说具体章节内容,通常数量庞大。 | 中到低内容分散SEO 价值有限) | 视情况(可选) |
| **目录页面** | 小说章节列表,汇总所有章节链接。 | 中便于用户导航SEO 价值中等) | 是 |
---
### 二、Sitemap 配置策略
#### 1. 哪些 URL 应该包含?
基于小说站点的特点,建议优先包含以下页面:
- **首页**
- 包含站点的唯一首页 URL`https://www.example.com/`)。
- 设置高优先级(如 `<priority>1.0</priority>`)和频繁更新(如 `<changefreq>daily</changefreq>`)。
- **分类列表(主页面)**
- 包含每个分类的主页面(如 `https://www.example.com/category/xuanhuan`)。
- 排除分页 URL`https://www.example.com/category/xuanhuan?page=2`),因为分页内容重复且 SEO 价值低。
- 示例:玄幻、言情、历史等分类页面。
- **男生/女生频道**
- 包含频道主页(如 `https://www.example.com/male``https://www.example.com/female`)。
- 如果频道下有子分类(如男生玄幻、女生穿越),也应包含。
- **排行榜(精选)**
- 包含主要排行榜页面(如 `https://www.example.com/rank/hot``https://www.example.com/rank/male`)。
- 如果排行榜页面频繁更新(如每日排行),可设置 `<changefreq>daily</changefreq>`
- 排除次要或动态参数页面(如 `?sort=week`),避免重复内容。
- **详情页面**
- 包含所有小说详情页面(如 `https://www.example.com/book/123`)。
- 这些页面是 SEO 的核心,吸引搜索流量(如用户搜索小说名)。
- 使用 `<lastmod>` 反映小说更新时间,提示搜索引擎重新抓取。
- **目录页面**
- 包含每个小说的目录页面(如 `https://www.example.com/book/123/chapters`)。
- 目录页面便于用户导航,且可能被搜索引擎索引为长尾关键词(如“小说名 章节列表”)。
- **章节页面(可选)**
- **不建议全部包含**小说章节页面数量庞大可能数十万到数百万SEO 价值较低(用户很少通过搜索直接进入具体章节)。
- **可选策略**
- 只包含最新章节(如最近 30 天的章节),吸引搜索引擎抓取更新内容。
- 只包含热门小说的前几章(如前 10 章),作为引流入口。
- 如果包含,设置较低优先级(如 `<priority>0.3</priority>`)。
#### 2. 哪些 URL 应该排除?
- **分页 URL**:如分类列表的 `?page=2`,重复内容无 SEO 价值。
- **动态参数 URL**:如 `?sort=latest``?utm_source=...`,应规范化到标准 URL。
- **不可索引页面**
- 已设置 `<meta name="robots" content="noindex">` 的页面。
-`robots.txt` 屏蔽的页面(如 `Disallow: /user/`)。
- **用户生成内容**
- 如评论页、用户个人中心、搜索结果页(`?q=keyword`)。
- **临时页面**
- 如促销活动页、测试页面。
- **错误页面**:如 404、500 页面。
---
### 三、处理大量 URL 的策略
小说站点通常有大量 URL尤其是章节页面可能超过 Sitemap 的限制50,000 条 URL 或 50MB。以下是应对方法
#### 1. 使用 Sitemap 索引文件
- 将 URL 分组到多个子 Sitemap 文件(如 `sitemap-books.xml``sitemap-chapters.xml`),每文件不超过 50,000 条 URL。
- 创建一个 Sitemap 索引文件(如 `sitemap_index.xml`)引用所有子 Sitemap。
- 示例:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://www.example.com/sitemap-main.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-books.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-chapters.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
</sitemapindex>
```
#### 2. 分组策略
- **按页面类型分组**
- `sitemap-main.xml`:首页、分类列表、排行榜、男生/女生频道。
- `sitemap-books.xml`:小说详情页面和目录页面。
- `sitemap-chapters.xml`:章节页面(如果包含)。
- **按更新频率分组**
- 频繁更新的页面(如排行榜、最新章节)单独分组,设置 `<changefreq>daily</changefreq>`。
- **按小说分组**
- 为每部小说生成单独的 Sitemap如 `sitemap-book123.xml`),包含其详情页、目录页和部分章节页。
#### 3. 动态生成 Sitemap
- **脚本生成**
- 使用 Python、PHP 等脚本从数据库查询 URL生成 Sitemap 文件。
- 示例Python参考前文
```python
from lxml import etree
import datetime
# 模拟数据库查询
urls = [
{'loc': 'https://www.example.com/', 'lastmod': '2025-04-21', 'changefreq': 'daily', 'priority': '1.0'},
{'loc': 'https://www.example.com/book/123', 'lastmod': '2025-04-21', 'changefreq': 'weekly', 'priority': '0.8'},
{'loc': 'https://www.example.com/book/123/chapters', 'lastmod': '2025-04-21', 'changefreq': 'weekly', 'priority': '0.6'},
]
urlset = etree.Element("urlset", xmlns="http://www.sitemaps.org/schemas/sitemap/0.9")
for url in urls:
url_element = etree.SubElement(urlset, "url")
loc = etree.SubElement(url_element, "loc")
loc.text = url['loc']
lastmod = etree.SubElement(url_element, "lastmod")
lastmod.text = url['lastmod']
changefreq = etree.SubElement(url_element, "changefreq")
changefreq.text = url['changefreq']
priority = etree.SubElement(url_element, "priority")
priority.text = url['priority']
tree = etree.ElementTree(urlset)
tree.write("sitemap-main.xml", pretty_print=True, xml_declaration=True, encoding="UTF-8")
```
- **定时任务**
- 使用 cron 任务每天或每周生成 Sitemap上传到根目录。
- 示例Linux cron
```bash
0 2 * * * python3 /path/to/generate_sitemap.py
```
- **触发式更新**
- 在小说更新(如新章节发布)时,触发脚本更新相关 Sitemap。
#### 4. 伪静态 Sitemap
- 配置服务器将 `sitemap_index.xml` 等请求重定向到动态脚本,实时生成 XML 内容。
- 示例Apache + PHP参考前文
```apache
RewriteEngine On
RewriteRule ^sitemap_index\.xml$ sitemap_index.php [L]
```
---
### 四、robots.txt 配置
在 `robots.txt` 中声明 Sitemap 索引文件,使用绝对路径:
```txt
User-agent: *
Disallow: /user/
Disallow: /search/
Sitemap: https://www.example.com/sitemap_index.xml
```
- 确保不通过 `Disallow` 屏蔽 Sitemap 文件。
- 如果 Sitemap 托管在 CDN如 `https://cdn.example.com/sitemap_index.xml`),在 `robots.txt` 中使用 CDN 地址,并验证所有权。
---
### 五、SEO 优化建议
1. **优先级设置**
- 首页:`<priority>1.0</priority>`
- 分类/频道/详情页:`<priority>0.8</priority>`
- 目录页:`<priority>0.6</priority>`
- 章节页(若包含):`<priority>0.3</priority>`
2. **更新频率**
- 首页、排行榜:`<changefreq>daily</changefreq>`
- 分类/频道/详情/目录页:`<changefreq>weekly</changefreq>`
- 章节页:`<changefreq>monthly</changefreq>`(或 `never` 如果不频繁更新)
3. **规范化 URL**
- 确保只包含规范 URL如 `https://www.example.com/book/123` 而非 `http://example.com/book/123`)。
- 使用 `<link rel="canonical">` 或 Sitemap 统一规范版本。
4. **避免重复内容**
- 排除带参数的 URL如 `?sort=latest`)。
- 如果男生/女生频道与分类列表有重复内容,选择主要入口包含在 Sitemap 中。
5. **图片 Sitemap可选**
- 为小说封面图片创建图片 Sitemap优化图片搜索排名。
- 示例:
```xml
<url>
<loc>https://www.example.com/book/123</loc>
<image:image>
<image:loc>https://www.example.com/images/book123.jpg</image:loc>
<image:title>小说封面</image:title>
</image:image>
</url>
```
---
### 六、注意事项
1. **章节页面数量庞大**
- 如果每部小说有数百章节,章节页面可能占主导。建议只包含最新或热门章节,或完全排除章节页面,依靠目录页面引导爬虫。
2. **抓取预算**
- 小说站点 URL 数量多,需优化 Sitemap 避免浪费搜索引擎的抓取预算。
3. **动态更新**
- 小说站点内容更新频繁(如新章节发布),建议动态生成 Sitemap 或频繁更新。
4. **验证 Sitemap**
- 提交 `sitemap_index.xml` 到 Google Search Console、Bing Webmaster Tools检查是否被正确解析。
- 使用 GSC 的“索引覆盖率”报告,确认重要页面(如详情页)是否被索引。
---
### 七、示例 Sitemap 配置
#### 索引文件(`sitemap_index.xml`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://www.example.com/sitemap-main.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-books.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
</sitemapindex>
```
#### 主 Sitemap`sitemap-main.xml`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.example.com/</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.example.com/category/xuanhuan</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://www.example.com/male</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://www.example.com/rank/hot</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>daily</changefreq>
<priority>0.7</priority>
</url>
</urlset>
```
#### 小说 Sitemap`sitemap-books.xml`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.example.com/book/123</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://www.example.com/book/123/chapters</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.6</priority>
</url>
</urlset>
```
---
### 八、结论
- **不需包含所有 URL**:小说站点应优先包含首页、分类列表、男生/女生频道、排行榜、详情页面和目录页面。章节页面可根据需要部分包含或完全排除。
- **精选策略**:重点包含 SEO 价值高的页面(如详情页),排除分页、动态参数、低价值页面。
- **大型站点处理**:使用 Sitemap 索引文件和子 Sitemap按页面类型分组动态生成以应对大量 URL。
- **SEO 优化**:设置合理的 `<priority>` 和 `<changefreq>`,定期更新 Sitemap验证索引效果。
如果你需要针对小说站点的具体脚本(生成 Sitemap 或伪静态配置、CMS 插件推荐,或其他细节(如图片 Sitemap、robots.txt 优化),请告诉我!

View File

@@ -0,0 +1,3 @@
User-agent: *
Disallow:
Sitemap: https://{$DomainModel->d_domain}/sitemap_index.xml

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{novel:pagerexp page="$Request.get.page" limit="50000"
d_key="key"
d_val="Novel"
p_val="page_data" button_num="10" cache_life="86400" func="generateSearchPager" export_name="resData" /}
{foreach $resData.data as $key=>$Novel}
<url>
<loc>https://www.{$DomainModel->d_domain}{site:nclurl n_id="$Novel.n_id" n_py="$Novel.n_name_pinyin" order="zheng" page="1"/}</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
{/foreach}
<!-- 最多 50,000 个 <url> 条目 -->
</urlset>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{novel:pagerexp page="$Request.get.page" limit="50000"
d_key="key"
d_val="Novel"
p_val="page_data" button_num="10" cache_life="86400" func="generateSearchPager" export_name="resData" /}
{foreach $resData.data as $key=>$Novel}
<url>
<loc>https://www.{$DomainModel->d_domain}{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
{/foreach}
<!-- 最多 50,000 个 <url> 条目 -->
</urlset>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<!-- // TODO 根据分页 查询最新 50000条章节 -->
<url>
<loc>https://www.{$DomainModel->d_domain}/chapters1</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.6</priority>
</url>
<!-- 最多 50,000 个 <url> 条目 -->
</urlset>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.{$DomainModel->d_domain}/</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<!-- 分类 -->
{novel:category d_key="strCategoryPinyin" d_val="strCategoryName"}
<!-- 排序 -->
{novel:sort d_key="sort_key" d_val="strSortName"}
<!-- 状态 -->
{novel:status d_key="status_key" d_val="strStatusName"}
<url>
<loc>https://www.{$DomainModel->d_domain}{site:nflurl category="$strCategoryPinyin" order="$sort_key" status="$status_key" /}</loc>
<lastmod>2025-04-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
{/novel:status}
{/novel:sort}
{/novel:category}
<!-- 注意 所有链接不要分页,有分页的取第一页即可 -->
</urlset>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://www.example.com/sitemap-main.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-books-1.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-books-2.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<!-- ...小说总数量/50000 得出 sitemap-books一共有多少个 -->
<sitemap>
<loc>https://www.example.com/sitemap-books-catalog-1.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-books-catalog-2.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<!-- ...小说总数量/50000 得出 sitemap-books-catalog一共有多少个,每个小说只取一个目录链接,分页不需要加入去 -->
<sitemap>
<loc>https://www.example.com/sitemap-chapters-1.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<sitemap>
<loc>https://www.example.com/sitemap-chapters-2.xml</loc>
<lastmod>2025-04-21</lastmod>
</sitemap>
<!-- ...小说章节取最新50w条 这里生成10个索引文件即可 -->
</sitemapindex>

View File

@@ -7,32 +7,33 @@
'{strNovelSex}' => '当前页面小说是男生还是女生 小说',
'{strNovelCategoryName}' => '当前页面小说分类名字',
'{strNovelStatus}' => '当前页面小说状态 是连载还是完结',
'{strNovelOrder}' => '当前页面小说排序 全部排序,最新入库,最近更新,推荐',
这个是分类或者书库的路由,公用一套视图模板
/shuku/:strGender/:strCategory/:strStatus/page:intPage
/shuku/:strGender/:strCategory/:strStatus/:strNovelOrder/page:intPage
请根据路由和上面的替换标识你帮忙设计100套最友好seo的 tkd 替换模板,字数要符合常规,不要超标也不要少,质量要保证
返回格式:
title [
'{strNovelSex}{strNovelCategoryName}{strNovelStatus}小说 - {strSiteName} - 第{intPage}页',
'{strNovelSex}{strNovelCategoryName}{strNovelStatus}小说 - {strSiteName} - 第{intPage}页',
'{strNovelSex}{strNovelCategoryName}{strNovelStatus}{strNovelOrder}小说 - {strSiteName} - 第{intPage}页',
'{strNovelSex}{strNovelOrder}{strNovelCategoryName}{strNovelStatus}小说 - {strSiteName} - 第{intPage}页',
..
]
keywords: [
'{strNovelCategoryName}, {strNovelSex}小说, {strNovelStatus}小说, {strSiteName}, 免费阅读',
'{strNovelCategoryName}, {strNovelSex}小说, {strNovelStatus}小说, {strSiteName},{strNovelOrder} 免费阅读',
..
]
description: [
'{strSiteName}提供{strNovelSex}{strNovelCategoryName}{strNovelStatus}小说免费阅读,第{intPage}页汇聚热门作品,欢迎体验{strSiteDomain}',
'{strSiteName}提供{strNovelSex}{strNovelCategoryName}{strNovelStatus}{strNovelOrder}小说免费阅读,第{intPage}页汇聚热门作品,欢迎体验{strSiteDomain}',
..
]
好的,我会根据你提供的书库路由 `/shuku/:strGender/:strCategory/:strStatus/page:intPage` 和替换标识,设计一个最优的 SEO 友好的 TKD 模板。你的案例已经给出了一个分类页的模板,我会在此基础上优化,确保它既符合书库页面的特点,又最大化 SEO 效果。
好的,我会根据你提供的书库路由 `/shuku/:strGender/:strCategory/:strStatus/:strNovelOrder/page:intPage` 和替换标识,设计一个最优的 SEO 友好的 TKD 模板。你的案例已经给出了一个分类页的模板,我会在此基础上优化,确保它既符合书库页面的特点,又最大化 SEO 效果。
---

View File

@@ -2,6 +2,8 @@
<!DOCTYPE html>
<html lang="zh">
<head>
{block name="get-data"}
{/block}
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>{block name="title"}{/block}</title>
@@ -42,8 +44,8 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script type="text/javascript" src="/template/shikong/js/qrcode.min.js"></script>
<script type="text/javascript" src="/template/shikong/js/enc/public.min.js"></script>
<script type="text/javascript" src='/template/shikong/js/enc/qd.min.js?version={site:cfg code="STATIC_FILE_VERSION" encode="false"/}'></script>
<script type="text/javascript" src='/template/shikong/js/index-247463.js?version=1{site:cfg code="STATIC_FILE_VERSION" encode="false"/}'></script>
<!-- <script type="text/javascript" src='/template/shikong/js/enc/qd.min.js?version={site:cfg code="STATIC_FILE_VERSION" encode="false"/}'></script> -->
<script type="text/javascript" src='/template/shikong/js/index-247463.js'></script>
{block name="head-js"}{/block}
@@ -72,7 +74,7 @@
</div>
<div class="s-main-box-middle" style="max-height:1rem">
<!-- <div class="s-main-box-middle" style="max-height:1rem">
<div
class="swiper swiper-top-zxcv swiper-initialized swiper-horizontal swiper-pointer-events swiper-ios swiper-backface-hidden">
<div class="swiper-wrapper">
@@ -88,7 +90,7 @@
</div>
<div class="swiper-pagination"></div>
</div>
</div>
</div> -->
<script>
@@ -112,7 +114,7 @@
{/if}
{novel:category d_key="strCategoryPinyin" d_val="strCategoryName"}
<a href='{$strPcPath}{site:nflurl category="$strCategoryPinyin" status="all" order="all" page="1"/}'>
<a href='{site:nflurl category="$strCategoryPinyin" status="all" order="all" page="1"/}'>
<div class="v-s-li-nav-link-vs_442378ea5a0a0b9d99bed43dc146baa0 " id="novel{$strCategoryPinyin}-page">{$strCategoryName}</div>
</a>
{/novel:category}
@@ -128,7 +130,7 @@
<div class="content-box">
<div style="margin-top:0px;width:100%;">
<!-- <div style="margin-top:0px;width:100%;">
<div class="main-box">
<div class="alert alert-primary" style="padding: 5px 10px;margin-bottom:0;border-radius:0px;"><strong><i
class="bi bi-bell-fill"></i></strong>
@@ -147,13 +149,12 @@
</div>
</div>
</div>
</div>
</div> -->
<div class="item-box" style="margin-top:0;">
<div class="main-box">
<div class="index-items-wrap">
<!-- <div class="index-items-wrap">
<div class="grid-box-s2">
<div>
<img class="pre-img lozad"
data-src="{gg_tu_pian}?v={site:cfg code='STATIC_FILE_VERSION' encode='false'/}"
@@ -163,9 +164,9 @@
</a>
</div>
</div>
</div>
</div> -->
<div class="p-card-box">
<!-- <div class="p-card-box">
<dl>
<dt>
@@ -178,13 +179,15 @@
</dt>
</dl>
</div>
</div> -->
</div>
</div>
</div>
{block name="main"} {site:wz wz="主内容" /}{/block}
{block name="main"}
{/block}
{include file="public/footer" /}
@@ -192,7 +195,11 @@
{/block}
{site:site valcode="site_tongji" encode="false"/}
<!-- 全局统计 -->
{site:cfg code="PUBLIC_TONGJI_CODE" encode="false"/}
<!-- 站点统计 -->
{$DomainModel->d_statis|raw}
</body>

View File

@@ -40,80 +40,180 @@
{/block}
{block name="main"}
{site:grm page_code="h5_index" diff="0" num="100" g_key="arrGrm" /}
<h2 class="site-description">{$DomainModel->d_index_description}</h2>
<div class="wrap-box" style="margin-top:0;">
<h3 class="wrap-title"><span>封面推荐</span></h3>
<div class="rec-focus">
{novel:list count="8" sort_type="tuijian" d_key="d_key" d_val="Novel" p_val="page_data" cache_life="86400"}
<dl class="rec-focus-book">
<dt class="book-img">
{$arrGrm[$d_key]|raw}
<a href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}'>
<img height="100" width="80" alt="{$Novel.n_name ?? ''} - {$Novel.n_category ?? ''}最新章节在线免费阅读"
src="{$Novel.n_cover_path ?? ''}">
<div class="layout-root">
<div class="work-content">
<div class="entry-point">
<a class="entry-item" href="{$strCategoryIndexUrlTemp}">
<div class="icon icon-category"></div>
<span>分类</span>
</a>
</dt>
<dd class="book-info">
<h2><a href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}'>{$Novel.n_name}</a></h2>
<p>作者:{$Novel.n_author}</p>
<p>{$Novel.n_description}</p>
</dd>
</dl>
{/novel:list}
<a class="entry-item" href="{$strRankUrlTemp}">
<div class="icon icon-rank"></div>
<span>排行</span>
</a>
<a class="entry-item" href="{$strBookShelfUrlTemp}">
<div class="icon icon-category"></div>
<span>书架</span>
</a>
</div>
<div class="section">
{include file="public/index-item-head" strItemTiele="抖音热搜" strItemHref="tuijian" /}
<div class="js-tabs">
<div class="tab-content-wrap">
<div class="">
<div class="novel-list">
{novel:list count="8" sort_type="tuijian" d_key="key" d_val="Novel" cache_life="86400"}
{include file="public/novel-list" /}
{/novel:list}
</div>
</div>
</div>
</div>
</div>
<div class="section">
{include file="public/index-item-head" strItemTiele="主编力推" strItemHref="tuijian" /}
<div class="js-tabs">
<div class="tab-content-wrap">
<div class="">
<div class="work-list">
{php}
$showIconStatus = "zhuantai";
{/php}
{novel:list count="8" sort_type="tuijian" d_key="key" d_val="Novel" cache_life="86400"}
{include file="public/novel-list-flex" /}
{/novel:list}
</div>
</div>
</div>
</div>
</div>
<div class="section">
{include file="public/index-item-head" strItemTiele="热门经典" strItemHref="tuijian" /}
<div class="js-tabs">
<div class="tab-content-wrap">
<div class="">
<div class="novel-list">
{novel:list count="8" sort_type="update" d_key="key" d_val="Novel" cache_life="86400"}
{include file="public/novel-list" showIconStatus=true/}
{/novel:list}
</div>
</div>
</div>
</div>
</div>
<div class="section">
{include file="public/index-item-head" strItemTiele="新书上架" strItemHref="news" /}
<div class="js-tabs">
<div class="tab-content-wrap">
<div class="">
<div class="work-list">
{php}
$showIconStatus = "zhuantai";
{/php}
{novel:list count="8" sort_type="news" d_key="key" d_val="Novel" cache_life="86400"}
{include file="public/novel-list-flex" /}
{/novel:list}
</div>
</div>
</div>
</div>
</div>
<div class="section">
{include file="public/index-item-head" strItemTiele="人气排行榜" strItemHref="news" /}
<div class="js-tabs">
<div class="tab-content-wrap">
<div class="">
<div class="novel-list">
{novel:ranklist count="10" sort_type="total" n_sex="man" d_key="key" d_val="Novel" cache_life="86400"}
{php}
$showIconStatus = true;
{/php}
{include file="public/novel-list" /}
{/novel:ranklist}
</div>
</div>
</div>
</div>
</div>
<div class="section">
{include file="public/index-item-head" strItemTiele="日排行榜" strItemHref="news" /}
<div class="js-tabs-line">
<div class="tab-content-wrap">
<div class="">
<div class="work-list">
{novel:ranklist count="10" sort_type="daily" n_sex="man" d_key="key" d_val="Novel" cache_life="86400"}
{php}
$showIconStatus = "paixu";
{/php}
{include file="public/novel-list-flex" /}
{/novel:ranklist}
</div>
</div>
</div>
</div>
</div>
<div class="section">
{include file="public/index-item-head" strItemTiele="最近更新" strItemHref="update" /}
<div class="js-tabs">
<div class="tab-content-wrap">
<div class="">
<div class="novel-list mei_ri_gen_xin_list">
{novel:list count="20" sort_type="update" d_key="key" d_val="Novel" cache_life="86400"}
<a href="" class="list-header">
<div class="block_txt ">
<h2>{$Novel.n_name}</h2>
<p class="xiaoshuo_info">
<span>{$Novel.n_category}/ <span>{$Novel.n_author} </span></span>
<span>{:date('m-d')}</span></p>
</div>
</a>
{/novel:list}
</div>
</div>
</div>
</div>
</div>
<div class="flex flex-between w-btn-box">
<a href="{$strRankUrlTemp}">
<div class="w-btn rank-btn">
<div class="icon"></div>
<div class="label">全部排行</div>
</div>
</a>
<a href="{$strCategoryIndexUrlTemp}">
<div class="w-btn category-btn">
<div class="icon"></div>
<div class="label">全部分类</div>
</div>
</a>
</div>
</div>
</div>
</div>
{novel:category d_key="strCategoryPinyin" d_val="strCategoryName"}
<div class="wrap-box">
<h3 class="wrap-title">
<span>{$strCategoryName}</span>
<a class="more" href='{site:nflurl category="$strCategoryPinyin" status="all" order="all" page="1"/}'>更多..</a>
</h3>
<div class="sort-box">
<dl class="sort-book-first">
<?php $start = 1 ;$start +=1 ;?>
{novel:list count="1" n_category="$strCategoryPinyin" sort_type="news" d_key="d_key" d_val="Novel"
p_val="page_data" cache_life="86400"}
<dt class="book-img">
{$arrGrm[$d_key+8+10*$start]|raw}
<a href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}'><img
height="100" width="80" class="lazyload-img" data-encrypted="false"
src="/static/img/default.jpg" data-src="{$Novel.n_cover_path ?? ''}"
alt="{$Novel.n_name ?? ''} - {$Novel.n_category ?? ''}最新章节在线免费阅读"></a></dt>
<dd class="book-info">
<h4><a href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}'>{$Novel.n_name}</a></h4>
<p>作者:{$Novel.n_author}</p>
<p>{$Novel.n_description}</p>
</dd>
{/novel:list}
</dl>
<ul class="sort-book-list">
{novel:list count="9" n_category="$strCategoryPinyin" sort_type="news" d_key="d_key" d_val="Novel"
p_val="page_data" cache_life="86400"}
<li>
{$arrGrm[$d_key+8+10*$start]|raw}
<a
href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}'>{$Novel.n_name}</a><span>{$Novel.n_author}</span>
</li>
{/novel:list}
</ul>
</div>
</div>
{/novel:category}
{/block}
{block name="customize"}

View File

@@ -59,117 +59,96 @@
{novel:pagerexp page="$Request.get.page" limit="30"
n_category="$Request.route.strCategory"
sort_type="$Request.route.strOrder"
n_status="$Request.route.strStatus" d_key="d_key"
n_status="$Request.route.strStatus"
d_key="d_key"
d_val="Novel" n_num="total"
button_num="5" cache_life="86400" func="generateCategoryPager" export_name="resData" /}
d_val="Novel"
button_num="8" cache_life="86400" func="generateCategoryPager" export_name="resData" /}
{site:grm page_code="h5_novel_library" diff="$resData.p_data.page" num="40" g_key="arrGrm" /}
<p class="site-description">{$strDescription??''}</p>
<div class="layout-root">
<div id="classify">
<div class="w-category">
<div class="type">
<div class="list">
<div class="navpf">
<nav class="sortChannel_nav">
<a class="on">分类:</a>
<a class='{eq name="$Request.route.strCategory" value="all"}on on2 {/eq} {if !$Request.route.strCategory || $Request.route.strCategory == ""}on on2 {/if}'
href='{site:nflurl category="all" status="$Request.route.strStatus" order="$Request.route.strOrder" page="$Request.route.intPage"/}'>全部分类</a>
<div class="item">
<a href="" class="text " id="fenlei_0">{site:wz wz="全部" /}</a>
</div>
{novel:category d_key="strCategoryPinyin" d_val="strCategoryName"}
{novel:category d_key="strCategoryPinyin" d_val="strCategoryName"}
<div class="item">
<a href='{site:nflurl category="$strCategoryPinyin" status="$Request.route.strStatus" order="$Request.route.strOrder" page="$Request.route.intPage"/}'
id="fenlei_{$strCategoryPinyin}" class="text ">
{$strCategoryName}</a>
</div>
{/novel:category}
<script>
$(function () {
let pageId = "#fenlei_{$Request.route.strCategory}"
$(pageId).addClass("active")
})
</script>
</div>
</div>
<div class="sort">
<div class="list">
{novel:sort d_key="key" d_val="strSortName"}
<div class="item" id="paixu_{$key}">
<a href='{site:nflurl category="$Request.route.strCategory" order="$key" page="$Request.route.intPage"/}'
class="text">{$strSortName}</a>
</div>
{/novel:sort}
</div>
<a class='{eq name="$Request.route.strCategory" value="$strCategoryPinyin"}on on2 {/eq}'
href='{site:nflurl category="$strCategoryPinyin" status="$Request.route.strStatus" order="$Request.route.strOrder" page="$Request.route.intPage"/}'>{$strCategoryName}</a>
{/novel:category}
</nav>
<nav class="sortChannel_nav">
<a class="on">排序:</a>
{novel:sort d_key="key" d_val="strSortName"}
<a href='{site:nflurl category="$Request.route.strCategory" status="$Request.route.strStatus" order="$key" page="$Request.route.intPage"/}'
class='{eq name="$Request.route.strOrder" value="$key"}on on2 {/eq} {if $key == "all" && $Request.route.strOrder == ""}on on2 {/if}'>{$strSortName}</a>
{/novel:sort}
</nav>
<nav class="sortChannel_nav">
<a class="on">状态:</a>
{novel:status d_key="key" d_val="strStatusName"}
<a href='{site:nflurl category="$Request.route.strCategory" status="$key" order="$Request.route.strOrder" page="$Request.route.intPage"/}'
class='{eq name="$Request.route.strStatus" value="$key"}on on2 {/eq} {if $key == "all" && $Request.route.strStatus == ""}on on2 {/if}'
btn="search_category">{$strStatusName}</a>
{/novel:status}
</nav>
</div>
<div class="wrap-box">
<h3 class="wrap-title"><span>更新列表</span></h3>
<ul class="sort_list">
{foreach $resData.data as $key=>$Novel}
<script>
$(function () {
let pageId = "#paixu_{$Request.route.strOrder}"
$(pageId).addClass("active")
})
</script>
<li>
<span class="s1">[{$Novel.n_category}]</span>
<span class="s2">
{$arrGrm[$key]|raw}
<a href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}' data-toggle="tooltip"
data-placement="right" title="{$Novel.n_name}">
{$Novel.n_name}
</a>
</span>
<span class="s4">{$Novel.n_author}</span>
<span class="s5">{:date('m-d')}</span>
</li>
{/foreach}
</ul>
</div>
</div>
</div>
<div class="content">
<div class="cartoon-list">
<div class="novel-list">
{foreach $resData.data as $key=>$Novel}
{include file="public/novel-list" /}
{/foreach}
</div>
</div>
<div class="wrap" style="display: block; padding-bottom: 1px;">
<ul class="pagination justify-content-center">
{volist name="resData.p_data.pager" id="vo" key="k"}
{switch $vo.label}
{case value="上一页"}
{if $resData.p_data.page == 1}
<li class="page-item disabled"><span class="page-link">«</span></li>
{else}
<li class="page-item"><a class="page-link" href="{$vo.url}">«</a></li>
{/if}
{/case}
{case value="下一页"}
{if $resData.p_data.page >= $resData.p_data.total}
<li class="page-item disabled"><span class="page-link">»</span></li>
{else}
<li class="page-item"><a class="page-link" href="{$vo.url}">»</a></li>
{/if}
{/case}
{default /}
{if preg_match('/^\d+$/', $vo.label)}
<li class="page-item"><a class="page-link" href="{$vo.url}">{$vo.label}</a></li>
{/if}
{/switch}
{/volist}
</ul>
</div>
<div class="row sort_page_num">
{volist name="resData.p_data.pager" id="vo" key="k"}
{switch $vo.label}
{case value="上一页"}
{if $resData.p_data.page == 1}
<span>«</span>
{else}
<a href="{$vo.url}">«</a>
{/if}
{/case}
{case value="下一页"}
{if $resData.p_data.page >= $resData.p_data.total}
<span>»</span>
{else}
<a href="{$vo.url}">»</a>
{/if}
{/case}
{default /}
{if preg_match('/^\d+$/', $vo.label)}
<a href="{$vo.url}">{$vo.label}</a>
{/if}
{/switch}
{/volist}
</div>
<div class="wrap-box">
<h3 class="wrap-title">
<span>封面推荐</span>
</h3>
<div class="rec-focus">
{novel:list count="8" sort_type="tuijian" d_key="d_key" d_val="Novel" p_val="page_data" cache_life="86400"}
<dl class="rec-focus-book">
<dt class="book-img">
{$arrGrm[$d_key+30]|raw}
<a href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}'>
<img height="100" width="80" class="lazyload-img" src="/static/img/default.jpg"
data-src="{$Novel.n_cover_path ?? ''}"
alt="{$Novel.n_name ?? ''} - {$Novel.n_category ?? ''}最新章节在线免费阅读">
</a>
</dt>
<dd class="book-info">
<h2>
<a href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}'>
{$Novel.n_name}
</a>
</h2>
<p>作者:{$Novel.n_author}</p>
<p>{$Novel.n_description}</p>
</dd>
</dl>
{/novel:list}
</div>
</div>
</div>

View File

@@ -0,0 +1,114 @@
{extend name="baseH5" /}
{block name="get-data"}
{site:helper func="initRankTKD" /}
{/block}
{block name="title"}{site:replace code="NOVEL@GETNOVELRANK@TITLE"}{/block}
{block name="keywords"}{site:replace code="NOVEL@GETNOVELRANK@KEYWORDS"}{/block}
{block name="description"}{site:replace code="NOVEL@GETNOVELRANK@DESCRIPTION"}{/block}
{block name="head"}
<!-- 社交媒体标签 -->
<meta property="og:title" content='{site:replace code="NOVEL@GETNOVELRANK@TITLE"}' />
<meta property="og:description" content='{site:replace code="NOVEL@GETNOVELRANK@DESCRIPTION"}' />
<meta property="og:url" content="https://{$DomainModel->d_domain}/paihang/all" />
<meta property="og:type" content="book" />
<!-- 结构化数据 -->
<script type="application/ld+json">
{
"@context": "https://{$DomainModel->d_domain}/paihang/all",
"@type": "book",
"headline": '{site:replace code="NOVEL@GETNOVELRANK@TITLE"}',
"description": '{site:replace code="NOVEL@GETNOVELRANK@DESCRIPTION"}',
"datePublished": "{:date('Y-m-d')}"
}
</script>
{/block}
{block name="head-js"}{/block}
{block name="logo-html"}
<h1 class="logo">
<a href="/">{$DomainModel->d_name}--排行榜最新免费阅读</a>
</h1>
{/block}
{block name="strPageCode"}
<?php $strPageCode = 'rank'; ?>
{/block}
{block name="main"}
{site:grm page_code="h5_rank" diff="0" num="100" g_key="arrGrm" /}
<div class="layout-root">
<div id="w-rank">
<div class="header">
<div class="back flex-center" onclick="history.go(-1)">
<div class="svg">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
<path
d="M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 246.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z">
</path>
</svg>
</div>
</div>
<div class="navs">
<a href='{site:rankurl status="$Request.route.strStatus" order="all" page="1"/}'
id="pai_hang_all" class="tabs-item">所有</a>
<a href='{site:rankurl order="$Request.route.strOrder" status="lianzai" page="$Request.route.intPage"/}'
id="pai_hang_lianzai" class="tabs-item">连载中</a>
<a href='{site:rankurl order="$Request.route.strOrder" status="wanjie" page="$Request.route.intPage"/}'
id="pai_hang_wanjie" class="tabs-item">已完结</a>
</div>
<script>
$(function(){
$("#pai_hang_{$Request.route.strStatus}").addClass("active")
})
</script>
</div>
<div class="wrap">
<div class="side-left">
<div class="slide-box">
<a href="{$strCategoryIndexUrlTemp}" class="slide-item " id="fenlei_all">{site:wz wz="全部" /}</a>
<a href='{site:rankurl status="$Request.route.strStatus" order="daily" page="$Request.route.intPage"/}'
id="fenlei_daily" class="slide-item ">日榜</a>
<a href='{site:rankurl status="$Request.route.strStatus" order="weekly" page="$Request.route.intPage"/}'
id="fenlei_weekly" class="slide-item ">周榜</a>
<a href='{site:rankurl status="$Request.route.strStatus" order="monthly" page="$Request.route.intPage"/}'
id="fenlei_monthly" class="slide-item ">月榜</a>
<a href='{site:rankurl status="$Request.route.strStatus" order="total" page="$Request.route.intPage"/}'
id="fenlei_total" class="slide-item ">总榜</a>
</div>
<script>
$(function(){
$(`#fenlei_{$Request.route.strOrder}`).addClass("active")
})
</script>
</div>
<div class="side-content">
<div class="novel-list mei_ri_gen_xin_list paihang-bang">
{novel:ranklist count="10" sort_type="$Request.route.strOrder" n_status="$Request.route.strStatus" d_key="d_key" d_val="Novel" cache_life="86400"}
<a href='{site:nurl n_id="$Novel.n_id" n_py="$Novel.n_name_pinyin"/}' class="list-header">
<div class="sort-index custom-box">{$key + 10 * $Request.route.intPage}</div>
<div class="block_txt ">
<h2>{$Novel.n_name}</h2>
<p class="xiaoshuo_info">
{$Novel.n_description}
</p>
</div>
</a>
{/novel:ranklist}
</div>
</div>
</div>
</div>
</div>
{/block}
{block name="customize"} {/block}

View File

@@ -1,24 +1,30 @@
<div class="footer">
<div class="links">
<a href="/">首页</a>
<a href="/boy.html">男生</a>
<a href="/girl.html">女生</a>
<a href="/shuku.html">书库</a>
<a href="/rank.html">排行</a>
</div>
<div id="firendlink">
友情连接:
<a href="/sitemap_index.xml">XML地图</a>
<a href="/site.txt">网站地图</a>
{site:forgelist count="30" d_key="d_key" d_val="ForgeNovel" cache_life="86400"}
<!-- footer -->
<div id="firendlink">
友情连接:
<a href="/sitemap_index.xml">XML地图</a>
<a href="/site.txt">网站地图</a>
{site:forgelist count="30" d_key="d_key" d_val="ForgeNovel" cache_life="86400"}
<a
href='{$strPcPath}{site:nnurl n_id="$ForgeNovel.n_id" n_py="$ForgeNovel.n_name_pinyin" n_fid="$ForgeNovel.n_forge_id"/}'>
href='{site:nnurl n_id="$ForgeNovel.n_id" n_py="$ForgeNovel.n_name_pinyin" n_fid="$ForgeNovel.n_forge_id"/}'>
{$ForgeNovel.n_forge_title}
</a>
{/site:forgelist}
</div>
<div class="copyright">
<p>精彩小说推荐尽在狂雨小说!</p>
<p>©Copyright 2020</p>
</div>
</div>
</div>
<div class="footer_cont"><p>本站所有小说为转载作品,所有章节均由网友上传,转载至本站只是为了宣传本书让更多读者欣赏。如有侵权,请发送邮箱,我们删除</p>
<p>Copyright © 2019 All Rights Reserved.</p></div>
<div class="s-footer-tel">
{site:wz wz="反馈邮箱:" /} {site:cfg code="YOU_XIANG" encode="false"/}
</div>
<div class="footer-box">{site:wz wz="牢记本站域名" /}
<a href="https://{$DomainModel->d_domain}">
{$DomainModel->d_domain}
</a>
</div>

View File

@@ -0,0 +1,16 @@
<div class="bg-top-pink bg-top-pink-minheight"></div>
<div class="title">
<div class="title-text">[strItemTiele]</div>
<div class="more">
<span class="icon">
<span class="icon__left-label">更多</span>
<a class="svg" href='{site:nflurl order="tuijian" page="1"/}'>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
<path
d="M310.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L242.7 256 73.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z">
</path>
</svg>
</a>
</span>
</div>
</div>

View File

@@ -0,0 +1,18 @@
<a href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}'>
<div class="novel-item">
<div class="top">
<img class="pre-img lozad" data-encrypted="false"
src="/assets/images/loading_img_bg_default.jpg"
data-src="{$Novel.n_cover_path}">
{if isset($showIconStatus) && $showIconStatus == 'paixu'}
<div class="icon-status">{$key + 1}</div>
{/if}
{if isset($showIconStatus) && $showIconStatus == 'zhuantai'}
<div class="icon-status">{$Novel.n_status}</div>
{/if}
</div>
<div class="bottom">{$Novel.n_name}</div>
</div>
</a>

View File

@@ -0,0 +1,25 @@
<div class="list-header">
<div class="block_img">
<a href='{site:nurl n_id="$Novel.n_id" n_py="$Novel.n_name_pinyin"/}'>
<img class="pre-img lozad" data-encrypted="false"
src="/assets/images/loading_img_bg_default.jpg"
data-src="{$Novel.n_cover_path}">
{if isset($showIconStatus) && $showIconStatus}
<div class="icon-status">{$key + 1}</div>
{/if}
</a>
</div>
<div class="block_txt">
<p class="p1">
<a href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}'></a>
</p>
<h2><a href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}'>{$Novel.n_name}</a></h2>
<p class="xiaoshuo_info"><span>{$Novel.n_category} </span><span> {$Novel.n_status}</span> <span> {$Novel.n_author}</span></p>
<p class="xiaoshuo_maioshu">
<a class="ellipsis" href='{site:nurl n_id="$Novel->n_id" n_py="$Novel->n_name_pinyin"/}'>
{$Novel.n_description}
</a>
</p>
</div>
</div>

View File

@@ -51,7 +51,7 @@ class CategoryModel extends MongoModel
'kehuan-xiaoshuo' => '科幻小说',
],
'women' => [
'zhongsheng-chuanyue' => '重生穿越',
'chongsheng-chuanyue' => '重生穿越',
'dushi-xiaoshuo' => '都市小说',
'lingyi-xiaoshuo' => '灵异小说',
'yanqing-xiaoshuo' => '言情小说',
@@ -64,7 +64,7 @@ class CategoryModel extends MongoModel
2 => 'junshi-xiaoshuo', // 军史-小说
3 => 'wangyou-xiaoshuo', // 网游-小说
4 => 'kehuan-xiaoshuo', // 科幻-小说
5 => 'zhongsheng-chuanyue', // 重生-穿越
5 => 'hongsheng-chuanyue', // 重生-穿越
6 => 'dushi-xiaoshuo', // 都市-小说
7 => 'lingyi-xiaoshuo', // 灵异-小说
8 => 'yanqing-xiaoshuo', // 言情-小说

View File

@@ -28,6 +28,7 @@ class ConverterMovel
'{strNovelCategoryName}' => '',
'{strNovelSex}' => '',
'{strNovelStatus}' => '',
'{strNovelOrder}' => '',
'{intPage}' => '',
'{strNovelAuthor}' => '',
'{strNovelDescription}' => '',
@@ -50,6 +51,7 @@ class ConverterMovel
'{strNovelCategoryName}' => '当前页面小说分类名字',
'{strNovelSex}' => '当前页面小说是男生还是女生 小说',
'{strNovelStatus}' => '当前页面小说状态 是连载还是完结',
'{strNovelOrder}' => '当前页面排行依据',
'{intPage}' => '当前页面分页页码',
'{strNovelAuthor}' => '小说作者',
'{strNovelDescription}' => '小说简介',
@@ -90,7 +92,9 @@ class ConverterMovel
*/
static public function getVal(string $strKey)
{
return self::$arrMap[self::getKey($strKey)];
$key = self::getKey($strKey);
return isset(self::$arrMap[$key]) ? (string) self::$arrMap[$key] : '';
// return self::$arrMap[self::getKey($strKey)];
}
/**

View File

@@ -214,22 +214,28 @@ class ChapterService
/**
* 根据NId获取小说详情
* 根据Id获取小说章节详情
*
* @param integer $intNId
* @param integer $intCSortNum
* @param integer $intCPage
* @return void
*/
public function getChapterInfo(int $intNId, int $intCSortNum, int $intCPage)
public function getChapterInfo(int $intNId, int $intCSortNum = 0, int $intCPage = 0)
{
// 小说详情
$arrNovel = $this->NovelModel->getNovelByNId($intNId);
// 章节
$ChapterModel = ChapterModel::getInstance();
$arrFilter = ['n_id' => $intNId, 'c_sort_num' => $intCSortNum, 'c_page' => $intCPage];
if($intCSortNum == 0 && $intCPage == 0){
// 最新章节
$arrChapter = $ChapterModel->getLatestChapterByNId($intNId);
}else{
// 章节
$arrFilter = ['n_id' => $intNId, 'c_sort_num' => $intCSortNum, 'c_page' => $intCPage];
$arrChapter = $ChapterModel->findOne($arrFilter);
}
$arrChapter = $ChapterModel->findOne($arrFilter);
$strChapterDescription = '';
// 上一章节和下一章节

View File

@@ -170,6 +170,32 @@ class NovelService
}
/**
* 排行榜url
* Undocumented function
*
* @param [type] $strGender
* @param [type] $strCategory
* @param [type] $strStatus
* @param [type] $strOrder
* @param [type] $intPage
* @return string
*/
public function getNovelRankUrl($strGender, $strCategory, $strStatus, $strOrder, $intPage): string
{
$strKey = 'RANK_LIST_URL';
$strUrl = $this->getPageUrl($strKey, [
'strGender' => !empty($strGender) ? $strGender : '',
'strCategory' => !empty($strCategory) ? $strCategory : 'all',
'strStatus' => !empty($strStatus) ? $strStatus : 'all',
'strOrder' => !empty($strOrder) ? $strOrder : 'all',
'intPage' => $intPage ?? 1,
]);
$strUrl = preg_replace('#/{2,}#', '/', $strUrl);
return (string)$strUrl;
}
/**
* Undocumented function
@@ -217,7 +243,7 @@ class NovelService
'update' => '最新更新',
];
public $arrRankSortType = [
static $arrRankSortType = [
'daily' => '天',
'weekly' => '周',
'monthly' => '月',
@@ -574,6 +600,23 @@ class NovelService
$intLifeTime = $intLifeTime;
}
// 更新值
$strGender = $this->SiteContext->Request->param('strGender');
$strNanUrlTemp = $this->SiteContext->DomainModel->getFomartSubject('NAN_SHENG_URL', '', false);
$strNanUrl = str_replace("/", "", $strNanUrlTemp);
$strCNSex = '全部';
if($strGender){
$strCNSex = $strGender == $strNanUrl ? '男生' : '女生';
}
ConverterMovel::setVal([
'intPage' => $intPage,
'strNovelSex' => $strCNSex,
'strNovelCategoryName' => empty($strNCategory) ? '' : str_replace("小说", "", $strNCategory),
'strNovelStatus' => empty($strNStatus) ? '' : $this->arrStatus[$strNStatus],
'strNovelOrder' => empty($strSortType) ? '' :$this->arrSortType[$strSortType],
'strSearchKeywords' => $strKey,
]);
if (empty($arrFilter['$and'])) {
$arrFilter = [];
}
@@ -651,7 +694,7 @@ class NovelService
* @param integer $intNId
* @return void
*/
public function getNovelByNId(int $intNId, int $intNForgeId = 0)
public function getNovelByNId(int $intNId, int|null $intNForgeId = 0)
{
// 小说详情

View File

@@ -165,6 +165,20 @@ class SiteContext
return ConverterMovel::convert($strTitleTemplate);
}
/**
* 获取 公共替换 变量
*
* @param string $strCode
* @return string
*/
public function getConverterVal(string $strCode): string
{
if (empty($strCode)) {
return ''; // 或返回默认值
}
return ConverterMovel::getVal($strCode);
}
/**
* 获取干扰码
@@ -274,4 +288,37 @@ class SiteContext
'strSiteName' => $this->DomainModel->d_name,
]);
}
/**
* 视图反向控制器(注释函数),在视图开头调用,用来初始化一些操作。这里尽量不要复杂逻辑。这是个样例
*
* @return void
*/
public function initSexTKD()
{
$strSex = $this->Request->param('strChannel');
ConverterMovel::setVal([
'intPage' => 1,
'strNovelSex' => $strSex == 'man' ? '男生' : '女生',
]);
}
/**
* 视图反向控制器(注释函数),在视图开头调用,用来初始化一些操作。这里尽量不要复杂逻辑。这是个样例
*
* @return void
*/
public function initRankTKD()
{
$strOrder = $this->Request->param('strOrder');
$strStatus = $this->Request->param('strStatus');
ConverterMovel::setVal([
'intPage' => 1,
'strNovelOrder' => NovelService::$arrRankSortType[$strOrder] ,
'strNovelStatus' => NovelService::$arrStatus[$strStatus] ,
]);
}
}