From c7978968f33cd0778c98988e776821e5a3603684 Mon Sep 17 00:00:00 2001 From: Default Date: Mon, 31 Mar 2025 23:14:52 +0800 Subject: [PATCH] seed --- code/app/admin/config/router.php | 13 +- .../admin/controller/{Domain.php => Site.php} | 107 +++++++++++- code/app/common.php | 13 ++ code/app/home/BaseController.php | 2 +- code/app/home/config/router.php | 82 +++++----- code/app/home/controller/Index.php | 16 +- code/app/home/controller/Novel.php | 110 +++++++++---- code/app/home/view/kuangyu/Pc/getLibrary.html | 52 +++--- code/app/home/view/kuangyu/basePc.html | 2 +- code/app/model/CategoryModel.php | 18 ++- code/app/model/ConverterMovel.php | 2 +- code/app/model/DomainModel.php | 52 ++++++ code/app/model/NovelModel.php | 43 +++-- code/app/model/SubjectFomartGroupModel.php | 19 +++ code/app/model/SubjectFomartModel.php | 17 ++ code/app/model/TemplatesModel.php | 18 +++ code/database/schema/mysql-schema.dump | 45 +++++- code/database/seeders/TemplateSeeder.php | 24 ++- code/extend/template/page/CusteomPage.php | 84 +++++----- code/extend/template/page/CusteomPage02.php | 152 ++++++++++++++++++ code/域名.xlsx | Bin 0 -> 8928 bytes 21 files changed, 686 insertions(+), 185 deletions(-) rename code/app/admin/controller/{Domain.php => Site.php} (53%) create mode 100644 code/app/model/SubjectFomartGroupModel.php create mode 100644 code/app/model/SubjectFomartModel.php create mode 100644 code/extend/template/page/CusteomPage02.php create mode 100644 code/域名.xlsx diff --git a/code/app/admin/config/router.php b/code/app/admin/config/router.php index b024377..a5e92d4 100644 --- a/code/app/admin/config/router.php +++ b/code/app/admin/config/router.php @@ -4,6 +4,7 @@ declare(strict_types=1); use app\admin\controller\Domain; use app\admin\controller\Novel; +use app\admin\controller\Site; use app\admin\middleware\AdminAuth; use think\facade\Route; @@ -39,9 +40,15 @@ Route::group("/novel", function () { # 站点 Route::group("/site", function () { - Route::get("/domain/list", [Domain::class, "getDomainList"])->name("Domain@getDomainList"); - Route::post("/domain/upload", [Domain::class, "uploadDomain"])->name("Domain@uploadDomain"); + # 域名管理 + Route::get("/domain/list", [Site::class, "getDomainList"])->name("Domain@getDomainList"); + Route::post("/domain/upload", [Site::class, "uploadDomain"])->name("Domain@uploadDomain"); + Route::post("/domain/save", [Site::class, "saveDomain"])->name("Domain@saveDomain"); - Route::get("/tkdarg/list", [Domain::class, "getTKDArgList"])->name("Domain@getDomainList"); + # TKD 参数模板 + Route::get("/tkdarg/list", [Site::class, "getTKDArgList"])->name("Domain@getTKDArgList"); + + # 视图模板 + Route::get("/template/list", [Site::class, "getTemplateList"])->name("Domain@getTKDArgList"); })->middleware(AdminAuth::class); diff --git a/code/app/admin/controller/Domain.php b/code/app/admin/controller/Site.php similarity index 53% rename from code/app/admin/controller/Domain.php rename to code/app/admin/controller/Site.php index 1434c27..76ee63f 100644 --- a/code/app/admin/controller/Domain.php +++ b/code/app/admin/controller/Site.php @@ -8,11 +8,13 @@ use app\admin\BaseController; use app\model\AdminUserModel; use app\model\ConverterMovel; use app\model\DomainModel; +use app\model\TemplatesModel; use app\Request; use PhpOffice\PhpSpreadsheet\IOFactory; use think\Response; -class Domain extends BaseController + +class Site extends BaseController { /** @@ -61,7 +63,7 @@ class Domain extends BaseController $arrDomain = [ 'd_domain' => $arrRows[0], 't_id' => $arrRows[1], - 'd_title' => $arrRows[2], + 'd_name' => $arrRows[2], 'd_keywords' => $arrRows[3], 'd_description' => $arrRows[4], 'd_statis' => $arrRows[5], @@ -69,7 +71,13 @@ class Domain extends BaseController 'd_text_log' => $arrRows[7], 'd_img_log' => $arrRows[8], ]; + + $TCfgTemplate = TemplatesModel::where('t_id', $arrDomain['t_id'])->find()->t_cfg_template; + + $arrDomain['t_cfg'] = json_encode($TCfgTemplate, JSON_UNESCAPED_UNICODE); + $DomainModel = DomainModel::where('d_domain', $arrDomain['d_domain'])->findOrEmpty(); + $DomainModel->fill($arrDomain); $DomainModel->save(); } @@ -129,4 +137,99 @@ class Domain extends BaseController return $this->success($arrResult); } + + + /** + * 添加|修改 域名 + * + * @param Request $Request + * @param AdminUserModel|null $AdminUserModel + * @return Response + */ + public function saveDomain(Request $Request, ?AdminUserModel $AdminUserModel) + { + $arrData = [ + "d_id" => $Request->post('d_id'), + "d_domain" => $Request->post('d_domain'), + "t_id" => $Request->post('t_id'), + "d_name" => $Request->post('d_name'), + "d_keywords" => $Request->post('d_keywords'), + "d_description" => $Request->post('d_description'), + "d_statis" => $Request->post('d_statis'), + "d_logo_type" => $Request->post('d_logo_type'), + "d_text_log" => $Request->post('d_text_log'), + "d_img_log" => $Request->post('d_img_log'), + "d_content_encode" => $Request->post('d_content_encode'), + "t_cfg" => $Request->post('t_cfg'), + ]; + + $arrRule = [ + // 'd_id' => 'require|number', + 'd_domain' => 'require', + 'd_logo_type' => 'require|number', + 'd_content_encode' => 'require|number', + 't_cfg' => 'require', + ]; + + $this->validate($arrData, $arrRule); + + if ($arrData['d_id']) { + $DomainModel = DomainModel::where('d_id', $arrData['d_id'])->findOrEmpty(); + } else { + $DomainModel = new DomainModel; + } + + $DomainModel->fill($arrData); + + $DomainModel->save(); + return $this->success(); + } + + /** + * 列表 + * + * @param Request $Request + * @param AdminUserModel|null $AdminUserModel + * @return Response + */ + public function getTemplateList(Request $Request, ?AdminUserModel $AdminUserModel) + { + $arrData = [ + "page" => $Request->get('page', 1), + "limit" => $Request->get('limit', 10), + "key" => $Request->get('key'), + ]; + + $arrRule = [ + 'page' => 'require|number', + 'limit' => 'require|number', + ]; + + $this->validate($arrData, $arrRule); + + $TemplatesModel = TemplatesModel::alias('t'); + + if (!empty($arrData['key'])) { + $strKey = $arrData['key']; + $TemplatesModel->where(function ($TemplatesModel) use ($strKey) { + $TemplatesModel->whereOr([ + ['t.t_code', 'like', "%" . $strKey . "%"], + ]); + }); + } + + $Paginate = $TemplatesModel->paginate([ + 'list_rows' => $arrData['limit'], + 'page' => $arrData['page'], + ]); + + $arrResult = [ + 'items' => $Paginate->items(), + 'total' => $Paginate->total(), + 'current_page' => $Paginate->currentPage(), + 'total_pages' => $Paginate->lastPage(), + ]; + + return $this->success($arrResult); + } } diff --git a/code/app/common.php b/code/app/common.php index 10da1e7..1556428 100644 --- a/code/app/common.php +++ b/code/app/common.php @@ -814,4 +814,17 @@ namespace { return $strPinYin; } + + + /** + * Undocumented function + * + * @param object $Obj + * @param string $strAction + * @return string + */ + function getFomartSubjectKey(string $strAction): string + { + return strtoupper(str_replace('::', '@', ltrim(strrchr($strAction, "\\"), "\\"))); + } } diff --git a/code/app/home/BaseController.php b/code/app/home/BaseController.php index f6122cd..176897f 100644 --- a/code/app/home/BaseController.php +++ b/code/app/home/BaseController.php @@ -75,7 +75,7 @@ abstract class BaseController private function initSiteTKD() { ConverterMovel::setVal([ - 'strSiteTitle' => $this->request->DomainModel->d_title, + 'strSiteName' => $this->request->DomainModel->d_name, 'strSiteKeywords' => $this->request->DomainModel->d_keywords, 'strSiteDescription' => $this->request->DomainModel->d_description, ]); diff --git a/code/app/home/config/router.php b/code/app/home/config/router.php index 529b96a..7e6a638 100644 --- a/code/app/home/config/router.php +++ b/code/app/home/config/router.php @@ -14,16 +14,16 @@ use think\facade\Route; /** * 首页 */ -Route::get("/", [Index::class,'index'])->ext('html')->append(['boolIsMobile' => true]); -Route::get("/pc/", [Index::class,'getPcIndex'])->append(['boolIsMobile' => false]); +Route::get("/", [Index::class, 'index'])->ext('html')->append(['boolIsMobile' => true]); +Route::get("/pc/", [Index::class, 'getPcIndex'])->append(['boolIsMobile' => false]); // Route::get("/index", [Index::class,'index'])->ext('html')->append(['boolIsMobile' => true]); // Route::get("/pc/index", [Index::class,'getPcIndex'])->ext('html')->append(['boolIsMobile' => false]); //排行榜 -Route::get('/paihang/all', [Novel::class,'getNovelRank'])->append(['boolIsMobile' => true]); -Route::get("/pc/paihang/all", [Novel::class,'getNovelRank'])->append(['boolIsMobile' => false]); +Route::get('/paihang/all', [Novel::class, 'getNovelRank'])->append(['boolIsMobile' => true]); +Route::get("/pc/paihang/all", [Novel::class, 'getNovelRank'])->append(['boolIsMobile' => false]); /** * 男生/女生 - grok 推荐最优方案 @@ -38,22 +38,22 @@ Route::get('/pc/nvsheng-xiaoshuo', [Novel::class, 'getNovelChannel'])->append([ * 书库 - grok 推荐最优方案 * /shuku/channel-category-status-page */ -Route::get('/shuku/all', [Novel::class,'getLibrary'])->append(['boolIsMobile' => true]); -Route::get('/pc/shuku/all', [Novel::class,'getLibrary'])->append(['boolIsMobile' => false]); -Route::get('/shuku/:intGender-:strCategory-:strStatus-:intPage', [Novel::class,'getLibrary']) +Route::get('/shuku/all', [Novel::class, 'getLibrary'])->append(['boolIsMobile' => true]); +Route::get('/pc/shuku/all', [Novel::class, 'getLibrary'])->append(['boolIsMobile' => false]); +Route::get('/shuku/:strGender/:strCategory/:strStatus/page:intPage', [Novel::class, 'getLibrary']) ->pattern([ - 'intGender' => '\d{1}', - 'strCategory' => '[\w]*', - 'strStatus' => '[\w]*', + 'strGender' => 'nansheng-xiaoshuo|nvsheng-xiaoshuo|all', + 'strCategory' => '[a-z\-]+', + 'strStatus' => 'all|lianzai|wanjie', 'intPage' => '\d+' ]) ->append(['boolIsMobile' => true]); -Route::get('/pc/shuku/:intGender-:strCategory-:strStatus-:intPage', [Novel::class,'getLibrary']) +Route::get('/pc/shuku/:strGender/:strCategory/:strStatus/page:intPage', [Novel::class, 'getLibrary']) ->pattern([ - 'intGender' => '\d{1}', - 'strCategory' => '[\w]*', - 'strStatus' => '[\w]*', + 'strGender' => 'nansheng-xiaoshuo|nvsheng-xiaoshuo|all', + 'strCategory' => '[a-z\-]+', + 'strStatus' => 'all|lianzai|wanjie', 'intPage' => '\d+' ]) ->append(['boolIsMobile' => false]); @@ -66,18 +66,18 @@ Route::get('/pc/shuku/:intGender-:strCategory-:strStatus-:intPage', [Novel::clas */ Route::get('/xiaoshuo/:name-:intNovelId/zhang-:intChapterSort/[:intChapterPage]', [Novel::class, 'getNovelChapter']) ->append(['boolIsMobile' => true, 'intUriType' => 1]) - ->pattern(['intNovelId' => '\d+','name' => '[\w-]+','intChapterId' => '\d+','intChapterPage' => '\d+']); + ->pattern(['intNovelId' => '\d+', 'name' => '[\w-]+', 'intChapterId' => '\d+', 'intChapterPage' => '\d+']); Route::get('/pc/xiaoshuo/:name-:intNovelId/zhang-:intChapterSort/[:intChapterPage]', [Novel::class, 'getNovelChapter']) ->append(['boolIsMobile' => false, 'intUriType' => 1]) - ->pattern(['intNovelId' => '\d+','name' => '[\w-]+','intChapterSort' => '\d+','intChapterPage' => '\d+']); + ->pattern(['intNovelId' => '\d+', 'name' => '[\w-]+', 'intChapterSort' => '\d+', 'intChapterPage' => '\d+']); /** * 最新章节-特殊页面处理 -*/ + */ Route::get('/pc/books/:name-:n_id/chapter/latest', [Novel::class, 'getNovelNewsChapter']) ->append(['boolIsMobile' => false, 'intUriType' => 1]) - ->pattern(['n_id' => '\d+','name' => '[\w-]+',]); + ->pattern(['n_id' => '\d+', 'name' => '[\w-]+',]); /** @@ -86,11 +86,11 @@ Route::get('/pc/books/:name-:n_id/chapter/latest', [Novel::class, 'getNovelNewsC */ Route::get('/xiaoshuo/:name-:intNovelId/mulu/:strOrder/[:intPage]', [Novel::class, 'getNovelChapterAll']) ->append(['boolIsMobile' => true, 'intUriType' => 1]) - ->pattern(['intNovelId' => '\d+','name' => '[\w-]+','strOrder' => 'zheng|dao','intPage' => '\d+']); + ->pattern(['intNovelId' => '\d+', 'name' => '[\w-]+', 'strOrder' => 'zheng|dao', 'intPage' => '\d+']); Route::get('/pc/xiaoshuo/:name-:intNovelId/mulu/:strOrder/[:intPage]', [Novel::class, 'getNovelChapterAll']) ->append(['boolIsMobile' => false, 'intUriType' => 1]) - ->pattern(['intNovelId' => '\d+','name' => '[\w-]+','strOrder' => 'zheng|dao','intPage' => '\d+']); + ->pattern(['intNovelId' => '\d+', 'name' => '[\w-]+', 'strOrder' => 'zheng|dao', 'intPage' => '\d+']); /** * 小说详情 @@ -103,57 +103,57 @@ Route::get('/pc/xiaoshuo/:name-:intNovelId/mulu/:strOrder/[:intPage]', [Novel::c */ Route::get('/pc/book/:name-:n_id', [Novel::class, 'getNovelInfo']) ->append(['boolIsMobile' => false, 'intUriType' => 1]) - ->pattern(['n_id' => '\d+','name' => '[\w-]+',]); + ->pattern(['n_id' => '\d+', 'name' => '[\w-]+',]); Route::get('/pc/novel/:name-:n_id', [Novel::class, 'getNovelInfo']) ->append(['boolIsMobile' => false, 'intUriType' => 2]) - ->pattern(['n_id' => '\d+','name' => '[\w-]+',]); + ->pattern(['n_id' => '\d+', 'name' => '[\w-]+',]); Route::get('/pc/xiaoshuo/:name-:n_id', [Novel::class, 'getNovelInfo']) ->append(['boolIsMobile' => false, 'intUriType' => 2]) - ->pattern(['n_id' => '\d+','name' => '[\w-]+',]); + ->pattern(['n_id' => '\d+', 'name' => '[\w-]+',]); Route::get('/pc/book-:name-:n_id', [Novel::class, 'getNovelInfo']) ->append(['boolIsMobile' => false, 'intUriType' => 3]) - ->pattern(['n_id' => '\d+','name' => '[\w-]+',]); + ->pattern(['n_id' => '\d+', 'name' => '[\w-]+',]); Route::get('/pc/novel-:name-:n_id', [Novel::class, 'getNovelInfo']) ->append(['boolIsMobile' => false, 'intUriType' => 3]) - ->pattern(['n_id' => '\d+','name' => '[\w-]+',]); + ->pattern(['n_id' => '\d+', 'name' => '[\w-]+',]); Route::get('/pc/xiaoshuo-:name-:n_id', [Novel::class, 'getNovelInfo']) ->append(['boolIsMobile' => false, 'intUriType' => 3]) - ->pattern(['n_id' => '\d+','name' => '[\w-]+',]); + ->pattern(['n_id' => '\d+', 'name' => '[\w-]+',]); + - // 搜索小说 -Route::get('/search', [Novel::class,'getSearchNovel'])->ext('html')->append(['boolIsMobile' => true]); -Route::get('/pc/search', [Novel::class,'getSearchNovel'])->ext('html')->append(['boolIsMobile' => false]); +Route::get('/search', [Novel::class, 'getSearchNovel'])->ext('html')->append(['boolIsMobile' => true]); +Route::get('/pc/search', [Novel::class, 'getSearchNovel'])->ext('html')->append(['boolIsMobile' => false]); // 小说用户中心 -Route::get('/user', [User::class,'Index'])->append(['boolIsMobile' => true]); -Route::get('/pc/user', [User::class,'Index'])->append(['boolIsMobile' => false]); +Route::get('/user', [User::class, 'Index'])->append(['boolIsMobile' => true]); +Route::get('/pc/user', [User::class, 'Index'])->append(['boolIsMobile' => false]); // 书架 -Route::get('/bookshelf', [User::class,'getBookShelf'])->append(['boolIsMobile' => true]); -Route::get('/pc/bookshelf', [User::class,'getBookShelf'])->append(['boolIsMobile' => false]); +Route::get('/bookshelf', [User::class, 'getBookShelf'])->append(['boolIsMobile' => true]); +Route::get('/pc/bookshelf', [User::class, 'getBookShelf'])->append(['boolIsMobile' => false]); // 历史记录 -Route::get('/history', [User::class,'getHistory'])->append(['boolIsMobile' => true]); -Route::get('/pc/history', [User::class,'getHistory'])->append(['boolIsMobile' => false]); +Route::get('/history', [User::class, 'getHistory'])->append(['boolIsMobile' => true]); +Route::get('/pc/history', [User::class, 'getHistory'])->append(['boolIsMobile' => false]); // 文章 列表 -Route::get('/article/list-[:intCategoryId]-[:intPage]', [Novel::class,'getArticleList'])->append(['boolIsMobile' => true]); -Route::get('/pc/article/list-[:intCategoryId]-[:intPage]', [Novel::class,'getArticleList'])->append(['boolIsMobile' => false]); -Route::get('/article/list', [Novel::class,'getArticleList'])->append(['boolIsMobile' => true]); -Route::get('/pc/article/list', [Novel::class,'getArticleList'])->append(['boolIsMobile' => false]); +Route::get('/article/list-[:intCategoryId]-[:intPage]', [Novel::class, 'getArticleList'])->append(['boolIsMobile' => true]); +Route::get('/pc/article/list-[:intCategoryId]-[:intPage]', [Novel::class, 'getArticleList'])->append(['boolIsMobile' => false]); +Route::get('/article/list', [Novel::class, 'getArticleList'])->append(['boolIsMobile' => true]); +Route::get('/pc/article/list', [Novel::class, 'getArticleList'])->append(['boolIsMobile' => false]); // 文章 详情 -Route::get('/article/info-:intArticleId', [Novel::class,'getArticleInfo'])->append(['boolIsMobile' => true]); -Route::get('/pc/article/info-:intArticleId', [Novel::class,'getArticleInfo'])->append(['boolIsMobile' => false]); +Route::get('/article/info-:intArticleId', [Novel::class, 'getArticleInfo'])->append(['boolIsMobile' => true]); +Route::get('/pc/article/info-:intArticleId', [Novel::class, 'getArticleInfo'])->append(['boolIsMobile' => false]); diff --git a/code/app/home/controller/Index.php b/code/app/home/controller/Index.php index 4d5d56e..7ea7299 100644 --- a/code/app/home/controller/Index.php +++ b/code/app/home/controller/Index.php @@ -6,6 +6,7 @@ namespace app\home\controller; use app\home\BaseController; use app\model\ConverterMovel; +use app\model\DomainModel; use app\model\NovelModel; use storage\StorageCore; use think\facade\View; @@ -161,6 +162,11 @@ class Index extends BaseController // 最近更新-随机50 $arrNewsUpdateNovel = $NovelModel->getSexNovelOnCache($Request->DomainModel->d_domain, 50); + $strTitle = $Request->DomainModel->getFomartSubject(getFomartSubjectKey(__METHOD__)); + + $strTitle = ConverterMovel::convert($strTitle); + + View::assign([ 'arrNewsUpdateNovel' => $arrNewsUpdateNovel, 'arrRecommendSerializationNovel' => $arrRecommendSerializationNovel, @@ -174,17 +180,11 @@ class Index extends BaseController 'arrGirlMoonRankNovel' => $arrGirlMoonRankNovel, 'arrBGirlTotalRankNovel' => $arrBGirlTotalRankNovel, 'arrAdBanner' => [], - 'strPageCode' => 'home' + 'strPageCode' => 'home', + 'strTitle' => $strTitle, ]); - $strTitle = '最新小说网-{strSiteTitle}-{strSiteKeywords}'; - - $strTitle = ConverterMovel::convert($strTitle); - - echo $strTitle;exit; - - if ($boolIsMobile) { return View::fetch(); } else { diff --git a/code/app/home/controller/Novel.php b/code/app/home/controller/Novel.php index 6d5cf4a..aab4673 100644 --- a/code/app/home/controller/Novel.php +++ b/code/app/home/controller/Novel.php @@ -5,11 +5,13 @@ declare(strict_types=1); namespace app\home\controller; use app\home\BaseController; +use app\model\CategoryModel; use app\model\ConverterMovel; use app\model\NovelModel; use storage\StorageCore; use think\facade\View; use app\Request; +use template\page\CusteomPage02; class Novel extends BaseController { @@ -131,53 +133,90 @@ class Novel extends BaseController * @param integer $intPage 分页 * @return void */ - public function getLibrary(Request $Request) //, $strNovelChannel = 'all', $strCategory = 'all', $strStatus = 'all', $intPage = 1) + public function getLibrary(Request $Request, $strGender = 'all', $strCategory = 'all', $strStatus = 'all', $intPage = 1) { $boolIsMobile = $Request->param('boolIsMobile'); - $intGender = (int)$Request->param('intGender',0); - $strCategory = (string)$Request->param('strCategory'); - $strStatus = (string)$Request->param('strStatus'); + // 性别 + + $arrSex = [ + 'all' => 0, + 'nansheng-xiaoshuo' => 1, + 'nvsheng-xiaoshuo' => 1, + ]; + + if (!key_exists($strGender, $arrSex)) { + return response('Bad Request', 400); + } + + $intGender = $arrSex[$strGender]; + + // 分类 + // $strCategory = $Request->param('strCategory'); + + if ($strCategory == 'all') { + $strSearchCategory = NULL; + } else if (!in_array($strGender, CategoryModel::$arrCategoryPinYin)) { + return response('Bad Request', 400); + } else { + $strCategoryKey = array_search($strGender, CategoryModel::$arrCategoryPinYin); + $strSearchCategory = CategoryModel::$arrCategory[$strCategoryKey]; + } + + // 小说状态 + // $strStatus = $Request->param('strStatus'); + $arrStatus = [ + 'all' => NULL, + 'lianzai' => '连载中', + 'wanjie' => '已完结', + ]; + + if (!key_exists($strStatus, $arrStatus)) { + return response('Bad Request', 400); + } + + $strSearchStatus = $arrStatus[$strStatus]; + + $intPage = (int)$Request->param('intPage'); + if ($intPage <= 1) { + $intPage = 1; + } $intLimit = 20; $intLifeTime = 24 * 3600; + $strKey = sprintf("Novel:Library:%s:%s:%s:%s", $intGender, $strSearchCategory, $strSearchStatus, $intPage); + + $NovelModel = new NovelModel; + $arrPage = $NovelModel->getCommonNovelPageOnCache($strKey, $intPage, $intLimit, $intLifeTime, $intGender, $strSearchStatus); - $strKey = sprintf("Novel:Library:%s:%s:%s:%s", $intGender, $strCategory, $strStatus, $intPage); - // var_dump($intType);exit; - $arrPage = $NovelModel->getCommonNovelPageOnCache($strKey, $intPage, $intLimit, $intLifeTime, $intGender, $strStatus); + $strTemplate = NULL; + $intButtomNum = 5; + if ($boolIsMobile == false) { + $intButtomNum = 10; + $strTemplate = 'pc/getLibrary'; + } - // echo '
';
-        // print_r($arrPage);
-        // exit;
-
-        // 模拟数据
-        $arrNovel = [
-            ['n_id' => 1, 'name' => '小说1', 'author' => '作者1'],
-            ['n_id' => 2, 'name' => '小说2', 'author' => '作者2'],
-            ['n_id' => 3, 'name' => '小说3', 'author' => '作者3'],
-            ['n_id' => 4, 'name' => '小说3', 'author' => '作者3'],
-            ['n_id' => 5, 'name' => '小说3', 'author' => '作者3'],
-            ['n_id' => 6, 'name' => '小说3', 'author' => '作者3'],
-            ['n_id' => 7, 'name' => '小说3', 'author' => '作者3'],
-            ['n_id' => 8, 'name' => '小说3', 'author' => '作者3'],
-        ];
+        $strBaseUrl = sprintf('/pc/shuku/%s/%s/%s/page{page}', $strGender, $strCategory, $strStatus);
+        $arrPaginator = CusteomPage02::generate($intPage,  $arrPage['total'], $intLimit, $strBaseUrl, $intButtomNum);
 
         View::assign([
-            'arrNovel' => $arrNovel,
+            'arrNovel' =>  $arrPage['data'],
             'strPageCode' => 'library',
-            'intGender' => $intGender,
+            'strGender' => $strGender,
             'strCategory' => $strCategory,
             'strStatus' => $strStatus,
             'intPage' => $intPage,
+            'intTotalPage' => $arrPage['pages'],
+            'arrCategory' => array_combine(array_values(CategoryModel::$arrCategoryPinYin), array_values(CategoryModel::$arrCategory)),
+            'arrPaginator' => $arrPaginator,
         ]);
-        if ($boolIsMobile) {
-            return View::fetch();
-        } else {
-            return View::fetch('pc/getLibrary');
-        }
+
+
+
+        return View::fetch($strTemplate);
     }
 
     // 书架
@@ -338,7 +377,7 @@ class Novel extends BaseController
 
         $strNovel = '斗罗大陆';
 
-        ConverterMovel::setVal("strNovelName",$strNovel);
+        ConverterMovel::setVal("strNovelName", $strNovel);
 
 
         // 模拟数据-随机推荐数据10条
@@ -359,17 +398,24 @@ class Novel extends BaseController
         // 最新要点->取新意章节, 随机提取一部分内容 大概150字数
 
 
+        // {strNovelName}最新章节_{strNovelName}{strNovelAuthor}_{strNovelName}全文阅读_{strSiteName}
+        // {strNovelName}免费全文阅读-{strNovelName}{strNovelAuthor}-{strSiteName}
 
-        
         // $strTitle = '小说详情-{strNovelName}-xxxxx';
 
         // $strTitle = ConverterMovel::convert($strTitle);
 
         // echo $strTitle;exit;
 
+        $strTitle =  $Request->DomainModel->getFomartSubject(getFomartSubjectKey(__METHOD__));
+        // echo  $strTitle ;exit;
+        $strTitle = ConverterMovel::convert($strTitle);
+
+
         View::assign([
             'arrRecommendNovel' => $arrRecommendNovel,
-            'strPageCode' => 'boy'
+            'strPageCode' => 'boy',
+            'strTitle' => $strTitle,
         ]);
         if ($boolIsMobile) {
             return View::fetch();
diff --git a/code/app/home/view/kuangyu/Pc/getLibrary.html b/code/app/home/view/kuangyu/Pc/getLibrary.html
index eb49593..71872b6 100644
--- a/code/app/home/view/kuangyu/Pc/getLibrary.html
+++ b/code/app/home/view/kuangyu/Pc/getLibrary.html
@@ -28,25 +28,28 @@
             
所属频道
所属分类
是否完结
@@ -63,19 +66,28 @@
    -
  • «
  • + + + {volist name="arrPaginator" id="vo" key="k" } +
  • {$vo.label}
  • + {/volist} + + + + +
diff --git a/code/app/home/view/kuangyu/basePc.html b/code/app/home/view/kuangyu/basePc.html index 995f960..3ae8206 100644 --- a/code/app/home/view/kuangyu/basePc.html +++ b/code/app/home/view/kuangyu/basePc.html @@ -6,7 +6,7 @@ - 狂雨小说 + {$strTitle??''} diff --git a/code/app/model/CategoryModel.php b/code/app/model/CategoryModel.php index 8ef6dec..af7dd11 100644 --- a/code/app/model/CategoryModel.php +++ b/code/app/model/CategoryModel.php @@ -28,6 +28,18 @@ class CategoryModel extends MongoModel 9 => '其他小说', ]; + static $arrCategoryPinYin = [ + 1 => 'xuanhuan-xiuzhen', // 玄幻-修真 + 2 => 'junshi-xiaoshuo', // 军史-小说 + 3 => 'wangyou-xiaoshuo', // 网游-小说 + 4 => 'kehuan-xiaoshuo', // 科幻-小说 + 5 => 'zhongsheng-chuanyue', // 重生-穿越 + 6 => 'dushi-xiaoshuo', // 都市-小说 + 7 => 'lingyi-xiaoshuo', // 灵异-小说 + 8 => 'yanqing-xiaoshuo', // 言情-小说 + 9 => 'qita-xiaoshuo', // 其他-小说 + ]; + static $arrMan = [ 1 => '玄幻修真', 2 => '军史小说', @@ -44,17 +56,17 @@ class CategoryModel extends MongoModel ]; - static public function getCategory():array + static public function getCategory(): array { return self::$arrCategory; } - static public function getManCategory():array + static public function getManCategory(): array { return self::$arrMan; } - static public function getWomenCategory():array + static public function getWomenCategory(): array { return self::$arrWomen; } diff --git a/code/app/model/ConverterMovel.php b/code/app/model/ConverterMovel.php index 33f7902..82d0f5e 100644 --- a/code/app/model/ConverterMovel.php +++ b/code/app/model/ConverterMovel.php @@ -14,7 +14,7 @@ use think\Model; class ConverterMovel { static private $arrMap = [ - '{strSiteTitle}' => '', + '{strSiteName}' => '', '{strSiteKeywords}' => '', '{strSiteDescription}' => '', '{strNovelName}' => '', diff --git a/code/app/model/DomainModel.php b/code/app/model/DomainModel.php index 916cf2a..09f5f3f 100644 --- a/code/app/model/DomainModel.php +++ b/code/app/model/DomainModel.php @@ -15,6 +15,8 @@ class DomainModel extends BaseModel protected $name = 'domain'; protected $pk = 'd_id'; + protected $json = ['t_cfg']; + static public function getDomainByCache($strDomain) { @@ -47,4 +49,54 @@ class DomainModel extends BaseModel return $strWords; } + + + /** + * Undocumented function + * + * @param string $strKey + * @return void + */ + public function getFomartSubject($strKey) //, $intNum = 1, $boolRand = false) + { + // echo $strKey; + // //exit; + // echo '
';
+        // var_dump($this->t_cfg);
+        // exit;
+        $intSfgId = $this->t_cfg->{$strKey}['sfg_id'];
+        // $SubjectFomartCol = SubjectFomartModel::where('sfg_id', $intSfgId)->select();
+
+        $SubjectFomartModel =  SubjectFomartModel::where('sfg_id', $intSfgId)->select()->first();
+        // var_dump($SubjectFomartModel->toArray());
+        // exit;
+
+        return  $SubjectFomartModel->sf_val;
+    }
+
+
+    /**
+     * Undocumented function
+     *
+     * @param array $arrArgs
+     * @return void
+     */
+    static public function getPageUrl($strKey, array $arrArgs): string
+    {
+        $Request = request();
+        // $strKey = $Request->controller(false, true) . '@' .
+        //     $Request->action(true) . '@URL';
+        // $strKey = strtoupper($strKey);
+
+        $strSfVal =  $Request->DomainModel->getFomartSubject($strKey);
+
+        $arrKeys = [];
+        $arrVals = [];
+        foreach ($arrArgs as $strKey => $strVal) {
+            $arrKeys[] = '{' . $strKey . '}';
+            $arrVals[] = $strVal;
+        }
+
+        return str_replace($arrKeys, $arrVals, $strSfVal);
+    }
 }
diff --git a/code/app/model/NovelModel.php b/code/app/model/NovelModel.php
index f8f4ead..52ba69f 100644
--- a/code/app/model/NovelModel.php
+++ b/code/app/model/NovelModel.php
@@ -99,8 +99,8 @@ class NovelModel extends MongoModel
                 $arrOptions = [
                     'sort' => $arrSort,
                     // 'limit' => $intCount * 3,
-                    'skip' => ($intPage - 1) * $intLimit, 
-                    'limit' => $intLimit, 
+                    'skip' => ($intPage - 1) * $intLimit,
+                    'limit' => $intLimit,
                     'projection' => [
                         'n_id' => 1,
                         'og_novel_book_name' => 1,
@@ -114,13 +114,15 @@ class NovelModel extends MongoModel
                     ],
                 ];
 
+              
                 $Cursor = $this->getCol()->find($arrFilter, $arrOptions);
+
                 $intTotal =  $this->getCol()->countDocuments($arrFilter);
 
                 $arrResult = iterator_to_array($Cursor);
 
                 shuffle($arrResult);
-    
+
                 $arrResult = [
                     'data' => $arrResult,
                     'total' => $intTotal,
@@ -507,21 +509,28 @@ class NovelModel extends MongoModel
      */
     static public function getNovelInfoUrl($intNId, $intPinYin): string
     {
-        $Request = request();
-        $strFomart = $Request->DomainModel->d_novel_info_url_fomart;
+        $strKey = 'NOVEL_INFO_URL';
+        $strUrl = DomainModel::getPageUrl($strKey, [
+            'intNId' => $intNId,
+            'strPinYin' => $intPinYin
+        ]);
+        return  (string)$strUrl;
 
-        return str_replace(
-            [
-                '{intNId}',
-                '{strPinYin}',
-            ],
-            [
-                $intNId,
-                $intPinYin
-            ],
-            $strFomart
-        );
+        // $Request = request();
+        // $strFomart = $Request->DomainModel->d_novel_info_url_fomart;
 
-        return $strUrl;
+        // return str_replace(
+        //     [
+        //         '{intNId}',
+        //         '{strPinYin}',
+        //     ],
+        //     [
+        //         $intNId,
+        //         $intPinYin
+        //     ],
+        //     $strFomart
+        // );
+
+        // return $strUrl;
     }
 }
diff --git a/code/app/model/SubjectFomartGroupModel.php b/code/app/model/SubjectFomartGroupModel.php
new file mode 100644
index 0000000..150aac4
--- /dev/null
+++ b/code/app/model/SubjectFomartGroupModel.php
@@ -0,0 +1,19 @@
+ 1,
                 't_code' => 'default',
                 't_path' => '/app/home/view/default/',
+                't_cfg_template' => [
+                    'HOME@INDEX' => [
+                        'description' => '首页Title 替换模板分组ID',
+                        'sfg_id' => 0,
+                    ],
+                    'NOVEL@GETNOVELINFO' => [
+                        'description' => '小说详情TITLE 替换模板分组ID',
+                        'sfg_id' => 0,
+                    ],
+                    'NOVEL_INFO_URL' => [
+                        'description' => '小说详情URL 替换模板分组ID',
+                        'sfg_id' => 0,
+                    ],
+                ],
             ],
             [
                 't_id' => 2,
@@ -39,7 +53,7 @@ class TemplateSeeder
                 't_code' => 'shiKong',
                 't_path' => '/app/home/view/shiKong/',
             ],
-            
+
 
         ];
 
@@ -52,9 +66,5 @@ class TemplateSeeder
         }
 
         TemplatesModel::flushCache();
-
-
-
-        
     }
 }
diff --git a/code/extend/template/page/CusteomPage.php b/code/extend/template/page/CusteomPage.php
index 03f32bc..89726d2 100644
--- a/code/extend/template/page/CusteomPage.php
+++ b/code/extend/template/page/CusteomPage.php
@@ -41,51 +41,51 @@ class CusteomPage  extends Paginator
         return $this->getPageLinkWrapper($url, $text);
     }
 
-   /**
- * 页码按钮
- * @return string
- */
-/**
- * 页码按钮
- * @return string
- */
-protected function getLinks(): string
-{
-    if ($this->simple) {
-        return '';
-    }
-
-    $block = [
-        'first' => null,
-        'slider' => null,
-        'last' => null,
-    ];
-
-    if ($this->lastPage <= 3) {
-        // 如果总页数少于或等于3,显示所有页码
-        $block['first'] = $this->getUrlRange(1, $this->lastPage);
-    } else {
-        if ($this->currentPage == 1) {
-            // 如果当前页码是第一页,显示前两页和第三页
-            $block['first'] = $this->getUrlRange(1, 3);
-        } elseif ($this->currentPage == $this->lastPage) {
-            // 如果当前页码是最后一页,显示最后三页
-            $block['first'] = $this->getUrlRange($this->lastPage - 2, $this->lastPage);
-        } else {
-            // 否则,显示当前页码及其前后各一页
-            $block['first'] = $this->getUrlRange($this->currentPage - 1, $this->currentPage + 1);
+    /**
+     * 页码按钮
+     * @return string
+     */
+    /**
+     * 页码按钮
+     * @return string
+     */
+    protected function getLinks(): string
+    {
+        if ($this->simple) {
+            return '';
         }
+
+        $block = [
+            'first' => null,
+            'slider' => null,
+            'last' => null,
+        ];
+
+        if ($this->lastPage <= 3) {
+            // 如果总页数少于或等于3,显示所有页码
+            $block['first'] = $this->getUrlRange(1, $this->lastPage);
+        } else {
+            if ($this->currentPage == 1) {
+                // 如果当前页码是第一页,显示前两页和第三页
+                $block['first'] = $this->getUrlRange(1, 3);
+            } elseif ($this->currentPage == $this->lastPage) {
+                // 如果当前页码是最后一页,显示最后三页
+                $block['first'] = $this->getUrlRange($this->lastPage - 2, $this->lastPage);
+            } else {
+                // 否则,显示当前页码及其前后各一页
+                $block['first'] = $this->getUrlRange($this->currentPage - 1, $this->currentPage + 1);
+            }
+        }
+
+        $html = '';
+
+        if (is_array($block['first'])) {
+            $html .= $this->getUrlLinks($block['first']);
+        }
+
+        return $html;
     }
 
-    $html = '';
-
-    if (is_array($block['first'])) {
-        $html .= $this->getUrlLinks($block['first']);
-    }
-
-    return $html;
-}
-
     /**
      * 渲染分页html
      * @return mixed
diff --git a/code/extend/template/page/CusteomPage02.php b/code/extend/template/page/CusteomPage02.php
new file mode 100644
index 0000000..4b51d7e
--- /dev/null
+++ b/code/extend/template/page/CusteomPage02.php
@@ -0,0 +1,152 @@
+ '上一页',
+            'next' => '下一页',
+            'ellipsis' => '...'
+        ];
+        $labels = array_merge($defaultLabels, $buttonLabels);
+
+        // 验证 totalButtons 必须大于 3
+        if ($totalButtons < 3) {
+            throw new \InvalidArgumentException('Total buttons must be greater than 3');
+        }
+
+        // 计算总页数
+        $totalPages = ceil($totalItems / $itemsPerPage);
+        if ($totalPages <= 1) return []; // 只有一页时返回空数组
+
+        // 确保当前页码在有效范围内
+        $currentPage = max(1, min($currentPage, $totalPages));
+
+        // 计算除去“上一页”和“下一页”后可显示的页码按钮数
+        $pageButtons = $totalButtons - 2; // 减去“上一页”和“下一页”
+
+        // 初始化按钮数组
+        $buttons = [];
+
+        // 上一页按钮
+        $buttons[] = [
+            'type' => 'prev',
+            'label' => $labels['prev'],
+            'url' => $currentPage > 1 ? str_replace('{page}', $currentPage - 1, $baseUrl) : null,
+            'rel' => $currentPage > 1 ? 'prev' : null,
+            'disabled' => $currentPage <= 1
+        ];
+
+        // 计算页码范围
+        $half = floor($pageButtons / 2);
+        $start = max(1, $currentPage - $half);
+        $end = $start + $pageButtons - 1;
+
+        // 调整范围,确保不超过总页数
+        if ($end > $totalPages) {
+            $end = $totalPages;
+            $start = max(1, $end - $pageButtons + 1);
+        }
+
+        // 如果总页数大于可显示的页码数,添加省略号逻辑
+        if ($totalPages > $pageButtons) {
+            if ($start > 1) {
+                $buttons[] = [
+                    'type' => 'page',
+                    'label' => '1',
+                    'url' => str_replace('{page}', 1, $baseUrl),
+                    'current' => false
+                ];
+                if ($start > 2) {
+                    $buttons[] = [
+                        'type' => 'ellipsis',
+                        'label' => $labels['ellipsis'],
+                        'url' => null
+                    ];
+                }
+            }
+
+            // 添加页码按钮
+            for ($i = $start; $i <= $end; $i++) {
+                $buttons[] = [
+                    'type' => 'page',
+                    'label' => (string)$i,
+                    'url' => str_replace('{page}', $i, $baseUrl),
+                    'current' => $i === $currentPage
+                ];
+            }
+
+            if ($end < $totalPages) {
+                if ($end < $totalPages - 1) {
+                    $buttons[] = [
+                        'type' => 'ellipsis',
+                        'label' => $labels['ellipsis'],
+                        'url' => null
+                    ];
+                }
+                $buttons[] = [
+                    'type' => 'page',
+                    'label' => (string)$totalPages,
+                    'url' => str_replace('{page}', $totalPages, $baseUrl),
+                    'current' => false
+                ];
+            }
+        } else {
+            // 总页数少于等于可显示页码数,直接全部显示
+            for ($i = 1; $i <= $totalPages; $i++) {
+                $buttons[] = [
+                    'type' => 'page',
+                    'label' => (string)$i,
+                    'url' => str_replace('{page}', $i, $baseUrl),
+                    'current' => $i === $currentPage
+                ];
+            }
+        }
+
+        // 下一页按钮
+        $buttons[] = [
+            'type' => 'next',
+            'label' => $labels['next'],
+            'url' => $currentPage < $totalPages ? str_replace('{page}', $currentPage + 1, $baseUrl) : null,
+            'rel' => $currentPage < $totalPages ? 'next' : null,
+            'disabled' => $currentPage >= $totalPages
+        ];
+
+        return $buttons;
+    }
+}
+
+// // 测试示例 1:显示 5 个按钮
+// $currentPage = 3;
+// $totalItems = 100;
+// $itemsPerPage = 10;
+// $baseUrl = '/male/xuanhuan-xiuzhen/finished/page{page}';
+// $buttons = Pagination::generate($currentPage, $totalItems, $itemsPerPage, $baseUrl, 5);
+// print_r($buttons);
+
+// // 测试示例 2:显示 7 个按钮
+// $buttons = Pagination::generate($currentPage, $totalItems, $itemsPerPage, $baseUrl, 7);
+// print_r($buttons);
+// 
diff --git a/code/域名.xlsx b/code/域名.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..3fbcbc24e8ab673ae755262e888473b4e1603135
GIT binary patch
literal 8928
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