Compare commits

...

34 Commits

Author SHA1 Message Date
7e650a0a04 修改版本号 2020-12-26 22:27:51 +08:00
45c59ecc37 前端新增深色主题模版 2020-12-26 22:16:58 +08:00
5e3962fef4 update 2020-12-26 20:10:11 +08:00
7f5035e369 update 2020-12-26 20:08:07 +08:00
44aad39847 update 2020-12-26 20:00:21 +08:00
6ad51908d5 文件夹结构调整,新增模版自定义功能 2020-12-26 19:13:07 +08:00
f03ab953d0 v3.2.0发布 2020-12-26 11:45:19 +08:00
5cc9dfa1bc v3.2.0发布 2020-12-26 11:42:09 +08:00
2fbda60617 修复jwt校验失败后的bug 2020-12-24 17:13:36 +08:00
39c19ac004 页面不存在则跳转到404页面 2020-12-24 16:54:37 +08:00
7494fe431a 页面不存在则跳转到404页面 2020-12-24 16:45:48 +08:00
c9f1500976 新增404页面,访问已删除的书页/目录页/内容页自动跳转到404页面 2020-12-24 16:26:21 +08:00
f61c252e71 爬虫代码优化 2020-12-24 01:30:00 +08:00
6fd183c2ae 爬虫代码优化 2020-12-24 01:22:19 +08:00
c3daaecaaa 爬虫代码优化 2020-12-24 01:17:52 +08:00
1b6cc8ccd5 爬虫代码优化 2020-12-24 00:10:19 +08:00
0a10504461 优化章节字数算法,优化爬虫代码 2020-12-23 23:48:34 +08:00
1046a7ffc1 后台数据校验优化 2020-12-22 23:12:22 +08:00
612555dbe6 更新QQ群 2020-12-22 09:35:24 +08:00
d5768e4011 后台首页gitee仓库地址更新 2020-12-21 17:51:54 +08:00
5982eb623f 更新文档 2020-12-16 09:53:39 +08:00
85ad5fa3b2 增加官网地址 2020-12-15 10:23:12 +08:00
bdc81f7676 更新安卓客户端 2020-12-13 10:09:42 +08:00
f31c86f362 修复手机端导航栏书架的点击问题 2020-12-13 09:33:59 +08:00
45d8902429 更新接口文档示例 2020-12-12 12:16:13 +08:00
ff9696bb7e 添加接口文档示例 2020-12-12 12:03:40 +08:00
cacebcaa33 小说章节列表接口排序字段新增默认值 2020-12-12 11:16:24 +08:00
355cb80458 restful api改造 2020-12-12 10:03:15 +08:00
a8c74d061c 修改gitee仓库地址 2020-12-11 13:40:35 +08:00
a713b66c1b 爬虫优化,兼容更多源站 2020-12-10 19:04:44 +08:00
e9d915c1fe 修改版本号 2020-12-10 13:39:57 +08:00
cd3520971d 修改版本号 2020-12-10 08:40:15 +08:00
dc4c9138ee novel-admin加入父工程管理 2020-12-09 18:24:23 +08:00
f830600c3e 爬虫优化,提升兼容性 2020-12-09 16:39:15 +08:00
1079 changed files with 119566 additions and 430 deletions

View File

@ -2,26 +2,26 @@
# 小说精品屋-plus
#### 官网
https://xiongxyang.gitee.io/home/
#### 新项目小说精品屋-微服务版
基于小说精品屋-plus构建的Spring Cloud 微服务小说门户平台
Gitee仓库地址 https://gitee.com/xiongxyang/novel-cloud
GitHub仓库地址 https://github.com/201206030/novel-cloud
Gitee仓库地址 https://gitee.com/novel_dev_team/novel-cloud
#### 演示地址
[点击前往](http://47.106.243.172:8888/)
#### 前言
小说精品屋-plus致力于打造一个完整的商用小说门户平台使用前建议先阅读此文档
#### 项目介绍
小说精品屋-plus是在[小说精品屋](https://github.com/201206030/fiction_house)的基础上去除了漫画和弹幕模块专注于小说是一个多端PC、移动)阅读、功能完善的小说原创/爬虫网站项目既包含了作家专区供原创作者上传小说又提供了爬虫工具通过规则多线程全自动采集任意小说网站数据已兼容99%的小说网站),新书自动入库,老书自动更新
小说精品屋-plus是在[小说精品屋](https://github.com/201206030/fiction_house)的基础上去除了漫画和弹幕模块专注于小说是一个多端PC、WAP)阅读、功能完善的原创文学CMS系统由前台门户系统、作家后台管理系统、平台后台管理系统、爬虫管理系统等多个子系统构成支持会员充值、订阅模式、新闻发布和实时统计报表等功能
小说精品屋-plus重新进行了数据库设计代码重构和功能增强提升了程序整体的可读性和性能增加了很多商用特性主要升级如下
@ -29,6 +29,7 @@ GitHub仓库地址 https://github.com/201206030/novel-cloud
- [x] 服务端代码重构MyBatis3升级为MyBatis3DynamicSql
- [x] 移动站与PC站站点分离浏览器自动识别跳转
- [x] PC站UI更新
- [x] 支持前端模版自定义内置多套模版
- [x] 新闻模块
- [x] 排行榜
- [x] 小说评论模块
@ -44,9 +45,10 @@ GitHub仓库地址 https://github.com/201206030/novel-cloud
```
novel-plus -- 父工程
novel-common -- 通用模块
novel-front -- 前台门户系统
novel-crawl -- 爬虫管理系统
novel-admin -- 后台管理系统
novel-front -- 前台门户&作家后台管理子系统可拆分
novel-crawl -- 爬虫管理系统
novel-admin -- 平台后台管理系统
templates -- 前端模版
```
#### 技术选型
@ -76,7 +78,12 @@ novel-plus -- 父工程
| Layui | 前端UI
#### PC站截图
#### 接口文档
[点击查看接口文档示例](doc/api/api.md)
#### 橙色主题模版截图
##### PC站截图
1. 首页
@ -130,7 +137,7 @@ novel-plus -- 父工程
![img](https://oscimg.oschina.net/oscnet/up-f849960f4c1303fea77d26e64fc505a7180.png)
#### 手机站截图
##### 手机站截图
1. 首页
@ -148,13 +155,13 @@ novel-plus -- 父工程
<img src="https://s3.ax1x.com/2020/12/04/Dbsew4.jpg" alt="QQ图片20191018161901" style="zoom:33%;" />
#### 爬虫管理系统截图
##### 爬虫管理系统截图
![img](https://s1.ax1x.com/2020/11/03/BsOgbD.png)
![img](https://s1.ax1x.com/2020/11/03/BsOHr8.png)
#### 后台管理系统截图
##### 后台管理系统截图
![img](https://oscimg.oschina.net/oscnet/up-0552343538674a22a64819834100558f39b.png)
@ -164,6 +171,30 @@ novel-plus -- 父工程
![img](https://oscimg.oschina.net/oscnet/up-faf5dda7320674c29a1772bc0c81d74762e.png)
#### 深色主题模版截图
##### PC站截图
1. 首页
![index](https://static.oschina.net/uploads/img/202006/24151811_wIus.png)
##### 手机站截图
1. 首页
![index](https://static.oschina.net/uploads/img/202006/24151812_OOob.jpg)
4. 小说详情页
![微信图片_20190904181558](https://static.oschina.net/uploads/img/202006/24151812_ZosF.png)
5. 目录页
![QQ图片20191018161901](https://static.oschina.net/uploads/img/202006/24151812_Krva.png)
5. 小说阅读页
![QQ图片20191018161901](https://static.oschina.net/uploads/img/202006/24151813_fDgT.png)
#### 安装步骤
##### 数据库安装
@ -171,19 +202,21 @@ novel-plus -- 父工程
1. 安装MySQL软件
2. 修改MySQL`max_allowed_packet `配置建议100M
3. 新建数据库设置编码为utf8mb4
4. 执行sql/novel_plus.sql脚本文件
4. 执行doc/sql/novel_plus.sql脚本文件
##### 爬虫管理系统安装
1. 修改novel-common模块下application-dev.yml文件中的数据库配置
1. 修改novel-common模块下application-common-dev.yml配置文件中的数据库配置
2. 修改novel-crawl模块下application.yml文件中的管理员账号密码
3. 启动程序打开浏览器默认8081端口访问
4. 选择已有或新增爬虫源支持自定义爬虫规则点击`开启`按钮开始爬取小说数据
##### 前台小说门户安装
##### 前台小说门户安装jar包形式部署时需要复制templates文件夹到jar文件的相同目录下
1. 修改novel-common模块下application-dev.yml文件中的数据库配置
2. 启动程序打开浏览器默认8080端口访问
1. 修改novel-common模块下application-common-dev.yml配置文件中的数据库配置
2. 修改novel-front模块下application.yml配置文件中的模版名为你需要使用的模版名templates文件夹下的模版文件夹名内置orange和dark两套模版
![mini-code](https://s3.ax1x.com/2020/12/26/r4uGM6.png)
3. 启动程序打开浏览器默认8080端口访问
**喜欢此项目的可以给我的GitHub和Gitee加个Star支持一下 **
@ -197,15 +230,15 @@ docker安装教程[点击前往](https://my.oschina.net/java2nb/blog/4271989)
#### 代码仓库
Gitee仓库地址 https://gitee.com/xiongxyang/novel-plus
GitHub仓库地址 https://github.com/201206030/novel-plus
Gitee仓库地址 https://gitee.com/novel_dev_team/novel-plus
#### QQ交流群
![mini-code](https://s1.ax1x.com/2020/10/31/BUQVeI.png)
[点击前往官网查看](https://xiongxyang.gitee.io/home/service.htm)
#### 微信公众号发布最新更新资讯
#### 微信公众号发布最新更新资讯最新前端模版最新爬虫规则技术文档等
![mini-code](https://s3.ax1x.com/2020/12/03/DoImOx.png)
@ -224,7 +257,7 @@ docker安装教程[点击前往](https://my.oschina.net/java2nb/blog/4271989)
本项目提供的爬虫工具仅用于采集项目初期的测试数据请勿用于商业盈利
用户使用本系统从事任何违法违规的事情一切后果由用户自行承担作者不承担任何责任
#### 备注
### 备注
精品小说屋所有相关项目均已在开源中国公开感兴趣的可进入[开源中国](https://www.oschina.net/p/fiction_house)按关键字`精品小说屋`搜索。

116
doc/api/api.md Normal file
View File

@ -0,0 +1,116 @@
<h1 class="curproject-name"> 小说精品屋-plus </h1>
小说精品屋-plus接口
# 作家模块
## 小说章节分页列表查询接口
<a id=小说章节分页列表查询接口> </a>
### 基本信息
**Path** /book/queryIndexList
**Method** GET
**接口描述:**
<p>作家后台章节管理页面需要请求该接口获取小说章节分页列表信息</p>
### 请求参数
**Query**
| 参数名称 | 是否必须 | 示例 | 备注 |
| ------------ | ------------ | ------------ | ------------ |
| bookId | 是 | 1334337530296893441 | 小说ID |
| curr | 否 | 1 | 查询页码默认1 |
| limit | 否 | 5 | 分页大小默认5 |
### 返回数据
<table>
<thead class="ant-table-thead">
<tr>
<th key=name>名称</th><th key=type>类型</th><th key=required>是否必须</th><th key=default>默认值</th><th key=desc>备注</th><th key=sub>其他信息</th>
</tr>
</thead><tbody className="ant-table-tbody"><tr key=0-0><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> code</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应状态吗200表示成功</span></td><td key=5></td></tr><tr key=0-1><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> msg</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应信息</span></td><td key=5></td></tr><tr key=0-2><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> data</span></td><td key=1><span>object</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应数据</span></td><td key=5></td></tr><tr key=0-2-0><td key=0><span style="padding-left: 20px"><span style="color: #8c8a8a">├─</span> total</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">总数量</span></td><td key=5></td></tr><tr key=0-2-1><td key=0><span style="padding-left: 20px"><span style="color: #8c8a8a">├─</span> list</span></td><td key=1><span>object []</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">章节数据集合</span></td><td key=5><p key=3><span style="font-weight: '700'">item 类型: </span><span>object</span></p></td></tr><tr key=0-2-1-0><td key=0><span style="padding-left: 40px"><span style="color: #8c8a8a">├─</span> id</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">章节ID</span></td><td key=5></td></tr><tr key=0-2-1-1><td key=0><span style="padding-left: 40px"><span style="color: #8c8a8a">├─</span> bookId</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">小说ID</span></td><td key=5></td></tr><tr key=0-2-1-2><td key=0><span style="padding-left: 40px"><span style="color: #8c8a8a">├─</span> indexName</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">章节名</span></td><td key=5></td></tr><tr key=0-2-1-3><td key=0><span style="padding-left: 40px"><span style="color: #8c8a8a">├─</span> isVip</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">是否收费1:收费0:免费</span></td><td key=5></td></tr><tr key=0-2-1-4><td key=0><span style="padding-left: 40px"><span style="color: #8c8a8a">├─</span> updateTime</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">更新时间</span></td><td key=5></td></tr><tr key=0-2-2><td key=0><span style="padding-left: 20px"><span style="color: #8c8a8a">├─</span> pageNum</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">页码</span></td><td key=5></td></tr><tr key=0-2-3><td key=0><span style="padding-left: 20px"><span style="color: #8c8a8a">├─</span> pageSize</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">分页大小</span></td><td key=5></td></tr><tr key=0-2-4><td key=0><span style="padding-left: 20px"><span style="color: #8c8a8a">├─</span> size</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">当前页数量</span></td><td key=5></td></tr>
</tbody>
</table>
## 小说章节删除接口
<a id=小说章节删除接口> </a>
### 基本信息
**Path** /author/deleteIndex/{indexId}
**Method** DELETE
**接口描述:**
<p>作家后台章节管理页面点击删除按钮请求该接口删除小说章节内容</p>
### 请求参数
**Headers**
| 参数名称 | 参数值 | 是否必须 | 示例 | 备注 |
| ------------ | ------------ | ------------ | ------------ | ------------ |
| Content-Type | application/x-www-form-urlencoded | 是 | | |
| Authorization | | 是 | eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2MDgzNDg0NzksInN1YiI6IntcImlkXCI6MTI1NTA2MDMyODMyMjAyNzUyMCxcInVzZXJuYW1lXCI6XCIxMzU2MDQyMTMyNFwiLFwibmlja05hbWVcIjpcIjEzNTYwNDIxMzI0XCJ9IiwiY3JlYXRlZCI6MTYwNzc0MzY3OTkxM30.0qhwis_zPb6t8wGNejMhDZ2iHCL9Tgh2UHd1gcQBCp8t6RW3ggSwtfo4l_RgMT_v8jOkLW91GzTVWlNnTE6LCA | 认证JWT请求登录接口成功后返回 |
**路径参数**
| 参数名称 | 示例 | 备注 |
| ------------ | ------------ | ------------ |
| indexId | 1337603246936645632 | 章节ID |
### 返回数据
<table>
<thead class="ant-table-thead">
<tr>
<th key=name>名称</th><th key=type>类型</th><th key=required>是否必须</th><th key=default>默认值</th><th key=desc>备注</th><th key=sub>其他信息</th>
</tr>
</thead><tbody className="ant-table-tbody"><tr key=0-0><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> code</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应状态吗200表示成功</span></td><td key=5></td></tr><tr key=0-1><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> msg</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应信息</span></td><td key=5></td></tr>
</tbody>
</table>
## 小说章节发布接口
<a id=小说章节发布接口> </a>
### 基本信息
**Path** /author/addBookContent
**Method** POST
**接口描述:**
<p>作家后台章节发布页面点击提交按钮请求该接口新增小说章节内容</p>
### 请求参数
**Headers**
| 参数名称 | 参数值 | 是否必须 | 示例 | 备注 |
| ------------ | ------------ | ------------ | ------------ | ------------ |
| Content-Type | application/x-www-form-urlencoded | 是 | | |
| Authorization | | 是 | eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2MDgzNDg0NzksInN1YiI6IntcImlkXCI6MTI1NTA2MDMyODMyMjAyNzUyMCxcInVzZXJuYW1lXCI6XCIxMzU2MDQyMTMyNFwiLFwibmlja05hbWVcIjpcIjEzNTYwNDIxMzI0XCJ9IiwiY3JlYXRlZCI6MTYwNzc0MzY3OTkxM30.0qhwis_zPb6t8wGNejMhDZ2iHCL9Tgh2UHd1gcQBCp8t6RW3ggSwtfo4l_RgMT_v8jOkLW91GzTVWlNnTE6LCA | 认证JWT请求登录接口成功后返回 |
**Body**
| 参数名称 | 参数类型 | 是否必须 | 示例 | 备注 |
| ------------ | ------------ | ------------ | ------------ | ------------ |
| bookId | text | 是 | 1334337530296893441 | 小说ID |
| indexName | text | 是 | 第六章未婚妻(下) | 章节名 |
| content | text | 是 | 开始之时,李七夜还是生疏无比,那怕他对于刀术的所有奥义了然于胸,但是,他出刀之时依然会颤抖,无法达到妙及巅毫的要求。 | 章节内容 |
| isVip | text | 是 | 1 | 是否收费1:收费0:免费 |
### 返回数据
<table>
<thead class="ant-table-thead">
<tr>
<th key=name>名称</th><th key=type>类型</th><th key=required>是否必须</th><th key=default>默认值</th><th key=desc>备注</th><th key=sub>其他信息</th>
</tr>
</thead><tbody className="ant-table-tbody"><tr key=0-0><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> code</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应状态吗200表示成功</span></td><td key=5></td></tr><tr key=0-1><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> msg</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应信息</span></td><td key=5></td></tr>
</tbody>
</table>

View File

@ -491,13 +491,6 @@ CREATE TABLE `sys_dept` (
-- ----------------------------
-- Records of sys_dept
-- ----------------------------
INSERT INTO `sys_dept` VALUES ('6', '0', '研发部', '1', '1');
INSERT INTO `sys_dept` VALUES ('7', '6', '研發一部', '1', '1');
INSERT INTO `sys_dept` VALUES ('8', '6', '研发二部', '2', '1');
INSERT INTO `sys_dept` VALUES ('9', '0', '销售部', '2', '1');
INSERT INTO `sys_dept` VALUES ('10', '9', '销售一部', '1', '1');
INSERT INTO `sys_dept` VALUES ('11', '0', '产品部', '3', '1');
INSERT INTO `sys_dept` VALUES ('12', '11', '产品一部', '1', '1');
INSERT INTO `sys_dept` VALUES ('13', '0', '测试部', '5', '1');
INSERT INTO `sys_dept` VALUES ('14', '13', '测试一部', '1', '1');
INSERT INTO `sys_dept` VALUES ('15', '13', '测试二部', '2', '1');
@ -894,52 +887,6 @@ CREATE TABLE `sys_log` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1412 DEFAULT CHARSET=utf8 COMMENT='系统日志';
-- ----------------------------
-- Records of sys_log
-- ----------------------------
INSERT INTO `sys_log` VALUES ('1369', '-1', '获取用户信息为空', '登录', '462', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:09:21');
INSERT INTO `sys_log` VALUES ('1370', '-1', '获取用户信息为空', '登录', '19', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:09:26');
INSERT INTO `sys_log` VALUES ('1371', '1', 'admin', '登录', '98', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:09:33');
INSERT INTO `sys_log` VALUES ('1372', '1', 'admin', '请求访问主页', '372', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:09:33');
INSERT INTO `sys_log` VALUES ('1373', '1', 'admin', '请求访问主页', '28', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:12:41');
INSERT INTO `sys_log` VALUES ('1374', '1', 'admin', '编辑角色', '11', 'com.java2nb.system.controller.RoleController.edit()', null, '127.0.0.1', '2020-05-13 11:18:42');
INSERT INTO `sys_log` VALUES ('1375', '1', 'admin', '添加菜单', '2', 'com.java2nb.system.controller.MenuController.add()', null, '127.0.0.1', '2020-05-13 11:19:55');
INSERT INTO `sys_log` VALUES ('1376', '1', 'admin', '保存菜单', '225', 'com.java2nb.system.controller.MenuController.save()', null, '127.0.0.1', '2020-05-13 11:24:42');
INSERT INTO `sys_log` VALUES ('1377', '1', 'admin', '编辑菜单', '15', 'com.java2nb.system.controller.MenuController.edit()', null, '127.0.0.1', '2020-05-13 11:24:54');
INSERT INTO `sys_log` VALUES ('1378', '1', 'admin', '编辑菜单', '11', 'com.java2nb.system.controller.MenuController.edit()', null, '127.0.0.1', '2020-05-13 11:24:58');
INSERT INTO `sys_log` VALUES ('1379', '1', 'admin', '更新菜单', '241', 'com.java2nb.system.controller.MenuController.update()', null, '127.0.0.1', '2020-05-13 11:25:12');
INSERT INTO `sys_log` VALUES ('1380', '1', 'admin', '编辑菜单', '8', 'com.java2nb.system.controller.MenuController.edit()', null, '127.0.0.1', '2020-05-13 11:25:16');
INSERT INTO `sys_log` VALUES ('1381', '1', 'admin', '更新菜单', '199', 'com.java2nb.system.controller.MenuController.update()', null, '127.0.0.1', '2020-05-13 11:25:26');
INSERT INTO `sys_log` VALUES ('1382', '1', 'admin', '编辑角色', '13', 'com.java2nb.system.controller.RoleController.edit()', null, '127.0.0.1', '2020-05-13 11:26:11');
INSERT INTO `sys_log` VALUES ('1383', '1', 'admin', '更新角色', '931', 'com.java2nb.system.controller.RoleController.update()', null, '127.0.0.1', '2020-05-13 11:26:36');
INSERT INTO `sys_log` VALUES ('1384', '-1', '获取用户信息为空', '登录', '11', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:27:02');
INSERT INTO `sys_log` VALUES ('1385', '1', 'admin', '登录', '19', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:27:08');
INSERT INTO `sys_log` VALUES ('1386', '1', 'admin', '请求访问主页', '27', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:27:08');
INSERT INTO `sys_log` VALUES ('1387', '1', 'admin', '登录', '272', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:27:56');
INSERT INTO `sys_log` VALUES ('1388', '1', 'admin', '请求访问主页', '109', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:27:56');
INSERT INTO `sys_log` VALUES ('1389', '1', 'admin', '编辑角色', '8', 'com.java2nb.system.controller.RoleController.edit()', null, '127.0.0.1', '2020-05-13 11:30:36');
INSERT INTO `sys_log` VALUES ('1390', '1', 'admin', '更新角色', '567', 'com.java2nb.system.controller.RoleController.update()', null, '127.0.0.1', '2020-05-13 11:30:42');
INSERT INTO `sys_log` VALUES ('1391', '-1', '获取用户信息为空', '登录', '246', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:31:38');
INSERT INTO `sys_log` VALUES ('1392', '1', 'admin', '登录', '38', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:31:42');
INSERT INTO `sys_log` VALUES ('1393', '1', 'admin', '请求访问主页', '110', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:31:43');
INSERT INTO `sys_log` VALUES ('1394', '1', 'admin', 'error', null, 'http://127.0.0.1/test/order/list', 'org.springframework.jdbc.BadSqlGrammarException: \r\n### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Table \'novel_plus.fb_order\' doesn\'t exist\r\n### The error may exist in file [E:\\baseprojectparent\\novel-plus\\novel-admin\\target\\classes\\mybatis\\test\\OrderMapper.xml]\r\n### The error may involve defaultParameterMap\r\n### The error occurred while setting parameters\r\n### SQL: select `id`,`fb_merchant_code`,`merchant_order_sn`,`order_sn`,`platform_order_no`,`trade_no`,`order_state`,`fn_coupon`,`red_packet`,`total_fee`,`order_price`,`fee`,`body`,`attach`,`store_id`,`cashier_id`,`device_no`,`user_id`,`user_logon_id`,`pay_time`,`pay_channel`,`no_cash_coupon_fee`,`cash_coupon_fee`,`cash_fee`,`sign`,`options`,`create_time`,`push_time`,`push_ip`,`mcht_id`,`sn` from fb_order order by id desc limit ?, ?\r\n### Cause: java.sql.SQLSyntaxErrorException: Table \'novel_plus.fb_order\' doesn\'t exist\n; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Table \'novel_plus.fb_order\' doesn\'t exist', null, '2020-05-13 11:33:27');
INSERT INTO `sys_log` VALUES ('1395', '1', 'admin', '登录', '276', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:39:20');
INSERT INTO `sys_log` VALUES ('1396', '1', 'admin', '请求访问主页', '95', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:39:20');
INSERT INTO `sys_log` VALUES ('1397', '1', 'admin', '登录', '285', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:47:00');
INSERT INTO `sys_log` VALUES ('1398', '1', 'admin', '请求访问主页', '90', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:47:00');
INSERT INTO `sys_log` VALUES ('1399', '1', 'admin', '登录', '251', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:48:28');
INSERT INTO `sys_log` VALUES ('1400', '1', 'admin', '请求访问主页', '95', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:48:28');
INSERT INTO `sys_log` VALUES ('1401', '1', 'admin', '登录', '302', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 14:09:33');
INSERT INTO `sys_log` VALUES ('1402', '1', 'admin', '请求访问主页', '88', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 14:09:34');
INSERT INTO `sys_log` VALUES ('1403', '1', 'admin', '请求更改用户密码', '3', 'com.java2nb.system.controller.UserController.resetPwd()', null, '127.0.0.1', '2020-05-13 14:11:49');
INSERT INTO `sys_log` VALUES ('1404', '1', 'admin', 'admin提交更改用户密码', '140', 'com.java2nb.system.controller.UserController.adminResetPwd()', null, '127.0.0.1', '2020-05-13 14:11:50');
INSERT INTO `sys_log` VALUES ('1405', '1', 'admin', '请求更改用户密码', '4', 'com.java2nb.system.controller.UserController.resetPwd()', null, '127.0.0.1', '2020-05-13 14:12:11');
INSERT INTO `sys_log` VALUES ('1406', '1', 'admin', '登录', '275', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 14:14:26');
INSERT INTO `sys_log` VALUES ('1407', '1', 'admin', '请求访问主页', '73', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 14:14:27');
INSERT INTO `sys_log` VALUES ('1408', '1', 'admin', 'error', null, 'http://127.0.0.1/novel/author/update', 'org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors\nField error in object \'authorDO\' on field \'id\': rejected value [1,1]; codes [typeMismatch.authorDO.id,typeMismatch.id,typeMismatch.java.lang.Long,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [authorDO.id,id]; arguments []; default message [id]]; default message [Failed to convert property value of type \'java.lang.String\' to required type \'java.lang.Long\' for property \'id\'; nested exception is java.lang.NumberFormatException: For input string: \"1,1\"]', null, '2020-05-13 14:14:38');
INSERT INTO `sys_log` VALUES ('1409', '1', 'admin', 'error', null, 'http://127.0.0.1/novel/author/update', 'org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors\nField error in object \'authorDO\' on field \'id\': rejected value [1,1]; codes [typeMismatch.authorDO.id,typeMismatch.id,typeMismatch.java.lang.Long,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [authorDO.id,id]; arguments []; default message [id]]; default message [Failed to convert property value of type \'java.lang.String\' to required type \'java.lang.Long\' for property \'id\'; nested exception is java.lang.NumberFormatException: For input string: \"1,1\"]', null, '2020-05-13 14:14:47');
INSERT INTO `sys_log` VALUES ('1410', '1', 'admin', '登录', '261', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 14:18:07');
INSERT INTO `sys_log` VALUES ('1411', '1', 'admin', '请求访问主页', '83', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 14:18:07');
-- ----------------------------
-- Table structure for sys_menu
@ -1047,9 +994,6 @@ CREATE TABLE `sys_role` (
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES ('1', '超级用户角色', 'admin', '拥有最高权限', '2', '2017-08-12 00:43:52', '2017-08-12 19:14:59');
INSERT INTO `sys_role` VALUES ('59', '普通用户', null, '基本用户权限', null, null, null);
INSERT INTO `sys_role` VALUES ('60', '测试', null, '&lt;div&gt;', null, null, null);
INSERT INTO `sys_role` VALUES ('61', 'test', null, '测试', null, null, null);
-- ----------------------------
-- Table structure for sys_role_data_perm
@ -1497,19 +1441,7 @@ CREATE TABLE `sys_user` (
-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES ('1', 'admin', '超级管理员', 'd633268afedf209e1e4ea0f5f43228a8', '6', 'admin@example.com', '17699999999', '1', '1', '2017-08-15 21:40:39', '2017-08-15 21:41:00', '96', '2017-12-14 00:00:00', '148', 'ccc', '122;121;', '北京市', '北京市市辖区', '东城区');
INSERT INTO `sys_user` VALUES ('2', 'test', '临时用户', 'd0af8fa1272ef5a152d9e27763eea293', '6', 'test@bootdo.com', null, '1', '1', '2017-08-14 13:43:05', '2017-08-14 21:15:36', null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('36', 'ldh', '刘德华', 'bfd9394475754fbe45866eba97738c36', '7', 'ldh@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('123', 'zxy', '张学友', '35174ba93f5fe7267f1fb3c1bf903781', '6', 'zxy@bootdo', null, '0', null, null, null, null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('124', 'wyf', '吴亦凡', 'e179e6f687bbd57b9d7efc4746c8090a', '6', 'wyf@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('130', 'lh', '鹿晗', '7924710cd673f68967cde70e188bb097', '9', 'lh@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('131', 'lhc', '令狐冲', 'd515538e17ecb570ba40344b5618f5d4', '6', 'lhc@bootdo.com', null, '0', null, null, null, null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('132', 'lyf', '刘亦菲', '7fdb1d9008f45950c1620ba0864e5fbd', '13', 'lyf@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('134', 'lyh', '李彦宏', 'dc26092b3244d9d432863f2738180e19', '8', 'lyh@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('135', 'wjl', '王健林', '3967697dfced162cf6a34080259b83aa', '6', 'wjl@bootod.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('136', 'gdg', '郭德纲', '3bb1bda86bc02bf6478cd91e42135d2f', '9', 'gdg@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('137', 'test2', 'test2', '649169898e69272c0e5bc899baf1e904', null, '1179705413@qq.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('138', 'test3', 'test3', '79ba2d0b58d8a2e94f6b18744c8cd280', '16', '1179705413@qq.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
INSERT INTO `sys_user` VALUES ('1', 'admin', '超级管理员', 'd633268afedf209e1e4ea0f5f43228a8', '14', 'admin@example.com', '17699999999', '1', '1', '2017-08-15 21:40:39', '2017-08-15 21:41:00', '96', '2017-12-14 00:00:00', '148', 'ccc', '122;121;', '北京市', '北京市市辖区', '东城区');
-- ----------------------------
-- Table structure for sys_user_role

View File

@ -5,7 +5,7 @@
<groupId>com.java2nb</groupId>
<artifactId>novel-admin</artifactId>
<version>2.11.0</version>
<version>3.3.0</version>
<packaging>jar</packaging>
<name>novel-admin</name>

View File

@ -1,5 +1,5 @@
java2nb:
uploadPath: c:/var/java2nb/uploaded_files/
uploadPath: /var/pic/
username: admin
password: 111111
logging:
@ -10,7 +10,7 @@ spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: test123456
#password:

View File

@ -147,7 +147,7 @@
<tr>
<td>下载地址</td>
<td>
<a href="https://gitee.com/xiongxyang/fiction_house" target="_blank">Gitee</a> /
<a href="https://gitee.com/novel_dev_team/fiction_house" target="_blank">Gitee</a> /
<a href="https://github.com/201206030/fiction_house" target="_blank">Github</a>
</td>
</tr>
@ -155,8 +155,8 @@
<td>Gitee</td>
<td style="padding-bottom: 0;">
<div class="layui-btn-container">
<a href='https://gitee.com/xiongxyang/fiction_house/stargazers'><img src='https://gitee.com/xiongxyang/fiction_house/badge/star.svg?theme=dark' alt='star'></img></a>
<a href='https://gitee.com/xiongxyang/fiction_house/members'><img src='https://gitee.com/xiongxyang/fiction_house/badge/fork.svg?theme=dark' alt='fork'></img></a>
<a href='https://gitee.com/novel_dev_team/fiction_house/stargazers'><img src='https://gitee.com/novel_dev_team/fiction_house/badge/star.svg?theme=dark' alt='star'></img></a>
<a href='https://gitee.com/novel_dev_team/fiction_house/members'><img src='https://gitee.com/novel_dev_team/fiction_house/badge/fork.svg?theme=dark' alt='fork'></img></a>
</div>
</td>
</tr>
@ -200,7 +200,7 @@
<tr>
<td>下载地址</td>
<td>
<a href="https://gitee.com/xiongxyang/novel-plus" target="_blank">Gitee</a> /
<a href="https://gitee.com/novel_dev_team/novel-plus" target="_blank">Gitee</a> /
<a href="https://github.com/201206030/novel-plus" target="_blank">Github</a>
</td>
</tr>
@ -208,8 +208,8 @@
<td>Gitee</td>
<td style="padding-bottom: 0;">
<div class="layui-btn-container">
<a href='https://gitee.com/xiongxyang/novel-plus/stargazers'><img src='https://gitee.com/xiongxyang/novel-plus/badge/star.svg?theme=dark' alt='star'></img></a>
<a href='https://gitee.com/xiongxyang/novel-plus/members'><img src='https://gitee.com/xiongxyang/novel-plus/badge/fork.svg?theme=dark' alt='fork'></img></a>
<a href='https://gitee.com/novel_dev_team/novel-plus/stargazers'><img src='https://gitee.com/novel_dev_team/novel-plus/badge/star.svg?theme=dark' alt='star'></img></a>
<a href='https://gitee.com/novel_dev_team/novel-plus/members'><img src='https://gitee.com/novel_dev_team/novel-plus/badge/fork.svg?theme=dark' alt='fork'></img></a>
</div>
</td>
</tr>
@ -253,7 +253,7 @@
<tr>
<td>下载地址</td>
<td>
<a href="https://gitee.com/xiongxyang/novel-cloud" target="_blank">Gitee</a> /
<a href="https://gitee.com/novel_dev_team/novel-cloud" target="_blank">Gitee</a> /
<a href="https://github.com/201206030/novel-cloud" target="_blank">Github</a>
</td>
</tr>
@ -261,8 +261,8 @@
<td>Gitee</td>
<td style="padding-bottom: 0;">
<div class="layui-btn-container">
<a href='https://gitee.com/xiongxyang/novel-cloud/stargazers'><img src='https://gitee.com/xiongxyang/novel-cloud/badge/star.svg?theme=dark' alt='star'></img></a>
<a href='https://gitee.com/xiongxyang/novel-cloud/members'><img src='https://gitee.com/xiongxyang/novel-cloud/badge/fork.svg?theme=dark' alt='fork'></img></a>
<a href='https://gitee.com/novel_dev_team/novel-cloud/stargazers'><img src='https://gitee.com/novel_dev_team/novel-cloud/badge/star.svg?theme=dark' alt='star'></img></a>
<a href='https://gitee.com/novel_dev_team/novel-cloud/members'><img src='https://gitee.com/novel_dev_team/novel-cloud/badge/fork.svg?theme=dark' alt='fork'></img></a>
</div>
</td>
</tr>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>novel</artifactId>
<groupId>com.java2nb</groupId>
<version>3.0.2</version>
<version>3.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -1,21 +1,30 @@
package com.java2nb.novel.core.advice;
import com.java2nb.novel.core.bean.ResultBean;
import com.java2nb.novel.core.enums.ResponseStatus;
import com.java2nb.novel.core.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 通用的异常处理器
*
* @author 11797*/
@Slf4j
@ControllerAdvice
@ResponseBody
@RestControllerAdvice(basePackages = "com.java2nb.novel.controller")
public class CommonExceptionHandler {
/**
* 处理后台数据校验异常
* */
@ExceptionHandler(BindException.class)
public ResultBean handlerBindException(BindException e){
log.error(e.getMessage(),e);
return ResultBean.fail(ResponseStatus.PARAM_ERROR);
}
/**
* 处理业务异常
* */

View File

@ -0,0 +1,26 @@
package com.java2nb.novel.core.advice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
/**
* 页面异常处理器
*
* @author 11797
*/
@Slf4j
@ControllerAdvice(basePackages = "com.java2nb.novel.page")
public class PageExceptionHandler {
/**
* 处理所有异常
*/
@ExceptionHandler(Exception.class)
public String handlerException(Exception e) {
log.error(e.getMessage(), e);
//跳转页面过程中出现异常时统一跳转到404页面
return "404";
}
}

View File

@ -1,9 +1,6 @@
package com.java2nb.novel.core.utils;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
/**
@ -28,4 +25,23 @@ public class HttpUtil {
return null;
}
}
public static String getByHttpClientWithChrome(String url) {
try {
HttpHeaders headers = new HttpHeaders();
headers.add("user-agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36");
HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
ResponseEntity<String> forEntity = restTemplate.exchange(url.toString(), HttpMethod.GET, requestEntity, String.class);
if (forEntity.getStatusCode() == HttpStatus.OK) {
return forEntity.getBody();
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -0,0 +1,11 @@
package com.java2nb.novel.core.valid;
/**
* 新增数据的校验分组
* @author xiongxiaoyang
*/
public interface AddGroup {
}

View File

@ -0,0 +1,11 @@
package com.java2nb.novel.core.valid;
/**
* 更新数据的校验分组
* @author xiongxiaoyang
*/
public interface UpdateGroup {
}

View File

@ -1,36 +1,56 @@
package com.java2nb.novel.entity;
import com.java2nb.novel.core.valid.AddGroup;
import com.java2nb.novel.core.valid.UpdateGroup;
import java.util.Date;
import javax.annotation.Generated;
import javax.validation.constraints.*;
public class User {
@Null(groups = {AddGroup.class, UpdateGroup.class})
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@NotBlank(groups = {AddGroup.class},message="手机号不能为空!")
@Pattern(groups = {AddGroup.class},regexp="^1[3|4|5|6|7|8|9][0-9]{9}$",message="手机号格式不正确!")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String username;
@NotBlank(groups = {AddGroup.class},message="密码不能为空!")
@Null(groups = {UpdateGroup.class})
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String password;
@Null(groups = {AddGroup.class})
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String nickName;
@Null(groups = {AddGroup.class})
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String userPhoto;
@Null(groups = {AddGroup.class})
@Min(value = 0,groups = {UpdateGroup.class})
@Max(value = 1,groups = {UpdateGroup.class})
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte userSex;
@Null(groups = {AddGroup.class,UpdateGroup.class})
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long accountBalance;
@Null(groups = {AddGroup.class,UpdateGroup.class})
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte status;
@Null(groups = {AddGroup.class,UpdateGroup.class})
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@Null(groups = {AddGroup.class,UpdateGroup.class})
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date updateTime;

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>novel</artifactId>
<groupId>com.java2nb</groupId>
<version>3.0.2</version>
<version>3.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -9,10 +9,7 @@ import com.java2nb.novel.service.CrawlService;
import com.java2nb.novel.vo.CrawlSingleTaskVO;
import com.java2nb.novel.vo.CrawlSourceVO;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* @author Administrator
@ -39,7 +36,7 @@ public class CrawlController {
/**
* 爬虫源分页列表查询
* */
@PostMapping("listCrawlByPage")
@GetMapping("listCrawlByPage")
public ResultBean listCrawlByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "10") int pageSize){
return ResultBean.ok(new PageInfo<>(BeanUtil.copyList(crawlService.listCrawlByPage(page,pageSize), CrawlSourceVO.class)
@ -71,7 +68,7 @@ public class CrawlController {
/**
* 单本采集任务分页列表查询
* */
@PostMapping("listCrawlSingleTaskByPage")
@GetMapping("listCrawlSingleTaskByPage")
public ResultBean listCrawlSingleTaskByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "10") int pageSize){
return ResultBean.ok(new PageInfo<>(BeanUtil.copyList(crawlService.listCrawlSingleTaskByPage(page,pageSize), CrawlSingleTaskVO.class)
@ -81,8 +78,8 @@ public class CrawlController {
/**
* 删除采集任务
* */
@PostMapping("delCrawlSingleTask")
public ResultBean delCrawlSingleTask(Long id){
@DeleteMapping("delCrawlSingleTask/{id}")
public ResultBean delCrawlSingleTask(@PathVariable("id") Long id){
crawlService.delCrawlSingleTask(id);

View File

@ -1,9 +1,6 @@
package com.java2nb.novel.core.crawl;
import com.java2nb.novel.core.utils.HttpUtil;
import com.java2nb.novel.core.utils.IdWorker;
import com.java2nb.novel.core.utils.RandomBookInfoUtil;
import com.java2nb.novel.core.utils.RestTemplateUtil;
import com.java2nb.novel.core.utils.*;
import com.java2nb.novel.entity.Book;
import com.java2nb.novel.entity.BookContent;
import com.java2nb.novel.entity.BookIndex;
@ -11,8 +8,7 @@ import com.java2nb.novel.utils.Constants;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
import java.text.SimpleDateFormat;
@ -38,13 +34,13 @@ public class CrawlParser {
private static RestTemplate restTemplate = RestTemplateUtil.getInstance("utf-8");
private static ThreadLocal <Integer> retryCount = new ThreadLocal<>();
private static ThreadLocal<Integer> retryCount = new ThreadLocal<>();
@SneakyThrows
public static Book parseBook(RuleBean ruleBean, String bookId) {
Book book = new Book();
String bookDetailUrl = ruleBean.getBookDetailUrl().replace("{bookId}", bookId);
String bookDetailHtml = getByHttpClient(bookDetailUrl);
String bookDetailHtml = getByHttpClientWithChrome(bookDetailUrl);
if (bookDetailHtml != null) {
Pattern bookNamePatten = compile(ruleBean.getBookNamePatten());
Matcher bookNameMatch = bookNamePatten.matcher(bookDetailHtml);
@ -66,7 +62,7 @@ public class CrawlParser {
boolean isFindPicUrl = picUrlMatch.find();
if (isFindPicUrl) {
String picUrl = picUrlMatch.group(1);
if(StringUtils.isNotBlank(picUrl) && StringUtils.isNotBlank(ruleBean.getPicUrlPrefix())) {
if (StringUtils.isNotBlank(picUrl) && StringUtils.isNotBlank(ruleBean.getPicUrlPrefix())) {
picUrl = ruleBean.getPicUrlPrefix() + picUrl;
}
//设置封面图片路径
@ -97,11 +93,11 @@ public class CrawlParser {
String desc = bookDetailHtml.substring(bookDetailHtml.indexOf(ruleBean.getDescStart()) + ruleBean.getDescStart().length());
desc = desc.substring(0, desc.indexOf(ruleBean.getDescEnd()));
//过滤掉简介中的特殊标签
desc = desc.replaceAll("<a[^<]+</a>","")
.replaceAll("<font[^<]+</font>","")
.replaceAll("<p>\\s*</p>","")
.replaceAll("<p>","")
.replaceAll("</p>","<br/>");
desc = desc.replaceAll("<a[^<]+</a>", "")
.replaceAll("<font[^<]+</font>", "")
.replaceAll("<p>\\s*</p>", "")
.replaceAll("<p>", "")
.replaceAll("</p>", "<br/>");
//设置书籍简介
book.setBookDesc(desc);
if (StringUtils.isNotBlank(ruleBean.getStatusPatten())) {
@ -147,9 +143,9 @@ public class CrawlParser {
}
public static Map<Integer, List> parseBookIndexAndContent(String sourceBookId, Book book, RuleBean ruleBean, Map<Integer, BookIndex> hasIndexs) {
Map<Integer,List> result = new HashMap<>(2);
result.put(BOOK_INDEX_LIST_KEY,new ArrayList(0));
result.put(BOOK_CONTENT_LIST_KEY,new ArrayList(0));
Map<Integer, List> result = new HashMap<>(2);
result.put(BOOK_INDEX_LIST_KEY, new ArrayList(0));
result.put(BOOK_CONTENT_LIST_KEY, new ArrayList(0));
Date currentDate = new Date();
@ -157,10 +153,10 @@ public class CrawlParser {
List<BookContent> contentList = new ArrayList<>();
//读取目录
String indexListUrl = ruleBean.getBookIndexUrl().replace("{bookId}", sourceBookId);
String indexListHtml = getByHttpClient(indexListUrl);
String indexListHtml = getByHttpClientWithChrome(indexListUrl);
if (indexListHtml != null) {
if(StringUtils.isNotBlank(ruleBean.getBookIndexStart())){
if (StringUtils.isNotBlank(ruleBean.getBookIndexStart())) {
indexListHtml = indexListHtml.substring(indexListHtml.indexOf(ruleBean.getBookIndexStart()) + ruleBean.getBookIndexStart().length());
}
@ -175,10 +171,7 @@ public class CrawlParser {
int indexNum = 0;
//总字数
Integer totalWordCount = 0;
//最新目录
Long lastIndexId = null;
String lastIndexName = null;
Integer totalWordCount = book.getWordCount() == null ? 0 : book.getWordCount();
while (isFindIndex) {
@ -186,61 +179,81 @@ public class CrawlParser {
String indexName = indexNameMatch.group(1);
if (hasIndex == null || !StringUtils.deleteWhitespace(hasIndex.getIndexName()).equals(StringUtils.deleteWhitespace(indexName))) {
String contentUrl = ruleBean.getBookContentUrl().replace("{bookId}", sourceBookId).replace("{indexId}", indexIdMatch.group(1));
String sourceIndexId = indexIdMatch.group(1);
String bookContentUrl = ruleBean.getBookContentUrl();
int calStart = bookContentUrl.indexOf("{cal_");
if (calStart != -1) {
//内容页URL需要进行计算才能得到
String calStr = bookContentUrl.substring(calStart, calStart + bookContentUrl.substring(calStart).indexOf("}"));
String[] calArr = calStr.split("_");
int calType = Integer.parseInt(calArr[1]);
if (calType == 1) {
///{cal_1_1_3}_{bookId}/{indexId}.html
//第一种计算规则去除第x个参数的最后y个字母
int x = Integer.parseInt(calArr[2]);
int y = Integer.parseInt(calArr[3]);
String calResult;
if (x == 1) {
calResult = sourceBookId.substring(0, sourceBookId.length() - y);
} else {
calResult = sourceIndexId.substring(0, sourceBookId.length() - y);
}
if (calResult.length() == 0) {
calResult = "0";
}
bookContentUrl = bookContentUrl.replace(calStr + "}", calResult);
}
}
String contentUrl = bookContentUrl.replace("{bookId}", sourceBookId).replace("{indexId}", sourceIndexId);
//查询章节内容
String contentHtml = getByHttpClient(contentUrl);
String contentHtml = getByHttpClientWithChrome(contentUrl);
if (contentHtml != null && !contentHtml.contains("正在手打中")) {
String content = contentHtml.substring(contentHtml.indexOf(ruleBean.getContentStart()) + ruleBean.getContentStart().length());
content = content.substring(0, content.indexOf(ruleBean.getContentEnd()));
//TODO插入章节目录和章节内容
//插入章节目录和章节内容
BookIndex bookIndex = new BookIndex();
bookIndex.setIndexName(indexName);
bookIndex.setIndexNum(indexNum);
Integer wordCount = StringUtil.getStrValidWordCount(content);
bookIndex.setWordCount(wordCount);
indexList.add(bookIndex);
BookContent bookContent = new BookContent();
BookContent bookContent = new BookContent();
bookContent.setContent(content);
contentList.add(bookContent);
//判断是新增还是更新
if(hasIndexs.size() == 0){
//新书入库
if (hasIndex != null) {
//章节更新
bookIndex.setId(hasIndex.getId());
bookContent.setIndexId(hasIndex.getId());
//计算总字数
totalWordCount = (totalWordCount+wordCount-hasIndex.getWordCount());
} else {
//章节插入
//设置目录和章节内容
Long indexId = idWorker.nextId();
lastIndexId = indexId;
lastIndexName = indexName;
bookIndex.setId(indexId);
bookIndex.setBookId(book.getId());
Integer wordCount = bookContent.getContent().length();
totalWordCount += wordCount;
bookIndex.setWordCount(wordCount);
bookIndex.setCreateTime(currentDate);
bookIndex.setUpdateTime(currentDate);
bookContent.setIndexId(indexId);
//设置小说基础信息
book.setWordCount(totalWordCount);
book.setLastIndexId(lastIndexId);
book.setLastIndexName(lastIndexName);
book.setLastIndexUpdateTime(currentDate);
book.setCreateTime(currentDate);
book.setUpdateTime(currentDate);
}else{
//老书更新
//计算总字数
totalWordCount += wordCount;
}
bookIndex.setUpdateTime(currentDate);
if(hasIndex != null){
bookIndex.setId(hasIndex.getId());
bookContent.setIndexId(hasIndex.getId());
}
}
@ -249,15 +262,29 @@ public class CrawlParser {
isFindIndex = indexIdMatch.find() & indexNameMatch.find();
}
if (indexList.size() > 0) {
//如果有爬到最新章节,则设置小说主表的最新章节信息
//获取爬取到的最新章节
BookIndex lastIndex = indexList.get(indexList.size()-1);
book.setLastIndexId(lastIndex.getId());
book.setLastIndexName(lastIndex.getIndexName());
book.setLastIndexUpdateTime(currentDate);
}
book.setWordCount(totalWordCount);
book.setUpdateTime(currentDate);
if (indexList.size() == contentList.size() && indexList.size() > 0) {
result.put(BOOK_INDEX_LIST_KEY,indexList);
result.put(BOOK_CONTENT_LIST_KEY,contentList);
result.put(BOOK_INDEX_LIST_KEY, indexList);
result.put(BOOK_CONTENT_LIST_KEY, contentList);
}
}
return result;
}
@ -267,7 +294,7 @@ public class CrawlParser {
ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
if (forEntity.getStatusCode() == HttpStatus.OK) {
String body = forEntity.getBody();
if(body.length() < Constants.INVALID_HTML_LENGTH){
if (body.length() < Constants.INVALID_HTML_LENGTH) {
return processErrorHttpResult(url);
}
//成功获得html内容
@ -280,14 +307,30 @@ public class CrawlParser {
}
private static String getByHttpClientWithChrome(String url) {
try {
String body = HttpUtil.getByHttpClientWithChrome(url);
if (body != null && body.length() < Constants.INVALID_HTML_LENGTH) {
return processErrorHttpResult(url);
}
//成功获得html内容
return body;
} catch (Exception e) {
e.printStackTrace();
}
return processErrorHttpResult(url);
}
@SneakyThrows
private static String processErrorHttpResult(String url){
private static String processErrorHttpResult(String url) {
Integer count = retryCount.get();
if(count == null){
if (count == null) {
count = 0;
}
if(count < Constants.HTTP_FAIL_RETRY_COUNT){
Thread.sleep( new Random().nextInt(10*1000));
if (count < Constants.HTTP_FAIL_RETRY_COUNT) {
Thread.sleep(new Random().nextInt(10 * 1000));
retryCount.set(++count);
return getByHttpClient(url);
}

View File

@ -58,6 +58,7 @@ public class StarterListener implements ServletContextListener {
Book book = CrawlParser.parseBook(ruleBean, needUpdateBook.getCrawlBookId());
//这里只做老书更新
book.setId(needUpdateBook.getId());
book.setWordCount(needUpdateBook.getWordCount());
if (needUpdateBook.getPicUrl() != null && needUpdateBook.getPicUrl().contains(Constants.LOCAL_PIC_PREFIX)) {
//本地图片则不更新
book.setPicUrl(null);

View File

@ -65,9 +65,8 @@ public interface BookService {
* @param book 小说数据
* @param bookIndexList 目录集合
* @param bookContentList 内容集合
* @param existBookIndexMap 已存在的章节Map
* */
void updateBookAndIndexAndContent(Book book, List<BookIndex> bookIndexList, List<BookContent> bookContentList, Map<Integer, BookIndex> existBookIndexMap);
* @param existBookIndexMap 已存在的章节Map */
void updateBookAndIndexAndContent(Book book, List<BookIndex> bookIndexList, List<BookContent> bookContentList, Map<Integer, BookIndex> existBookIndexMap);
/**
* 更新一下最后一次的抓取时间

View File

@ -1,6 +1,5 @@
package com.java2nb.novel.service.impl;
import com.java2nb.novel.core.utils.IdWorker;
import com.java2nb.novel.entity.Book;
import com.java2nb.novel.entity.BookContent;
import com.java2nb.novel.entity.BookIndex;
@ -79,12 +78,9 @@ public class BookServiceImpl implements BookService {
if(bookIndexList.size()>0) {
if (book.getId() == null) {
book.setId(new IdWorker().nextId());
}
//保存小说主表
book.setCreateTime(new Date());
bookMapper.insertSelective(book);
//批量保存目录和内容
@ -109,7 +105,7 @@ public class BookServiceImpl implements BookService {
@Override
public Map<Integer, BookIndex> queryExistBookIndexMap(Long bookId) {
List<BookIndex> bookIndexs = bookIndexMapper.selectMany(select(BookIndexDynamicSqlSupport.id,BookIndexDynamicSqlSupport.indexNum,BookIndexDynamicSqlSupport.indexName)
List<BookIndex> bookIndexs = bookIndexMapper.selectMany(select(BookIndexDynamicSqlSupport.id,BookIndexDynamicSqlSupport.indexNum,BookIndexDynamicSqlSupport.indexName,BookIndexDynamicSqlSupport.wordCount)
.from(BookIndexDynamicSqlSupport.bookIndex)
.where(BookIndexDynamicSqlSupport.bookId,isEqualTo(bookId))
.build()
@ -122,36 +118,19 @@ public class BookServiceImpl implements BookService {
@Transactional(rollbackFor = Exception.class)
@Override
public void updateBookAndIndexAndContent(Book book, List<BookIndex> bookIndexList, List<BookContent> bookContentList, Map<Integer, BookIndex> existBookIndexMap) {
Date currentDate = new Date();
public void updateBookAndIndexAndContent(Book book, List<BookIndex> bookIndexList, List<BookContent> bookContentList, Map<Integer, BookIndex> existBookIndexMap) {
for (int i = 0; i < bookIndexList.size(); i++) {
BookIndex bookIndex = bookIndexList.get(i);
BookContent bookContent = bookContentList.get(i);
//插入或更新目录
Integer wordCount = bookContent.getContent().length();
bookIndex.setWordCount(wordCount);
bookIndex.setUpdateTime(currentDate);
if(bookIndex.getId() == null) {
if(!existBookIndexMap.containsKey(bookIndex.getIndexNum())) {
//插入
bookIndex.setBookId(book.getId());
Long indexId = new IdWorker().nextId();
bookIndex.setId(indexId);
bookIndex.setCreateTime(currentDate);
bookIndexMapper.insertSelective(bookIndex);
}else{
//更新
bookIndexMapper.updateByPrimaryKeySelective(bookIndex);
}
if(bookContent.getIndexId() == null) {
//插入
bookContent.setIndexId(bookIndex.getId());
bookContentMapper.insertSelective(bookContent);
}else{
//更新
bookIndexMapper.updateByPrimaryKeySelective(bookIndex);
bookContentMapper.update(update(BookContentDynamicSqlSupport.bookContent)
.set(BookContentDynamicSqlSupport.content)
.equalTo(bookContent.getContent())
@ -160,21 +139,10 @@ public class BookServiceImpl implements BookService {
.render(RenderingStrategies.MYBATIS3));
}
}
//更新小说主表
if(bookIndexList.size()>0) {
//有更新章节,才需要更新以下字段
book.setWordCount(queryTotalWordCount(book.getId()));
BookIndex lastIndex = bookIndexList.get(bookIndexList.size()-1);
if(!existBookIndexMap.containsKey(lastIndex.getIndexNum())) {
//如果最新章节不在已存在章节中,那么更新小说表最新章节信息
book.setLastIndexId(lastIndex.getId());
book.setLastIndexName(lastIndex.getIndexName());
book.setLastIndexUpdateTime(currentDate);
}
}
book.setUpdateTime(currentDate);
book.setBookName(null);
book.setAuthorName(null);
if(Constants.VISIT_COUNT_DEFAULT.equals(book.getVisitCount())) {

View File

@ -30,6 +30,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.java2nb.novel.core.utils.HttpUtil.getByHttpClient;
import static com.java2nb.novel.core.utils.HttpUtil.getByHttpClientWithChrome;
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.crawlBookId;
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.crawlSourceId;
import static com.java2nb.novel.mapper.CrawlSourceDynamicSqlSupport.*;
@ -217,7 +218,7 @@ public class CrawlServiceImpl implements CrawlService {
.replace("{catId}", ruleBean.getCatIdRule().get("catId" + catId))
.replace("{page}", page + "");
String bookListHtml = getByHttpClient(catBookListUrl);
String bookListHtml = getByHttpClientWithChrome(catBookListUrl);
if (bookListHtml != null) {
Pattern bookIdPatten = Pattern.compile(ruleBean.getBookIdPatten());
Matcher bookIdMatcher = bookIdPatten.matcher(bookListHtml);

View File

@ -5,7 +5,7 @@
<select id="queryNeedUpdateBook" resultType="com.java2nb.novel.entity.Book">
select id,crawl_source_id,crawl_book_id,crawl_last_time,pic_url
select id,crawl_source_id,crawl_book_id,crawl_last_time,pic_url,word_count
from book where last_index_update_time > #{startDate} and crawl_source_id is not null
order by crawl_last_time
limit ${limit}
@ -15,8 +15,7 @@
<select id="queryTotalWordCount" parameterType="long" resultType="int">
select sum(t2.word_count) from book t1 inner join book_index t2
on t1.id = t2.book_id and t1.id = #{bookId}
select sum(word_count) from book_index where book_id = #{bookId}
</select>
<update id="updateCrawlLastTime">

View File

@ -96,7 +96,7 @@
<script language="javascript" type="text/javascript">
$(function () {
$.ajax({
type: "POST",
type: "get",
url: "/crawl/listCrawlByPage",
data: {'curr':1,'limit':100},
dataType: "json",

View File

@ -125,7 +125,7 @@
function search(curr, limit) {
$.ajax({
type: "POST",
type: "get",
url: "/crawl/listCrawlSingleTaskByPage",
data: {'curr': curr, 'limit': limit},
dataType: "json",
@ -205,9 +205,9 @@
function del(id) {
$.ajax({
type: "POST",
url: "/crawl/delCrawlSingleTask",
data: {'id': id},
type: "delete",
url: "/crawl/delCrawlSingleTask/"+id,
data: {},
dataType: "json",
success: function (data) {
if (data.code == 200) {

View File

@ -117,7 +117,7 @@
示例:<b></b>
<li><input type="text" id="visitCountPatten" class="s_input icon_key"
placeholder="小说点击量的正则表达式"></li>
示例:<b>&lt;p class=\"review\"&gt;</b>
示例:<b>&lt;p class="review"&gt;</b>
<li><input type="text" id="descStart" class="s_input icon_key"
placeholder="小说简介开始截取字符串"></li>
示例:<b>&lt;/p&gt;</b>

View File

@ -122,7 +122,7 @@
function search(curr, limit) {
$.ajax({
type: "POST",
type: "get",
url: "/crawl/listCrawlByPage",
data: {'curr':curr,'limit':limit},
dataType: "json",

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>novel</artifactId>
<groupId>com.java2nb</groupId>
<version>3.0.2</version>
<version>3.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -13,10 +13,7 @@ import com.java2nb.novel.service.BookService;
import com.java2nb.novel.service.FriendLinkService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -38,7 +35,7 @@ public class AuthorController extends BaseController{
/**
* 校验笔名是否存在
* */
@PostMapping("checkPenName")
@GetMapping("checkPenName")
public ResultBean checkPenName(String penName){
return ResultBean.ok(authorService.checkPenName(penName));
@ -47,7 +44,7 @@ public class AuthorController extends BaseController{
/**
* 作家发布小说分页列表查询
* */
@PostMapping("listBookByPage")
@GetMapping("listBookByPage")
public ResultBean listBookByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "10") int pageSize ,HttpServletRequest request){
return ResultBean.ok(new PageInfo<>(bookService.listBookPageByUserId(getUserDetails(request).getId(),page,pageSize)
@ -90,8 +87,8 @@ public class AuthorController extends BaseController{
/**
* 删除章节
*/
@PostMapping("deleteIndex")
public ResultBean deleteIndex(Long indexId, HttpServletRequest request) {
@DeleteMapping("deleteIndex/{indexId}")
public ResultBean deleteIndex(@PathVariable("indexId") Long indexId, HttpServletRequest request) {
Author author = checkAuthor(request);
@ -136,8 +133,8 @@ public class AuthorController extends BaseController{
/**
* 查询章节内容
*/
@PostMapping("queryIndexContent")
public ResultBean queryIndexContent(Long indexId, HttpServletRequest request) {
@GetMapping("queryIndexContent/{indexId}")
public ResultBean queryIndexContent(@PathVariable("indexId") Long indexId, HttpServletRequest request) {
Author author = checkAuthor(request);
@ -167,7 +164,7 @@ public class AuthorController extends BaseController{
/**
* 作家日收入统计数据分页列表查询
* */
@PostMapping("listIncomeDailyByPage")
@GetMapping("listIncomeDailyByPage")
public ResultBean listIncomeDailyByPage(@RequestParam(value = "curr", defaultValue = "1") int page,
@RequestParam(value = "limit", defaultValue = "10") int pageSize ,
@RequestParam(value = "bookId", defaultValue = "0") Long bookId,
@ -183,7 +180,7 @@ public class AuthorController extends BaseController{
/**
* 作家月收入统计数据分页列表查询
* */
@PostMapping("listIncomeMonthByPage")
@GetMapping("listIncomeMonthByPage")
public ResultBean listIncomeMonthByPage(@RequestParam(value = "curr", defaultValue = "1") int page,
@RequestParam(value = "limit", defaultValue = "10") int pageSize ,
@RequestParam(value = "bookId", defaultValue = "0") Long bookId,

View File

@ -12,10 +12,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
@ -41,7 +38,7 @@ public class BookController extends BaseController{
/**
* 查询首页小说设置列表数据
* */
@PostMapping("listBookSetting")
@GetMapping("listBookSetting")
public ResultBean listBookSetting(){
return ResultBean.ok(bookService.listBookSettingVO());
}
@ -49,7 +46,7 @@ public class BookController extends BaseController{
/**
* 查询首页点击榜单数据
* */
@PostMapping("listClickRank")
@GetMapping("listClickRank")
public ResultBean listClickRank(){
return ResultBean.ok(bookService.listClickRank());
}
@ -57,7 +54,7 @@ public class BookController extends BaseController{
/**
* 查询首页新书榜单数据
* */
@PostMapping("listNewRank")
@GetMapping("listNewRank")
public ResultBean listNewRank(){
return ResultBean.ok(bookService.listNewRank());
}
@ -65,7 +62,7 @@ public class BookController extends BaseController{
/**
* 查询首页更新榜单数据
* */
@PostMapping("listUpdateRank")
@GetMapping("listUpdateRank")
public ResultBean listUpdateRank(){
return ResultBean.ok(bookService.listUpdateRank());
}
@ -73,7 +70,7 @@ public class BookController extends BaseController{
/**
* 查询小说分类列表
* */
@PostMapping("listBookCategory")
@GetMapping("listBookCategory")
public ResultBean listBookCategory(){
return ResultBean.ok(bookService.listBookCategory());
}
@ -81,7 +78,7 @@ public class BookController extends BaseController{
/**
* 分页搜索
* */
@PostMapping("searchByPage")
@GetMapping("searchByPage")
public ResultBean searchByPage(BookSP bookSP, @RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "20") int pageSize){
PageInfo<BookVO> pageInfo = bookService.searchByPage(bookSP,page,pageSize);
return ResultBean.ok(pageInfo);
@ -90,8 +87,8 @@ public class BookController extends BaseController{
/**
* 查询小说详情信息
* */
@PostMapping("queryBookDetail")
public ResultBean queryBookDetail(Long id){
@GetMapping("queryBookDetail/{id}")
public ResultBean queryBookDetail(@PathVariable("id") Long id){
return ResultBean.ok(bookService.queryBookDetail(id));
}
@ -99,7 +96,7 @@ public class BookController extends BaseController{
/**
* 查询小说排行信息
* */
@PostMapping("listRank")
@GetMapping("listRank")
public ResultBean listRank(@RequestParam(value = "type",defaultValue = "0") Byte type,@RequestParam(value = "limit",defaultValue = "30") Integer limit){
return ResultBean.ok(bookService.listRank(type,limit));
}
@ -120,7 +117,7 @@ public class BookController extends BaseController{
/**
* 查询章节相关信息
* */
@PostMapping("queryBookIndexAbout")
@GetMapping("queryBookIndexAbout")
public ResultBean queryBookIndexAbout(Long bookId,Long lastBookIndexId) {
Map<String,Object> data = new HashMap<>(2);
data.put("bookIndexCount",bookService.queryIndexCount(bookId));
@ -135,7 +132,7 @@ public class BookController extends BaseController{
/**
* 根据分类id查询同类推荐书籍
* */
@PostMapping("listRecBookByCatId")
@GetMapping("listRecBookByCatId")
public ResultBean listRecBookByCatId(Integer catId) {
return ResultBean.ok(bookService.listRecBookByCatId(catId));
}
@ -144,7 +141,7 @@ public class BookController extends BaseController{
/**
*分页查询书籍评论列表
* */
@PostMapping("listCommentByPage")
@GetMapping("listCommentByPage")
public ResultBean listCommentByPage(@RequestParam("bookId") Long bookId,@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize) {
return ResultBean.ok(new PageInfo<>(bookService.listCommentByPage(null,bookId,page,pageSize)));
}
@ -165,7 +162,7 @@ public class BookController extends BaseController{
/**
* 根据小说ID查询小说前十条最新更新目录集合
* */
@PostMapping("queryNewIndexList")
@GetMapping("queryNewIndexList")
public ResultBean queryNewIndexList(Long bookId){
return ResultBean.ok(bookService.queryIndexList(bookId,"index_num desc",1,10));
}
@ -173,8 +170,8 @@ public class BookController extends BaseController{
/**
* 目录页
* */
@PostMapping("/queryIndexList")
public ResultBean indexList(Long bookId,@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize,@RequestParam(value = "orderBy") String orderBy) {
@GetMapping("/queryIndexList")
public ResultBean indexList(Long bookId,@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize,@RequestParam(value = "orderBy",defaultValue = "index_num desc") String orderBy) {
return ResultBean.ok(new PageInfo<>(bookService.queryIndexList(bookId,orderBy,page,pageSize)));
}

View File

@ -4,6 +4,7 @@ import com.java2nb.novel.core.bean.ResultBean;
import com.java2nb.novel.service.FriendLinkService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -22,7 +23,7 @@ public class FriendLinkController {
/**
* 查询首页友情链接
* */
@PostMapping("listIndexLink")
@GetMapping("listIndexLink")
public ResultBean listIndexLink(){
return ResultBean.ok(friendLinkService.listIndexLink());
}

View File

@ -5,10 +5,7 @@ import com.java2nb.novel.core.bean.ResultBean;
import com.java2nb.novel.service.NewsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* @author 11797
@ -24,7 +21,7 @@ public class NewsController {
/**
* 查询首页新闻
* */
@PostMapping("listIndexNews")
@GetMapping("listIndexNews")
public ResultBean listIndexNews(){
return ResultBean.ok(newsService.listIndexNews());
}
@ -32,7 +29,7 @@ public class NewsController {
/**
* 分页查询新闻列表
* */
@PostMapping("listByPage")
@GetMapping("listByPage")
public ResultBean listByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize){
return ResultBean.ok(new PageInfo<>(newsService.listByPage(page,pageSize)));
}

View File

@ -6,19 +6,17 @@ import com.java2nb.novel.core.bean.UserDetails;
import com.java2nb.novel.core.cache.CacheService;
import com.java2nb.novel.core.enums.ResponseStatus;
import com.java2nb.novel.core.utils.RandomValidateCodeUtil;
import com.java2nb.novel.core.valid.AddGroup;
import com.java2nb.novel.core.valid.UpdateGroup;
import com.java2nb.novel.entity.User;
import com.java2nb.novel.entity.UserBuyRecord;
import com.java2nb.novel.form.UserForm;
import com.java2nb.novel.service.BookService;
import com.java2nb.novel.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
@ -45,12 +43,7 @@ public class UserController extends BaseController {
* 登陆
*/
@PostMapping("login")
public ResultBean login(@Valid UserForm user, BindingResult result) {
//判断参数是否合法
if (result.hasErrors()) {
log.info(result.getAllErrors().toString());
return ResultBean.fail(ResponseStatus.PARAM_ERROR);
}
public ResultBean login(User user) {
//登陆
UserDetails userDetails = userService.login(user);
@ -67,13 +60,8 @@ public class UserController extends BaseController {
* 注册
*/
@PostMapping("register")
public ResultBean register(@Valid UserForm user, @RequestParam(value = "velCode", defaultValue = "") String velCode, BindingResult result) {
public ResultBean register(@Validated({AddGroup.class}) User user, @RequestParam(value = "velCode", defaultValue = "") String velCode) {
//判断参数是否合法
if (result.hasErrors()) {
log.info(result.getAllErrors().toString());
return ResultBean.fail(ResponseStatus.PARAM_ERROR);
}
//判断验证码是否正确
if (!velCode.equals(cacheService.get(RandomValidateCodeUtil.RANDOM_CODE_KEY))) {
@ -115,7 +103,7 @@ public class UserController extends BaseController {
/**
* 查询小说是否已加入书架
*/
@PostMapping("queryIsInShelf")
@GetMapping("queryIsInShelf")
public ResultBean queryIsInShelf(Long bookId, HttpServletRequest request) {
UserDetails userDetails = getUserDetails(request);
if (userDetails == null) {
@ -140,8 +128,8 @@ public class UserController extends BaseController {
/**
* 移出书架
* */
@PostMapping("removeFromBookShelf")
public ResultBean removeFromBookShelf(Long bookId, HttpServletRequest request) {
@DeleteMapping("removeFromBookShelf/{bookId}")
public ResultBean removeFromBookShelf(@PathVariable("bookId") Long bookId, HttpServletRequest request) {
UserDetails userDetails = getUserDetails(request);
if (userDetails == null) {
return ResultBean.fail(ResponseStatus.NO_LOGIN);
@ -153,7 +141,7 @@ public class UserController extends BaseController {
/**
* 分页查询书架
* */
@PostMapping("listBookShelfByPage")
@GetMapping("listBookShelfByPage")
public ResultBean listBookShelfByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "10") int pageSize,HttpServletRequest request) {
UserDetails userDetails = getUserDetails(request);
if (userDetails == null) {
@ -165,7 +153,7 @@ public class UserController extends BaseController {
/**
* 分页查询阅读记录
* */
@PostMapping("listReadHistoryByPage")
@GetMapping("listReadHistoryByPage")
public ResultBean listReadHistoryByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "10") int pageSize,HttpServletRequest request) {
UserDetails userDetails = getUserDetails(request);
if (userDetails == null) {
@ -203,7 +191,7 @@ public class UserController extends BaseController {
/**
* 分页查询我的反馈列表
* */
@PostMapping("listUserFeedBackByPage")
@GetMapping("listUserFeedBackByPage")
public ResultBean listUserFeedBackByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize, HttpServletRequest request){
UserDetails userDetails = getUserDetails(request);
if (userDetails == null) {
@ -215,7 +203,7 @@ public class UserController extends BaseController {
/**
* 查询个人信息
* */
@PostMapping("userInfo")
@GetMapping("userInfo")
public ResultBean userInfo(HttpServletRequest request) {
UserDetails userDetails = getUserDetails(request);
if (userDetails == null) {
@ -228,7 +216,7 @@ public class UserController extends BaseController {
* 更新个人信息
* */
@PostMapping("updateUserInfo")
public ResultBean updateUserInfo(User user,HttpServletRequest request) {
public ResultBean updateUserInfo(@Validated({UpdateGroup.class}) User user, HttpServletRequest request) {
UserDetails userDetails = getUserDetails(request);
if (userDetails == null) {
return ResultBean.fail(ResponseStatus.NO_LOGIN);
@ -263,7 +251,7 @@ public class UserController extends BaseController {
/**
* 分页查询用户书评
* */
@PostMapping("listCommentByPage")
@GetMapping("listCommentByPage")
public ResultBean listCommentByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize,HttpServletRequest request) {
UserDetails userDetails = getUserDetails(request);
if (userDetails == null) {

View File

@ -0,0 +1,25 @@
package com.java2nb.novel.core.config;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
/**
* 错误页面配置
* @author xiongxiaoyang
*/
@Configuration
public class ErrorPageConfig implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
/*1.错误类型为404默认显示404.html网页*/
ErrorPage e404 = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
/**
TODO 2.错误类型为500表示服务器响应错误默认显示/500.html网页
*/
registry.addErrorPages(e404);
}
}

View File

@ -86,7 +86,11 @@ public class JwtTokenUtil {
*/
private boolean isTokenExpired(String token) {
Date expiredDate = getExpiredDateFromToken(token);
return expiredDate.before(new Date());
if(expiredDate == null){
return true;
}else {
return expiredDate.before(new Date());
}
}
/**
@ -94,7 +98,7 @@ public class JwtTokenUtil {
*/
private Date getExpiredDateFromToken(String token) {
Claims claims = getClaimsFromToken(token);
return claims.getExpiration();
return claims != null ? claims.getExpiration() : null;
}
/**

View File

@ -1,20 +0,0 @@
package com.java2nb.novel.form;
import lombok.Data;
import javax.annotation.Generated;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
@Data
public class UserForm {
@NotBlank(message="手机号不能为空!")
@Pattern(regexp="^1[3|4|5|6|7|8|9][0-9]{9}$",message="手机号格式不正确!")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String username;
@NotBlank(message="密码不能为空!")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String password;
}

View File

@ -1,6 +1,6 @@
package com.java2nb.novel.controller;
package com.java2nb.novel.page;
import com.java2nb.novel.core.bean.ResultBean;
import com.java2nb.novel.controller.BaseController;
import com.java2nb.novel.core.bean.UserDetails;
import com.java2nb.novel.core.utils.ThreadLocalUtil;
import com.java2nb.novel.entity.*;
@ -9,16 +9,16 @@ import com.java2nb.novel.service.BookService;
import com.java2nb.novel.service.NewsService;
import com.java2nb.novel.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
@ -27,7 +27,7 @@ import java.util.List;
@Slf4j
@RequiredArgsConstructor
@Controller
public class PageController extends BaseController{
public class PageController extends BaseController {
private final BookService bookService;
@ -97,6 +97,7 @@ public class PageController extends BaseController{
/**
* 详情页
* */
@SneakyThrows
@RequestMapping("/book/{bookId}.html")
public String bookDetail(@PathVariable("bookId") Long bookId, Model model) {
Book book = bookService.queryBookDetail(bookId);
@ -112,6 +113,7 @@ public class PageController extends BaseController{
/**
* 目录页
* */
@SneakyThrows
@RequestMapping("/book/indexList-{bookId}.html")
public String indexList(@PathVariable("bookId") Long bookId, Model model) {
Book book = bookService.queryBookDetail(bookId);
@ -125,13 +127,14 @@ public class PageController extends BaseController{
/**
* 内容页
* */
@SneakyThrows
@RequestMapping("/book/{bookId}/{bookIndexId}.html")
public String indexList(@PathVariable("bookId") Long bookId,@PathVariable("bookIndexId") Long bookIndexId, HttpServletRequest request,Model model) {
public String indexList(@PathVariable("bookId") Long bookId,@PathVariable("bookIndexId") Long bookIndexId, HttpServletRequest request, Model model) {
//查询书籍
Book book = bookService.queryBookDetail(bookId);
model.addAttribute("book",book);
//查询目录
BookIndex bookIndex = bookService.queryBookIndex(bookIndexId);
model.addAttribute("book",book);
model.addAttribute("bookIndex",bookIndex);
//查询上一章节目录ID
Long preBookIndexId = bookService.queryPreBookIndexId(bookId,bookIndex.getIndexNum());

View File

@ -3,7 +3,6 @@ package com.java2nb.novel.service;
import com.java2nb.novel.core.bean.UserDetails;
import com.java2nb.novel.entity.UserBuyRecord;
import com.java2nb.novel.form.UserForm;
import com.java2nb.novel.vo.BookReadHistoryVO;
import com.java2nb.novel.vo.BookShelfVO;
import com.java2nb.novel.entity.User;
@ -19,17 +18,17 @@ public interface UserService {
/**
* 用户注册
* @param form 用户注册提交信息类
* @param user 用户注册信息类
* @return jwt载体信息类
* */
UserDetails register(UserForm form);
UserDetails register(User user);
/**
* 用户登陆
* @param form 用户登陆提交信息类
* @param user 用户登陆信息类
* @return jwt载体信息类
* */
UserDetails login(UserForm form);
UserDetails login(User user);
/**
* 查询小说是否已加入书架

View File

@ -5,7 +5,6 @@ import com.java2nb.novel.core.bean.UserDetails;
import com.java2nb.novel.core.utils.BeanUtil;
import com.java2nb.novel.entity.*;
import com.java2nb.novel.entity.User;
import com.java2nb.novel.form.UserForm;
import com.java2nb.novel.service.UserService;
import com.java2nb.novel.core.enums.ResponseStatus;
import com.java2nb.novel.core.exception.BusinessException;
@ -29,7 +28,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.book;
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.id;
import static com.java2nb.novel.mapper.UserBookshelfDynamicSqlSupport.userBookshelf;
import static com.java2nb.novel.mapper.UserDynamicSqlSupport.*;
@ -59,11 +57,11 @@ public class UserServiceImpl implements UserService {
@Override
public UserDetails register(UserForm form) {
public UserDetails register(User user) {
//查询用户名是否已注册
SelectStatementProvider selectStatement = select(count(id))
.from(user)
.where(username, isEqualTo(form.getUsername()))
.from(UserDynamicSqlSupport.user)
.where(username, isEqualTo(user.getUsername()))
.build()
.render(RenderingStrategies.MYBATIS3);
long count = userMapper.count(selectStatement);
@ -72,7 +70,7 @@ public class UserServiceImpl implements UserService {
throw new BusinessException(ResponseStatus.USERNAME_EXIST);
}
User entity = new User();
BeanUtils.copyProperties(form,entity);
BeanUtils.copyProperties(user,entity);
//数据库生成注册记录
Long id = new IdWorker().nextId();
entity.setId(id);
@ -91,12 +89,12 @@ public class UserServiceImpl implements UserService {
}
@Override
public UserDetails login(UserForm form) {
public UserDetails login(User user) {
//根据用户名密码查询记录
SelectStatementProvider selectStatement = select(id, username,nickName)
.from(user)
.where(username, isEqualTo(form.getUsername()))
.and(password, isEqualTo(MD5Util.MD5Encode(form.getPassword(), Charsets.UTF_8.name())))
.from(UserDynamicSqlSupport.user)
.where(username, isEqualTo(user.getUsername()))
.and(password, isEqualTo(MD5Util.MD5Encode(user.getPassword(), Charsets.UTF_8.name())))
.build()
.render(RenderingStrategies.MYBATIS3);
List<User> users = userMapper.selectMany(selectStatement);
@ -105,10 +103,10 @@ public class UserServiceImpl implements UserService {
}
//生成UserDetail对象并返回
UserDetails userDetails = new UserDetails();
User user = users.get(0);
user = users.get(0);
userDetails.setId(user.getId());
userDetails.setNickName(user.getNickName());
userDetails.setUsername(form.getUsername());
userDetails.setUsername(user.getUsername());
return userDetails;
}
@ -232,12 +230,9 @@ public class UserServiceImpl implements UserService {
@Override
public void updateUserInfo(Long userId, User user) {
User updateUser = new User();
updateUser.setId(userId);
updateUser.setNickName(user.getNickName());
updateUser.setUserSex(user.getUserSex());
updateUser.setUpdateTime(new Date());
userMapper.updateByPrimaryKeySelective(updateUser);
user.setId(userId);
user.setUpdateTime(new Date());
userMapper.updateByPrimaryKeySelective(user);
}

View File

@ -25,6 +25,14 @@ spring:
jest:
uris: http://127.0.0.1:9200
#thymeleaf模版路径配置
thymeleaf:
prefix: file:${user.dir}/templates/${templates.name}/html/
suffix: .html
#静态文件路径配置
resources:
static-locations: file:${user.dir}/templates/${templates.name}/static/
redisson:
singleServerConfig:
address: 127.0.0.1:6379
@ -64,4 +72,14 @@ book:
#字数
word-count: 1000
#价值(屋币)
value: 5
value: 5
#模版配置
templates:
name: orange

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -2,39 +2,13 @@ var SCYC = {
}
$.extend($.fn.validatebox.defaults.rules, {
checkBookName: {
validator: function (value, param) {
var url = "/aspx/book/booklist.aspx";
var data = { bid: param, bname: value, act: "getbooknamerepeat" };
var bool = false;
$.ajax({
type: "post",
dataType: 'html',
async: false,
url: url,
data: data,
cache: false,
success: function (result) {
if (result == "1") {
$.fn.validatebox.defaults.rules.checkBookName.message = '该书名已存在,请重新输入';
bool = false;
} else {
$.fn.validatebox.defaults.rules.checkBookName.message = '';
bool = true;
}
}
});
return bool;
message: '';
}
},
checkNiceName: {
checkPenName: {
validator: function (value, param) {
var url = "/author/checkPenName";
var data = { penName: value};
var bool = false;
$.ajax({
type: "post",
type: "get",
dataType: 'json',
async: false,
url: url,
@ -42,10 +16,10 @@ $.extend($.fn.validatebox.defaults.rules, {
cache: false,
success: function (result) {
if (result.data) {
$.fn.validatebox.defaults.rules.checkNiceName.message = '笔名已存在,请重新输入';
$.fn.validatebox.defaults.rules.checkPenName.message = '笔名已存在,请重新输入';
bool = false;
} else {
$.fn.validatebox.defaults.rules.checkNiceName.message = '';
$.fn.validatebox.defaults.rules.checkPenName.message = '';
bool = true;
}
}

View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Page Not Found</title>
<script>
setTimeout(function () {
location.href = '/';
},3000)
</script>
</head>
<body style="background: url(/images/404.jpeg) no-repeat;" >
</body>
</html>

View File

@ -56,7 +56,7 @@
function search(curr, limit) {
$.ajax({
type: "POST",
type: "get",
url: "/news/listByPage",
data: {'curr':curr,'limit':limit},
dataType: "json",

View File

@ -118,7 +118,7 @@
$.ajax({
type: "POST",
type: "get",
url: "/author/listIncomeMonthByPage",
data: {'curr':curr,'limit':limit},
dataType: "json",

View File

@ -124,7 +124,7 @@
}
$.ajax({
type: "POST",
type: "get",
url: "/author/listIncomeDailyByPage",
data: data,
dataType: "json",

View File

@ -134,9 +134,9 @@
}
$.ajax({
type: "POST",
url: "/author/queryIndexContent",
data: {'indexId':indexId},
type: "get",
url: "/author/queryIndexContent/"+indexId,
data: {},
dataType: "json",
success: function (data) {
if (data.code == 200) {

View File

@ -144,7 +144,7 @@
function search(curr, limit) {
$.ajax({
type: "POST",
type: "get",
url: "/author/listBookByPage",
data: {'curr':curr,'limit':limit},
dataType: "json",

View File

@ -144,7 +144,7 @@
function search(curr, limit) {
$.ajax({
type: "POST",
type: "get",
url: "/book/queryIndexList",
data: {'bookId': bookId, 'curr': curr, 'limit': limit, 'orderBy': 'index_num desc'},
dataType: "json",
@ -299,9 +299,9 @@
layer.close(index);
$.ajax({
type: "POST",
url: "/author/deleteIndex",
data: {'indexId': indexId},
type: "delete",
url: "/author/deleteIndex/"+indexId,
data: {},
dataType: "json",
success: function (data) {
if (data.code == 200) {

View File

@ -60,7 +60,7 @@
作者笔名:
</td>
<td>
<input name="penName" th:value="${author.penName}" type="text" maxlength="8" id="TxtNiceName" class="easyui-validatebox inpMain" data-options="required:true" validType="checkNiceName" />
<input name="penName" th:value="${author.penName}" type="text" maxlength="8" id="TxtNiceName" class="easyui-validatebox inpMain" data-options="required:true" validType="checkPenName" />
</td>
<td>

View File

@ -119,7 +119,7 @@
function searchComments(curr, limit) {
$.ajax({
type: "POST",
type: "get",
url: "/book/listCommentByPage",
data: {'bookId': $("#bookId").val(),'curr':curr,'limit':limit},
dataType: "json",

View File

@ -234,7 +234,7 @@
}
//查询是否在书架
$.ajax({
type: "POST",
type: "get",
url: "/user/queryIsInShelf",
data: {'bookId':$("#bookId").val()},
dataType: "json",

View File

@ -199,7 +199,7 @@
var lastBookIndexId = $("#lastBookIndexId").val();
if(lastBookIndexId){
$.ajax({
type: "POST",
type: "get",
url: "/book/queryBookIndexAbout",
data: {'bookId': bookId, 'lastBookIndexId': lastBookIndexId},
dataType: "json",
@ -226,7 +226,7 @@
<script language="javascript" type="text/javascript">
//查询是否在书架
$.ajax({
type: "POST",
type: "get",
url: "/user/queryIsInShelf",
data: {'bookId': $("#bookId").val()},
dataType: "json",
@ -255,7 +255,7 @@
function loadCommentList(){
$.ajax({
type: "POST",
type: "get",
url: "/book/listCommentByPage",
data: {'bookId': $("#bookId").val()},
dataType: "json",
@ -335,7 +335,7 @@
var bookCatId = $("#bookCatId").val();
//查询同类推荐
$.ajax({
type: "POST",
type: "get",
url: "/book/listRecBookByCatId",
data: {'catId': bookCatId},
dataType: "json",

View File

@ -88,7 +88,7 @@
function listRank(rankType){
$.ajax({
type: "POST",
type: "get",
url: "/book/listRank",
data: {'type':rankType,'limit':30},
dataType: "json",

View File

@ -163,7 +163,7 @@
$.ajax({
type: "POST",
type: "get",
url: "/book/searchByPage",
data: searchData,
dataType: "json",
@ -227,7 +227,7 @@
function listBookCategory(c) {
$.ajax({
type: "POST",
type: "get",
url: "/book/listBookCategory",
data: {},
dataType: "json",

View File

@ -2,7 +2,7 @@
<div class="box_center cf">
<div class="copyright">
<ul >
<li class="menu"><a href="/?to=mobile">手机站</a><i class="line">|</i><a href="/">网站首页</a><i class="line">|</i><a href="/about/default.html" >关于我们</a><i class="line">|</i><a href="/about/contact.html" >联系我们</a><i class="line">|</i><a href="/user/feedback.html" >反馈留言</a><i class="line">|</i><a href="/author/index.html" >作家专区</a></li>
<li class="menu"><a href="/?to=mobile">手机站</a><i class="line">|</i><a href="/">网站首页</a><i class="line">|</i><a href="/about/default.html" >关于我们</a><i class="line">|</i><a href="/about/contact.html" >联系我们</a><i class="line">|</i><a href="/user/feedback.html" >反馈留言</a><i class="line">|</i><a href="/author/index.html" >作家专区</a><i class="line">|</i><a href="/mobile/fiction_house.apk" >客户端</a></li>
<li th:text="'Copyright (C) '+#{website.domain}+' All rights reserved&nbsp;&nbsp;'+#{website.name}+'版权所有'"></li>
</ul>

View File

@ -157,7 +157,7 @@
$(function () {
//加载首页书籍设置数据
$.ajax({
type: "POST",
type: "get",
url: "/book/listBookSetting",
data: {},
dataType: "json",
@ -331,7 +331,7 @@
})
//首页新闻查询
$.ajax({
type: "POST",
type: "get",
url: "/news/listIndexNews",
data: {},
dataType: "json",
@ -359,7 +359,7 @@
//点击榜单数据查询
$.ajax({
type: "POST",
type: "get",
url: "/book/listClickRank",
data: {},
dataType: "json",
@ -402,7 +402,7 @@
})
//新书榜单查询
$.ajax({
type: "POST",
type: "get",
url: "/book/listNewRank",
data: {},
dataType: "json",
@ -446,7 +446,7 @@
})
//更新榜单查询
$.ajax({
type: "POST",
type: "get",
url: "/book/listUpdateRank",
data: {},
dataType: "json",
@ -504,7 +504,7 @@
})
//友情链接查询
$.ajax({
type: "POST",
type: "get",
url: "/friendLink/listIndexLink",
data: {},
dataType: "json",

View File

@ -195,7 +195,7 @@
<script>
//查询是否在书架
$.ajax({
type: "POST",
type: "get",
url: "/user/queryIsInShelf",
data: {'bookId': $("#bookIdHidden").val()},
dataType: "json",
@ -221,7 +221,7 @@
//查询最新目录集合
$.ajax({
type: "POST",
type: "get",
url: "/book/queryNewIndexList",
data: {'bookId': $("#bookIdHidden").val()},
dataType: "json",

View File

@ -168,7 +168,7 @@
}
$.ajax({
type: "POST",
type: "get",
url: "/book/searchByPage",
data: searchData,
dataType: "json",

View File

@ -4,7 +4,7 @@
<a href="/?to=pc" style="font-size: 14px;color: #fff;margin-left: 8px">电脑站</a>
<a href="/user/read_history.html" style="font-size: 14px;color: #fff;margin-left: 8px">阅读记录</a>
<a href="/user/favorites.html" style="font-size: 14px;color: #fff;margin-left: 8px">书架</a>
<a href="/mobile/HotBook.apk" style="font-size: 14px;color: #fff;margin-left: 8px">客户端</a>
<a href="/mobile/fiction_house.apk" style="font-size: 14px;color: #fff;margin-left: 8px">客户端</a>
<!--<a href="https://www.zinglizingli.xyz/me/index.html" style="font-size: 14px;color: #fff;margin-left: 8px">开发者</a>-->

View File

@ -91,7 +91,7 @@
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=7">女频小说</a></dd>
</dl>
</li>
<li class="layui-nav-item"><a href="javascript:toMyCollect()">书架</a></li>
<li class="layui-nav-item"><a href="/user/favorites.html">书架</a></li>
</ul>
<ul class="layui-nav pc" lay-filter="" style="padding:0 36px;text-align: center">
@ -235,7 +235,7 @@
<script>
//加载首页书籍设置数据
$.ajax({
type: "POST",
type: "get",
url: "/book/listBookSetting",
data: {},
dataType: "json",
@ -318,7 +318,7 @@
//更新榜单查询
$.ajax({
type: "POST",
type: "get",
url: "/book/listUpdateRank",
data: {},
dataType: "json",

View File

@ -86,7 +86,7 @@
//查询用户信息
$.ajax({
type: "POST",
type: "get",
url: "/user/userInfo",
data: {},
dataType: "json",

View File

@ -52,7 +52,7 @@
function search(curr, limit) {
$.ajax({
type: "POST",
type: "get",
url: "/user/listCommentByPage",
data: {'curr':curr,'limit':limit},
dataType: "json",

View File

@ -80,7 +80,7 @@
function search(curr, limit) {
$.ajax({
type: "POST",
type: "get",
url: "/user/listBookShelfByPage",
data: {'curr':curr,'limit':limit},
dataType: "json",

View File

@ -59,7 +59,7 @@
function search(curr, limit) {
$.ajax({
type: "POST",
type: "get",
url: "/user/listUserFeedBackByPage",
data: {'curr':curr,'limit':limit},
dataType: "json",

View File

@ -67,7 +67,7 @@
function search(curr, limit) {
$.ajax({
type: "POST",
type: "get",
url: "/user/listReadHistoryByPage",
data: {'curr':curr,'limit':limit},
dataType: "json",

View File

@ -57,7 +57,7 @@
<script type="text/javascript">
//查询用户信息
$.ajax({
type: "POST",
type: "get",
url: "/user/userInfo",
data: {},
dataType: "json",

View File

@ -53,7 +53,7 @@
<script type="text/javascript">
//查询用户信息
$.ajax({
type: "POST",
type: "get",
url: "/user/userInfo",
data: {},
dataType: "json",

View File

@ -45,7 +45,7 @@
<script type="text/javascript">
//查询用户信息
$.ajax({
type: "POST",
type: "get",
url: "/user/userInfo",
data: {},
dataType: "json",

View File

@ -81,7 +81,7 @@
<script type="text/javascript">
//查询用户信息
$.ajax({
type: "POST",
type: "get",
url: "/user/userInfo",
data: {},
dataType: "json",
@ -113,7 +113,7 @@
})
//查询书架列表
$.ajax({
type: "POST",
type: "get",
url: "/user/listBookShelfByPage",
data: {'limit':2},
dataType: "json",

View File

@ -5,11 +5,12 @@
<groupId>com.java2nb</groupId>
<artifactId>novel</artifactId>
<version>3.0.2</version>
<version>3.3.0</version>
<modules>
<module>novel-common</module>
<module>novel-front</module>
<module>novel-crawl</module>
<module>novel-admin</module>
</modules>
<packaging>pom</packaging>

View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Page Not Found</title>
<script>
setTimeout(function () {
location.href = '/';
},3000)
</script>
</head>
<body style="background: url(/images/404.jpeg) no-repeat;" >
</body>
</html>

View File

@ -0,0 +1,364 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta th:if="${catId == 9}" name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=1">
<meta th:if="${catId != 9}" name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title th:utext="${book.bookName}+${bookIndex.indexName}"></title>
<meta name="keywords" th:content="${book.bookName}+','+${bookIndex.indexName}">
<meta name="description"
th:content="${book.bookName}+'最新更新章节免费在线阅读TXT下载'">
<div th:include="common/css :: css"></div>
<script type="text/javascript">
function reinitIframe(){
var iframe = document.getElementById("frame_content");
try{
iframe.height =  iframe.contentWindow.document.documentElement.scrollHeight;
}catch (ex){}
}
window.setInterval("reinitIframe()", 200);
</script>
<script th:fragment="js" src="/js/jquery-1.9.1.js"></script>
<script th:fragment="js" src="/layui/layui.all.js"></script>
</div>
<style type="text/css">
.line-limit-length {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.indexP p a {
color: #4c6978;
}
.Readarea {
font-size: 18px;
line-height: 35px;
padding: 10px;
color: #333;
}
div, p {
wrap-work: break-word;
word-break: break-all;
word-wrap: break-word;
word-break: normal;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-ms-box-sizing: border-box;
}
.indexDiv a {
margin-left: 20px;
}
.Readpage {
font-size: 14px;
padding: 0;
background: #d4eaf2;
height: 40px;
line-height: 40px;
text-align: center;
}
div, p {
wrap-work: break-word;
word-break: break-all;
word-wrap: break-word;
word-break: normal;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-ms-box-sizing: border-box;
}
* {
margin: 0;
padding: 0;
/* background-attachment: fixed; */
}
user agent stylesheet
p {
display: block;
-webkit-margin-before: 1em;
-webkit-margin-after: 1em;
-webkit-margin-start: 0px;
-webkit-margin-end: 0px;
}
.huyanon {
border: 1px solid #64c878;
box-shadow: 0 1px 2px #b9ecc4 inset, 0 -1px 0 #6c9f76 inset, 0 -2px 3px #b9ecc4 inset;
background: -webkit-linear-gradient(top, #90dfa2, #84d494);
background: -moz-linear-gradient(top, #90dfa2, #84d494);
background: linear-gradient(top, #90dfa2, #84d494);
}
.Readpage a {
font-size: 16px;
padding: 2px 2px;
line-height: 35px;
}
.lightoff, .huyanoff, .sizebgon {
border: 1px solid #333;
box-shadow: 0 1px 2px #8b8b8b inset, 0 -1px 0 #3d3d3d inset, 0 -2px 3px #8b8b8b inset;
background: -webkit-linear-gradient(top, #656565, #4c4c4c);
background: -moz-linear-gradient(top, #656565, #4a4a4a);
background: linear-gradient(top, #656565, #4a4a4a);
}
.button {
width: 40px;
line-height: 38px;
text-align: center;
font-weight: bold;
color: #fff;
text-shadow: 1px 1px 1px #333;
border-radius: 5px;
margin: 3px 0px 0px 0;
position: relative;
overflow: hidden;
}
a {
color: #4c6978;
text-decoration: none;
border: none;
cursor: pointer;
}
.lighton {
border: 1px solid #d2a000;
box-shadow: 0 1px 2px #fedd71 inset, 0 -1px 0 #a38b39 inset, 0 -2px 3px #fedd71 inset;
background: -webkit-linear-gradient(top, #fece34, #d8a605);
background: -moz-linear-gradient(top, #fece34, #d8a605);
background: linear-gradient(top, #fece34, #d8a605);
}
.screen_toolbar {
position: fixed;
width: 100%;
left: 0px;
bottom: 100px;
text-align: center;
}
</style>
</head>
<body id="read">
<div id="content">
<input type="hidden" id="bookIdHidden" th:value="${book.id}"/>
<input type="hidden" id="bookNameHidden" th:value="${book.bookName}"/>
<input type="hidden" id="contentIdHidden" th:value="${bookIndex.id}"/>
<input type="hidden" id="indexNameHidden" th:value="${bookIndex.indexName}"/>
<input type="hidden" id="indexNumHidden" th:value="${bookIndex.indexNum}"/>
<script>
var token = localStorage.getItem("token");
</script>
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
<div style="width:10%;float: left;margin-left: 10px">
<a href="javascript:history.go(-1)">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe65c;</i></a>
</div>
<a style="color: #ffffff;" th:href="'/book/'+ ${book.id} + '.html'"><b style="padding-left: 5%;float: left;width: 69%" class="line-limit-length" th:utext="${bookIndex.indexName}+' '+${book.bookName}"></b></a>
<div style="width:10%;float: right;margin-right: 10px"><a href="/">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe68e;</i>
</a>
</div>
</div>
<p class="Readpage" style="background:#FFFFFF;padding:2px;">
<a id="lightdiv" class="button lighton" onclick="nr_setbg('light')">开灯</a>
<a id="huyandiv" class="button huyanon" onclick="nr_setbg('huyan')">护眼</a>&nbsp;&nbsp;&nbsp;&nbsp;
字体:<a id="fontbig" class="sizebg" onclick="nr_setbg('big')">大</a> <a id="fontmiddle" class="button sizebgon"
onclick="nr_setbg('middle')">中</a> <a
id="fontsmall" class="sizebg" onclick="nr_setbg('small')">小</a>
</p>
<div class="indexDiv" style="height: 42px;line-height: 42px;text-align:center;background: #f2f2f2">
<a th:href="${preBookIndexId!=0?'/book/'+book.id+'/'+preBookIndexId+'.html':'#'}">上一章</a>
<a th:href="'/book/indexList-'+${book.id}+'.html'">目录</a>
<a th:href="${nextBookIndexId!=0?'/book/'+book.id+'/'+nextBookIndexId+'.html':'#'}">下一章</a>
</div>
<!--<div id="screenInput" class="screen_toolbar" style="display: none">
<div style="height: 5px" class="layui-col-xs2 layui-col-sm3 layui-col-md3 layui-col-lg3"></div>
<div class="layui-col-xs6 layui-col-sm4 layui-col-md4 layui-col-lg4">
<input type="text" id="screenBulletText" required lay-verify="required" placeholder="请输入弹幕内容,右下角开关可控制弹幕是否开启" autocomplete="off"
class="layui-input">
</div>
<div class="layui-col-xs2 layui-col-sm1 layui-col-md1 layui-col-lg1">
<button class="layui-btn send">发送</button>
</div>
</div>
<form id="screenSwitch" class="layui-form">
<div class="layui-form-item" style="position: fixed;right: 0px;bottom: 100px" title="弹幕开关">
&lt;!&ndash; <label class="layui-form-label" style="opacity:0.5;font-weight: bold;color: red;">弹幕</label>&ndash;&gt;
<div class="layui-input-block">
<input class="clear" type="checkbox" name="switch" lay-skin="switch">
</div>
</div>
</form>-->
<div th:replace="common/js :: js">
</div>
<div id="chaptercontent" class="Readarea ReadAjax_content screen_container"
style="color: rgb(0, 0, 0); font-size: 25px;" th:if="${!needBuy}">
<p style="width:100%;text-alight:center; overflow: auto;-webkit-overflow-scrolling:touch;" >&nbsp;&nbsp;&nbsp;&nbsp;
<span
th:utext="${bookContent.content}"></span></p>
</div>
<div class="Readarea ReadAjax_content screen_container"
style="color: rgb(0, 0, 0); font-size: 10px;background-color: #fff" th:if="${needBuy}">
<h5>此章为VIP章节需要订阅后才能继续阅读</h5>
价格:<span style="color: red" th:text="${bookIndex.bookPrice}+'屋币(1元=100屋币)'"></span><br/>
<a href="javascript:buyBookIndex()" type="button" class="layui-btn layui-btn-sm layui-btn-radius">购买</a>
</div>
<div class="indexDiv" style="height: 42px;line-height: 42px;text-align:center;background: #f2f2f2">
<a th:href="${preBookIndexId!=0?'/book/'+book.id+'/'+preBookIndexId+'.html':'#'}">上一章</a>
<a th:href="'/book/indexList-'+${book.id}+'.html'">目录</a>
<a th:href="${nextBookIndexId!=0?'/book/'+book.id+'/'+nextBookIndexId+'.html':'#'}">下一章</a>
</div>
</div>
<div th:replace="common/footer :: footer">
</div>
<a name="buttom"></a>
</body>
<script>
var ua = navigator.userAgent;
var ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
isIphone =!ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
isAndroid = ua.match(/(Android)\s+([\d.]+)/),
isMobile = isIphone || isAndroid;
</script>
<script>
(function () {
//添加阅读记录
$.ajax({
type: "POST",
url: "/user/addReadHistory",
data: {'bookId': $("#bookIdHidden").val(), 'preContentId': $("#contentIdHidden").val()},
dataType: "json",
success: function (data) {
},
error: function () {
}
})
$("#content").css("min-height",($(window).height()-60)+"px");
})();
</script>
<script src="/js/read.js"></script>
<script language="javascript">getset()</script>
<script language="javascript">getset1()</script>
<script language="javascript">
var books = localStorage.getItem("historyBooks");
var item = parseInt($("#bookIdHidden").val());
if (books) {
var booksArr = JSON.parse(books);
if (booksArr.length >= 50) {
booksArr.splice(0, 1);
}
booksArr.remove(item);
booksArr[booksArr.length] = item;
} else {
var booksArr = [item];
}
localStorage.setItem("historyBooks", JSON.stringify(booksArr));//
function toMyCollect() {
var token = localStorage.getItem("token");
if (token) {
window.location.href = "/book/search?token=" + token;
} else {
window.location.href = "/user/login.html";
}
}
function buyBookIndex(){
$.ajax({
type: "POST",
url: "/user/buyBookIndex",
data: {'bookId':$("#bookIdHidden").val(),"bookName":$("#bookNameHidden").val(),
"bookIndexId":$("#contentIdHidden").val(),"bookIndexName":$("#indexNameHidden").val()},
dataType: "json",
success: function (data) {
if (data.code == 200) {
location.reload();
} else if(data.code == 1001){
//未登录
}else {
layer.alert(data.msg);
}
},
error: function () {
layer.alert('网络异常');
}
})
}
$.post("/book/addVisitCount", {"bookId": $("#bookIdHidden").val()}, function () {
});
</script>
</html>

View File

@ -0,0 +1,354 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title th:utext="${book.bookName}+'小说最新章节免费阅读和下载'"></title>
<meta name="keywords" th:content="${book.bookName}+','+${book.bookName}+'最新章节,'+${book.bookName}+'免费阅读,'+${book.bookName}+'TXT下载'">
<meta name="description"
th:content="${book.bookName}+'最新章节列表,'+${book.bookName}+'最新更新章节免费无广告无弹窗在线阅读,'+${book.bookName}+'小说TXT免费下载。'">
<div th:include="/common/css :: css"></div>
<style type="text/css">
.indexP p a{
color:#4c6978;
}
.tag-list {
padding-top: 0px;
padding-bottom: 20px;
position: fixed;
top:50px;
right: 0px;
width: 120px;
z-index:100000;
}
.tag-list .tag {
float: right;
width: 100%;
text-align: right;
margin-top: 5px;
}
.tag-list .tag a {
display: inline-block;
margin-right: 8px;
font-size: 12px;
}
.tag-list .highlight {
padding: 5px 9px;
border: 1px solid #f90;
color: #f90;
border-radius: 50px;
}
.tag-list .highlight .text {
color: #f90;
}
.tag-list .tag .text {
display: inline-block;
vertical-align: middle;
color: #f90;
}
ul, li {
padding: 0;
margin: 0;
list-style: none;
}
.tag-list .tag a {
display: inline-block;
margin-right: 8px;
font-size: 12px;
}
.tag-list .highlight .icn {
color: #f90;
}
.tag-list .tag .icn {
margin-right: 5px;
color: #ccc;
}
.tag-list .highlight .text {
padding-left: 3px;
color: #f90;
}
.tag-list .tag .text {
display: inline-block;
vertical-align: middle;
color: #f90;
}
.line-limit-length {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
</head>
<body>
<div id="content">
<ul class="tag-list clearfix" id="tagLi">
</ul>
<input type="hidden" id="bookIdHidden" th:value="${bookId}"/>
<input type="hidden" id="bookNamedHidden" th:value="${book.bookName}"/>
<input type="hidden" id="preContentId" th:value="${firstBookIndexId}"/>
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
<div style="float: left;margin-left: 10px">
<a href="javascript:history.go(-1)">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe65c;</i></a>
</div>
<b class="layui-icon" th:utext="${book.bookName}"></b>
<div style="float: right;margin-right: 10px">
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe68e;</i></a>
</div>
</div>
<div class="layui-row" style="background: #f2f2f2">
<div style="padding: 10px" class="layui-col-xs4 layui-col-sm2 layui-col-md2 layui-col-lg2">
<img style=" width:auto; height:auto; max-width:100%; max-height:100%;" th:src="${book.picUrl}"/>
</div>
<div style="position:relative;padding: 10px 20px" class="layui-col-xs8 layui-col-sm8 layui-col-md8 layui-col-lg8">
<a th:href="'javascript:searchBooks(\''+ ${book.authorName}+'\')'"><div style=";color: #4c6978;" th:utext="'作者'+ ${book.authorName}"></div></a>
<a th:href="'/book/book_ranking.html?catId='+${book.catId}"><div style="margin-top: 5px;color: #4c6978;" th:text="'类别'+ ${book.catName}"></div></a>
<div style="margin-top: 5px;color: #4c6978;" th:text="'状态'+ ${book.bookStatus==0?'连载':'完结'}"></div>
<div style="margin-top: 5px;color: #4c6978;">更新:<i th:text="${#dates.format(book.lastIndexUpdateTime, 'yy-MM-dd')}"></i></div>
<div style="margin-top: 5px;color: #4c6978;">评分:<i style="font-weight:bold;color: red" th:text="${book.score} + '分'"></i></div>
<div style="margin-top: 5px;color: #4c6978;">点击:<i style="font-weight:bold;color: red" th:text="${book.visitCount}"></i></div>
</div>
</div>
<div style="text-align: center;height: 45px;line-height: 45px">
<a th:href="'/book/'+${book.id}+'/'+${firstBookIndexId}+'.html'" type="button" class="layui-btn layui-btn-sm layui-btn-radius">开始阅读</a>
<!--
<button type="button" onclick="downloadFile()" class="layui-btn layui-btn-sm layui-btn-radius layui-bg-normal">下载TXT</button>
-->
</div>
<p style="line-height: 23px;padding: 10px;font-size: 14px;color: #4c6978;" th:utext="${book.bookDesc}">
</p>
<div class="layui-collapse">
<div class="layui-colla-item" >
<h2 class="layui-colla-title">
<span>最新章节</span>
<span style="margin-left: 30px">
更新: <i th:text="${#dates.format(book.lastIndexUpdateTime, 'yy-MM-dd HH:mm:ss')}"></i>
</span>
</h2>
<div class="layui-colla-content layui-show indexP layui-row" id="indexList">
</div>
</div>
</div>
<div style="height: 42px;color:#4c6978;line-height: 42px;padding-left: 30px;background: #f2f2f2" >
<a th:href="'/book/indexList-'+${book.id}+'.html'">查看完整目录</a>
</div>
<!--
<div style="position: fixed;top:0px;left:0px;z-index:-100;opacity: 0" th:utext="${attacDivForSearch}"></div>
-->
</div>
<div th:replace="/common/footer :: footer">
</div>
</body>
<div th:replace="/common/js :: js">
</div>
<script>
//查询是否在书架
$.ajax({
type: "GET",
url: "/user/queryIsInShelf",
data: {'bookId': $("#bookIdHidden").val()},
dataType: "json",
success: function (data) {
if (data.code == 200) {
if (data.data) {
$("#cFavs").html("<button type=\"button\" id=\"cFavs\" class=\"layui-btn layui-btn-sm layui-btn-radius layui-btn-warm\">已在书架</button>");
}
} else if (data.code == 1001) {
//未登录
} else {
layer.alert(data.msg);
}
},
error: function () {
layer.alert('网络异常');
}
})
//查询最新目录集合
$.ajax({
type: "GET",
url: "/book/queryNewIndexList",
data: {'bookId': $("#bookIdHidden").val()},
dataType: "json",
success: function (data) {
if (data.code == 200) {
var indexListHtml = "";
for(var i = 0 ; i < data.data.length ; i++){
var bookIndex = data.data[i];
indexListHtml+=("<p class=\"line-limit-length layui-col-xs12 layui-col-sm4 layui-col-md3 layui-col-lg2\" style=\"padding-left:10px;height: 50px;line-height: 50px;\"><a href=\"/book/"+$("#bookIdHidden").val()+"/"+bookIndex.id+".html\">"+bookIndex.indexName+"</a></p>");
}
$("#indexList").html(indexListHtml);
} else if (data.code == 1001) {
//未登录
} else {
layer.alert(data.msg);
}
},
error: function () {
layer.alert('网络异常');
}
})
function addInShell() {
$.ajax({
type: "POST",
url: "/user/addToBookShelf",
data: {'bookId': $("#bookIdHidden").val(), 'preContentId': $("#preContentId").val()},
dataType: "json",
success: function (data) {
if (data.code == 200) {
$("#cFavs").html("<button type=\"button\" id=\"cFavs\" class=\"layui-btn layui-btn-sm layui-btn-radius layui-btn-warm\">已在书架</button>");
} else if (data.code == 1001) {
//未登录
location.href = '/user/login.html?originUrl=' + decodeURIComponent(location.href);
} else {
layer.alert(data.msg);
}
},
error: function () {
layer.alert('网络异常');
}
})
}
$("#content").css("min-height",($(window).height()-60)+"px");
function downloadFile() {
var fileUrl = '/book/download?bookId='+$("#bookIdHidden").val()+'&bookName='+$("#bookNamedHidden").val();
window.location.href=fileUrl;
}
function toMyCollect(){
var token = localStorage.getItem("token");
if(token) {
window.location.href = "/book/search?token=" + token;
}else{
window.location.href = "/user/login.html";
}
}
function addToCollect(){
var token = localStorage.getItem("token");
if(token) {
$.get("/user/addToCollect",{"bookId":$("#bookIdHidden").val(),"token":token},function(data){
layer.alert(data.desc);
if(data.code == 1) {
$('#collectButton').unbind("click");
$("#collectButton").text("撤下书架");
$("#collectButton").click(function () {
cancelToCollect();
});
}
});
}else{
window.location.href = "/user/login.html?bookId="+$("#bookIdHidden").val();
}
}
function cancelToCollect(){
var token = localStorage.getItem("token");
if(token) {
$.get("/user/cancelToCollect",{"bookId":$("#bookIdHidden").val(),"token":token},function(data){
layer.alert(data.desc);
if(data.code == 1) {
$('#collectButton').unbind("click");
$("#collectButton").text("加入书架");
$("#collectButton").click(function () {
addToCollect();
});
}
});
}else{
window.location.href = "/user/login.html?bookId="+$("#bookIdHidden").val();
}
}
function searchBooks(keyword) {
window.location.href = "/book/book_ranking.html?keyword=" + encodeURI(keyword);
}
$.post("/book/addVisitCount", {"bookId": $("#bookIdHidden").val()}, function () {
});
</script>
</html>

View File

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title th:utext="${book.bookName}+'最新免费章节目录列表'"></title>
<meta name="keywords" th:content="${book.bookName}+','+${book.bookName}+'最新章节'">
<meta name="description"
th:content="${book.bookName}+'最新章节列表,'+${book.bookName}+'最新更新章节免费无广告无弹窗在线阅读TXT下载。'">
</div>
<div th:include="/common/css :: css"></div>
<style type="text/css">
.indexP p a {
color: #4c6978;
}
.line-limit-length {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
</div>
</head>
<body>
<div id="content">
<input type="hidden" id="bookIdHidden" th:value="${book.id}"/>
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
<div style="float: left;margin-left: 10px">
<a href="javascript:history.go(-1)">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe65c;</i></a>
</div>
<a style="color: #ffffff;" th:href="'/book/'+ ${book.id} + '.html'"><b class="layui-icon" th:utext="${book.bookName}"></b></a>
<div style="float: right;margin-right: 10px">
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe68e;</i></a>
</div>
</div>
<p style="height: 30px;line-height: 30px;padding: 10px">
<a href="#buttom" style="color: red">&nbsp;&nbsp;↓直达页面底部</a>
</p>
<div class="layui-colla-content layui-show indexP layui-row">
<p class="line-limit-length layui-col-xs12 layui-col-sm4 layui-col-md3 layui-col-lg2" style="padding-left:10px;height: 50px;line-height: 50px;" th:each="index : ${bookIndexList}">
<a th:href="'/book/'+${index.bookId}+'/'+${index.id}+'.html'" th:utext="${index.indexName}">
</a>
</p>
</div>
</div>
<div th:replace="/common/footer :: footer">
</div>
<a name="buttom"></a>
</body>
<div th:replace="/common/js :: js">
</div>
<script>
$("#content").css("min-height",($(window).height()-60)+"px");
$.get("/book/addVisit",{"bookId":$("#bookIdHidden").val()},function(){});
function toMyCollect(){
var token = localStorage.getItem("token");
if(token) {
window.location.href = "/book/search?token=" + token;
}else{
window.location.href = "/user/login.html";
}
}
</script>
</html>

View File

@ -0,0 +1,320 @@
<!DOCTYPE html>
<html lang="en">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title th:text="#{website.name}+'列表'"></title>
<meta name="keywords"
th:content="#{website.name}+',精品小说,弹幕网站,弹幕,弹幕小说网站,免费小说,小说阅读,小说排行,轻小说,txt小说下载,电子书下载,动漫轻小说,日本轻小说'">
<meta name="description"
th:content="#{website.name}+'是国内优秀的小说弹幕网站,'+#{website.name}+'提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。'">
<div th:include="/common/css :: css"></div>
</div>
<style type="text/css">
.line-limit-length {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.indexP p a {
color: #4c6978;
}
.Readarea {
font-size: 18px;
line-height: 35px;
padding: 10px;
color: #333;
}
div, p {
wrap-work: break-word;
word-break: break-all;
word-wrap: break-word;
word-break: normal;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-ms-box-sizing: border-box;
}
.indexDiv a {
margin-left: 20px;
}
img {
width: 130px;
height: 180px;
}
</style>
</head>
<body>
<input type="hidden" id="limit" th:value="${limit}"/>
<input type="hidden" id="curr" th:value="${curr}"/>
<input type="hidden" id="total" th:value="${total}"/>
<input type="hidden" id="ids" th:value="${ids}"/>
<input type="hidden" id="bookStatus" th:value="${bookStatus}"/>
<input type="hidden" id="token" th:value="${token}"/>
<input type="hidden" id="keyword" th:value="${keyword}"/>
<input type="hidden" id="catId" th:value="${catId}"/>
<input type="hidden" id="sortBy" th:value="${sortBy}"/>
<input type="hidden" id="sort" th:value="${sort}"/>
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
<div style="float: left;margin-left: 10px">
<a href="javascript:history.go(-1)">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe65c;</i></a>
</div>
<b class="layui-icon">小说列表</b>
<div style="float: right;margin-right: 10px">
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe68e;</i></a>
</div>
</div>
<div class="layui-container">
<div class="layui-row">
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
autocomplete="off"
class="layui-input" th:value="${keyword}">
</div>
<div class="layui-col-xs1" style="padding: 1%">
<button onclick="search(1,20)" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
</div>
</div>
</div>
<div id="bookList">
</div>
<div id="books" style="text-align: center"></div>
<div th:replace="/common/footer :: footer">
</div>
<a name="buttom"></a>
</body>
<div th:replace="/common/js :: js"></div>
<script>
var catId = getQueryVariable("catId");
var bookStatus = getQueryVariable("bookStatus");
var sortBy = getQueryVariable("sortBy");
var keyword = getQueryVariable("keyword");
if(keyword != false){
$("#title").val(decodeURI(keyword));
}else{
keyword = "";
}
search(1,20);
function search(curr,limit) {
var searchData = {};
searchData.curr = curr;
searchData.limit = limit;
keyword = $("#title").val();
if(catId != false){
searchData.catId = catId;
}
if(bookStatus != false){
searchData.bookStatus = bookStatus;
}
if(sortBy != false){
searchData.sort = sortBy;
}else if(!keyword){
sortBy = "last_index_update_time";
}
if(keyword){
searchData.keyword = keyword;
}
$.ajax({
type: "GET",
url: "/book/searchByPage",
data: searchData,
dataType: "json",
success: function (data) {
if (data.code == 200) {
var bookList = data.data.list;
var bookListHtml = "";
for (var i = 0; i < bookList.length; i++) {
var book = bookList[i];
/*var end = book.bookDesc.indexOf("<");
if(end != -1) {
book.bookDesc = book.bookDesc.substring(0,end);
}*/
if(book.bookDesc){
book.bookDesc = book.bookDesc.replace(/<[^>]+>/g,"").replace(/\s+/g,"").replace(/&nbsp;/g,"");
}
bookListHtml += ("<div class=\"layui-row\" style=\"margin-bottom:10px;padding:10px;background: #f2f2f2\">\n" +
" <a href=\"/book/"+book.id+".html\">\n" +
" <div class=\"layui-col-xs6 layui-col-sm3 layui-col-md2 layui-col-lg2\" style=\"text-align: center\">\n" +
" <img width='150' height='180' align=\"center\"\n" +
" src=\""+book.picUrl+"\"/>\n" +
"\n" +
" </div>\n" +
" </a>\n" +
" <div style=\"padding: 10px\" class=\"layui-col-xs6 layui-col-sm8 layui-col-md8 layui-col-lg8\">\n" +
" <a href=\"/book/"+book.id+".html\">\n" +
" <div class=\"line-limit-length\" style=\";color: #4c6978;font-weight: bold;font-size: 15px\">"+book.bookName+"</div>\n" +
" </a>\n" +
" <div style=\";color: #4c6978;float: right;\"><i style=\"color: red\"></i></div>\n" +
" <a href=\"/book/book_ranking.html?keyword="+encodeURI(book.authorName)+"\">\n" +
" <div style=\";color: #4c6978;\" class=\"line-limit-length\">作者:"+book.authorName+"</div>\n" +
" </a>\n" +
" <div style=\"margin-top: 5px;color: #4c6978;\">类别:"+book.catName+"</div>\n" +
" <div style=\"margin-top: 5px;color: #4c6978;\">状态:"+(book.bookStatus==0?'连载':'完结')+"</div>\n" +
" <div style=\"margin-top: 5px;color: #4c6978;\">更新:<i>"+book.lastIndexUpdateTime.substr(0,11)+"</i>\n" +
" </div>\n" +
" <div style=\"margin-top: 5px;color: #4c6978;\">简介:"+(book.bookDesc?(book.bookDesc.length>20?(book.bookDesc.substr(0,20)+"..."):book.bookDesc):book.bookDesc)+"</div>\n" +
"\n" +
"\n" +
" </div>\n" +
"\n" +
" </div>");
}
$("#bookList").html(bookListHtml);
layui.use('laypage', function () {
var laypage = layui.laypage;
//执行一个laypage实例
laypage.render({
elem: 'books' //注意,这里的 test1 是 ID不用加 # 号
, count: data.data.total //数据总数,从服务端得到,
, curr: data.data.pageNum
, limit: data.data.pageSize
, jump: function (obj, first) {
//obj包含了当前分页的所有参数比如
console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。
console.log(obj.limit); //得到每页显示的条数
//首次不执行
if (!first) {
search(obj.curr, obj.limit);
} else {
}
}
});
});
} else {
layer.alert(data.msg);
}
},
error: function () {
layer.alert('网络异常');
}
})
}
function searchByAllCondition(curr, limit, newKeyword) {
var toUrl = "/book/search?curr=" + curr + "&limit=" + limit;
var ids = $("#ids").val();
if (ids) {
toUrl += ("&historyBookIds=" + ids);
}
var token = $("#token").val();
if (token) {
toUrl += ("&token=" + token);
}
var keyword = $("#keyword").val();
if (newKeyword) {
toUrl += encodeURI("&keyword=" + newKeyword);
} else if (keyword) {
toUrl += encodeURI("&keyword=" + keyword);
}
var bookStatus = $("#bookStatus").val();
if (bookStatus) {
toUrl += ("&bookStatus=" + bookStatus);
}
var catId = $("#catId").val();
if (catId) {
toUrl += ("&catId=" + catId);
}
var sortBy = $("#sortBy").val();
if (sortBy) {
toUrl += ("&sortBy=" + sortBy);
}
var sort = $("#sort").val();
if (sort) {
toUrl += ("&sort=" + sort);
}
window.location.href = toUrl;
}
function searchBooks() {
var keywords = $("#title").val();
$("#keyword").val("");
searchByAllCondition(1, 20, keywords);
}
</script>
<script>
function toMyCollect() {
var token = localStorage.getItem("token");
if (token) {
window.location.href = "/book/search?token=" + token;
} else {
window.location.href = "/user/login.html";
}
}
</script>
</html>

View File

@ -0,0 +1,88 @@
<!DOCTYPE html>
<html lang="en">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>小说提交</title>
<div th:include="common/css :: css"></div>
</head>
<body id="read" >
</div>
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
<div style="float: left;margin-left: 10px">
<a href="javascript:history.go(-1)">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe65c;</i></a>
</div>
<b class="layui-icon">单本小说提交</b>
<div style="float: right;margin-right: 10px"><a href="/">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe68e;</i>
</a>
</div>
</div>
<div style="height: 800px;padding: 20px;border: 1px solid #eee;">
<form class="layui-form" action="">
<div class="layui-form-item">
<label class="layui-form-label">详情页Url:</label>
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1" >
<input type="text" id="bookUrl" name="bookUrl" required lay-verify="required" placeholder="请输入源站小说详情页Url" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">小说名:</label>
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1" >
<input type="text" id="bookName" name="bookName" required lay-verify="required" placeholder="请输入小说名" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">小说评分:</label>
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1">
<input type="number" id="score" name="score" required lay-verify="required" placeholder="请输入小说评分" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="formDemo">提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</div>
<div th:replace="common/footer :: footer">
</div>
<a name="buttom"></a>
</body>
<div th:replace="common/js :: js"></div>
<script>
//Demo
layui.use('form', function(){
var form = layui.form;
//监听提交
form.on('submit(formDemo)', function(){
$.post("/book/submit",{"bookUrl":$("#bookUrl").val(),"bookName":$("#bookName").val(),"score":$("#score").val()},function (data) {
if(data.code == 1 ){
layer.alert("提交成功任务排队中请过一段时间后再搜索查看");
}else{
layer.alert("提交失败");
}
});
return false;
});
});
</script>
</html>

View File

@ -0,0 +1,24 @@
<div th:fragment="css">
<link rel="stylesheet" href="/layui/css/layui.css">
<style type="text/css">
.app {
display: none;
}
@media (max-width: 360px) {
.app {
display: block !important;
}
}
.pc {
display: block;
}
@media (max-width: 360px) {
.pc {
display: none;
}
}
</style>
</div>

View File

@ -0,0 +1,11 @@
<div th:fragment="footer" style="height: 60px;line-height: 60px;text-align: center" class="layui-footer footer footer-demo layui-bg-cyan">
<!--<a href="/mobile/book/searchSoftBook.html" style="font-size: 14px;color: #92B8B1;">轻小说</a>
<a href="/mobile/book/searchSoftBook.html?catId=9" style="font-size: 14px;color: #92B8B1;margin-left: 8px">漫画</a>-->
<a href="/?to=mobile" style="font-size: 14px;color: #92B8B1;margin-left: 8px">手机站</a>
<!--<a href="https://www.zinglizingli.xyz/me/index.html" style="font-size: 14px;color: #92B8B1;margin-left: 8px">开发者</a>-->
<div style="float: right"><a href="#top"><i class="layui-icon"
style="margin-right:15px;font-size: 30px;color:#92B8B1 ">&#xe604;</i></a>
</div>
</div>

View File

@ -0,0 +1,3 @@
<script th:fragment="js" src="/js/jquery-1.9.1.js"></script>
<script th:fragment="js" src="/js/common.js"></script>
<script th:fragment="js" src="/layui/layui.all.js"></script>

View File

@ -0,0 +1,388 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title th:text="#{website.name}"></title>
<meta name="keywords" th:content="#{website.name}+',精品小说,弹幕网站,弹幕,弹幕小说网站,免费小说,小说阅读,小说排行,轻小说,txt小说下载,电子书下载,动漫轻小说,日本轻小说'">
<meta name="description"
th:content="#{website.name}+'是国内优秀的小说弹幕网站,'+#{website.name}+'提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。'">
<meta property="og:type" content="novel_index"/>
<meta property="og:title" th:content="#{website.name}"/>
<meta property="og:description"
th:content="#{website.name}+'是国内优秀的小说弹幕网站,'+#{website.name}+'提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。'"/>
<div th:include="/common/css :: css"></div>
<style>
.line-limit-length {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.layui-nav .layui-nav-item {
position: relative;
display: inline-block;
vertical-align: middle;
line-height: 50px;
}
body ul.layui-nav li.layui-nav-item a {
display: block;
transition: all .3s;
-webkit-transition: all .3s;
}
</style>
</head>
<body>
<!-- 你的HTML代码 -->
<a name="top"></a>
<ul class="layui-nav app" lay-filter="" style="display:none;padding:0 10px;text-align: center">
<li class="layui-nav-item"><a>分类</a>
<dl class="layui-nav-child">
<dd><a href="/book/book_ranking.html?catId=1&sort=last_index_update_time">玄幻小说</a></dd>
<dd><a href="/book/book_ranking.html?catId=2&sort=last_index_update_time">修真小说</a></dd>
<dd><a href="/book/book_ranking.html?catId=3&sort=last_index_update_time">都市小说</a></dd>
<dd><a href="/book/book_ranking.html?catId=4&sort=last_index_update_time">历史小说</a></dd>
<dd><a href="/book/book_ranking.html?catId=6&sort=last_index_update_time">网游小说</a></dd>
<dd><a href="/book/book_ranking.html?catId=5&sort=last_index_update_time">科幻小说</a></dd>
<dd><a href="/book/book_ranking.html?catId=7&sort=last_index_update_time">女频小说</a></dd>
</dl>
</li>
<li class="layui-nav-item"><a>全本</a>
<dl class="layui-nav-child">
<dd><a href="/book/book_ranking.html?bookStatus=1">全部小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=1">玄幻小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=2">修真小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=3">都市小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=4">历史小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=6">网游小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=5">科幻小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=7">女频小说</a></dd>
</dl>
</li>
<li class="layui-nav-item"><a>排行</a>
<dl class="layui-nav-child">
<dd><a href="/book/book_ranking.html?sortBy=visit_count">全部小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=1">玄幻小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=2">修真小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=3">都市小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=4">历史小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=6">网游小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=5">科幻小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=7">女频小说</a></dd>
</dl>
</li>
</ul>
<ul class="layui-nav pc" lay-filter="" style="padding:0 36px;text-align: center">
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=1&sort=last_index_update_time">玄幻小说</a></li>
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=2&sort=last_index_update_time">修真小说</a></li>
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=3&sort=last_index_update_time">都市小说</a></li>
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=4&sort=last_index_update_time">历史小说</a></li>
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=6&sort=last_index_update_time">网游小说</a></li>
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=5&sort=last_index_update_time">科幻小说</a></li>
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=7&sort=last_index_update_time">女频小说</a></li>
<li class="layui-nav-item"><a>完本小说</a>
<dl class="layui-nav-child"> <!-- 二级菜单 -->
<dd><a href="/book/book_ranking.html?bookStatus=1">全部小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=1">玄幻小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=2">修真小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=3">都市小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=4">历史小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=6">网游小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=5">科幻小说</a></dd>
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=7">女频小说</a></dd>
</dl>
</li>
<li class="layui-nav-item"><a>小说排行</a>
<dl class="layui-nav-child"> <!-- 二级菜单 -->
<dd><a href="/book/book_ranking.html?sortBy=visit_count">全部小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=1">玄幻小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=2">修真小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=3">都市小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=4">历史小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=6">网游小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=5">科幻小说</a></dd>
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=7">女频小说</a></dd>
</dl>
</li>
</ul>
<div class="layui-container">
<div class="layui-row">
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
autocomplete="off"
class="layui-input">
</div>
<div class="layui-col-xs1" style="padding: 1%">
<button onclick="searchBooks()" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
</div>
</div>
</div>
<div style="height: 1px" class="layui-col-lg1"></div>
<div class="layui-collapse layui-col-lg10">
<div class="layui-colla-item">
<h2 class="layui-colla-title">本站推荐</h2>
<div class="layui-colla-content layui-show">
<div class="layui-container" style="padding: 0px">
<div class="layui-row" style="text-align: center" id="currentWeek">
</div>
</div>
</div>
</div>
<div class="layui-colla-item">
<h2 class="layui-colla-title">热门小说推荐</h2>
<div class="layui-colla-content layui-show">
<div class="layui-container">
<div class="layui-row" id="hotRecBooks">
<!--<div th:each="hotBook : ${hotBooks}" style="margin-top: 1%"
class="layui-col-xs12 layui-col-sm6 layui-col-md6 layui-col-lg6">
<a th:href="'/book/'+${hotBook.id}+'.html'">
<div class="layui-col-xs5 layui-col-sm3 layui-col-md3 layui-col-lg3">
<img style=" width:100px; height:125px;"
th:src="${hotBook.picUrl}"/>
</div>
<div class="layui-col-xs7 layui-col-sm6 layui-col-md7 layui-col-lg7"
style="float: left;padding-right: 10px">
<div><b th:text="${hotBook.bookName}"></b></div>
<div class="layui-col-xs8 layui-col-sm9 layui-col-md10 layui-col-lg10"
th:text="'作者'+ ${hotBook.author}"></div>
<div class="layui-col-xs3 layui-col-sm2 layui-col-md1 layui-col-lg1" style="text-align: right;">
<b><i style="color: red"
th:text="${hotBook.score} + '分'"></i></b></div>
</div>
<div class="layui-elip layui-col-xs12 layui-col-sm9 layui-col-md10 layui-col-lg10 layui-col-sm9 layui-col-md10 layui-col-lg10"
th:text="${hotBook.bookDesc}">
</div>
</a>
</div>-->
</div>
</div>
</div>
</div>
</div>
</div>
<div style="clear: both"></div>
<div style="height: 1px" class="layui-col-lg1"></div>
<div class="layui-colla-item layui-col-lg10"
style="border-width: 1px;border-style: solid;border-radius: 2px;border-top-width: 0px"><a
href="javascript:moreNewBooks()">
<h2 class="layui-colla-title">最近更新小说
<div style="float: right; margin-right: 20px"><i style="font-size: 14px;"
class="layui-icon">更多&#xe65b;</i>
</div>
</h2>
</a>
<div class="layui-colla-content layui-show">
<div class="layui-container" style="padding-left: 2px;padding-right: 5px">
<div class="layui-row" id="updateRankBooks">
</div>
</div>
</div>
</div>
</div>
<div style="clear: both"></div>
<div th:replace="/common/footer :: footer">
</div>
<div th:replace="/common/js :: js">
</div>
<script src="/js/wap_collect.js"></script>
<script>
//加载首页书籍设置数据
$.ajax({
type: "GET",
url: "/book/listBookSetting",
data: {},
dataType: "json",
success: function (data) {
if (data.code == 200) {
//本周强推
var rightListBooks = data.data[2];
var rightListBooksHtml = "";
for (var i = 0; i < 3; i++) {
var rightListBook = rightListBooks[i];
var classHtml = "";
if (i == 0) {
classHtml = "on";
}
if (i < 3) {
classHtml += (" num" + (i + 1));
}
rightListBooksHtml += (" <span>\n" +
" <a href=\"/book/"+rightListBook.bookId+".html\">\n" +
" <div style=\"padding: 1%\" class=\"layui-col-xs4 layui-col-sm4 layui-col-md4 layui-col-lg4\">\n" +
" <img style=\" width:80%; height:auto; max-width:100%; max-height:100%;\"\n" +
" src=\""+rightListBook.picUrl+"\"/>\n" +
"\n" +
" <br/>\n" +
" <span>"+rightListBook.bookName+"</span>\n" +
"\n" +
" </div>\n" +
" </a>\n" +
" </span>");
}
$("#currentWeek").html(rightListBooksHtml);
//热门推荐
var hotRecBooks = data.data[3];
var hotRecBooksHtml = "";
for (var i = 0; i < 6; i++) {
var hotRecBook = hotRecBooks[i];
if(hotRecBook.bookDesc){
hotRecBook.bookDesc = hotRecBook.bookDesc.replace(/<[^>]+>/g,"").replace(/\s+/g,"");
}
hotRecBooksHtml += ("<div style=\"margin-bottom: 5px\" class=\"layui-col-xs12 layui-col-sm6 layui-col-md4 layui-col-lg4\">\n" +
" <a href=\"/book/"+hotRecBook.bookId+".html\">\n" +
" <div class=\"layui-col-xs5 layui-col-sm4 layui-col-md4 layui-col-lg4\" >\n" +
" <img style=\" width:100px; height:125px;\"\n" +
" src=\""+hotRecBook.picUrl+"\"/>\n" +
"\n" +
" </div>\n" +
" <div class=\"layui-col-xs5 layui-col-sm6 layui-col-md6 layui-col-lg6\">\n" +
" <ul>\n" +
" <li class=\"line-limit-length\" style=\"font-weight: bold\">"+hotRecBook.bookName+"</li>\n" +
" <li>作者:"+hotRecBook.authorName+"</li>\n" +
" <li style=\"width: 180px;height:40px;overflow: hidden\">简介:  "+hotRecBook.bookDesc+"" +
" </ul>\n" +
" </div>\n" +
" <div style=\"font-style: italic;color: red\"\n" +
" class=\"layui-col-xs2 layui-col-sm2 layui-col-md2 layui-col-lg2\"></div>\n" +
" </a>\n" +
" </div>");
}
$("#hotRecBooks").html(hotRecBooksHtml);
} else {
layer.alert(data.msg);
}
},
error: function () {
layer.alert('网络异常');
}
})
//更新榜单查询
$.ajax({
type: "GET",
url: "/book/listUpdateRank",
data: {},
dataType: "json",
success: function (data) {
if (data.code == 200) {
var updateRankBooks = data.data;
var updateRankBookHtml = "";
for (var i = 0; i < 10; i++) {
var updateRankBook = updateRankBooks[i];
if(updateRankBook.bookDesc){
updateRankBook.bookDesc = updateRankBook.bookDesc.replace(/<[^>]+>/g,"").replace(/\s+/g,"");
}
updateRankBookHtml += ("<div style=\"padding-bottom: 30px\"\n" +
" class=\"layui-col-xs12 layui-col-sm6 layui-col-md6 layui-col-lg6\">\n" +
"\n" +
" <a href=\"/book/"+updateRankBook.id+".html\">\n" +
" <div class=\"line-limit-length layui-col-xs8 layui-col-sm6 layui-col-md6 layui-col-lg6\"><b>"+(i+1)+"."+updateRankBook.bookName+"</b> - <span class=\"layui-elip\">"+updateRankBook.authorName+"</span>\n" +
" </div>\n" +
" <div class=\"layui-col-sm3 layui-col-md3 layui-col-lg3\"\n" +
" style=\"color: #FF5722;float: right;margin-right:5px\"><i>"+updateRankBook.lastIndexUpdateTime+"</i></div>\n" +
"\n" +
" <div style=\"clear: both\"></div>\n" +
" <div style=\"padding-left: 5px;padding-top: 5px\"\n" +
" class=\"layui-elip layui-col-md11 layui-col-sm11 layui-col-lg11\">简介:  "+updateRankBook.bookDesc+"" +
" </div></a>\n" +
" </div>");
}
$("#updateRankBooks").html(updateRankBookHtml);
} else {
layer.alert(data.msg);
}
}
,
error: function () {
layer.alert('网络异常');
}
})
function moreNewBooks(event) {
window.location.href = "/book/book_ranking.html?sortBy=last_index_update_time";
}
function searchBooks() {
var keywords = $("#title").val();
window.location.href = "/book/book_ranking.html?keyword=" + encodeURI(keywords);
}
function toMyCollect() {
var token = localStorage.getItem("token");
if (token) {
window.location.href = "/book/book_ranking.html?token=" + token;
} else {
window.location.href = "/user/login.html";
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,364 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta th:if="${catId == 9}" name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=1">
<meta th:if="${catId != 9}" name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title th:utext="${book.bookName}+${bookIndex.indexName}"></title>
<meta name="keywords" th:content="${book.bookName}+','+${bookIndex.indexName}">
<meta name="description"
th:content="${book.bookName}+'最新更新章节免费在线阅读TXT下载'">
<div th:include="mobile/common/css :: css"></div>
<script type="text/javascript">
function reinitIframe(){
var iframe = document.getElementById("frame_content");
try{
iframe.height =  iframe.contentWindow.document.documentElement.scrollHeight;
}catch (ex){}
}
window.setInterval("reinitIframe()", 200);
</script>
<script th:fragment="js" src="/mobile/js/jquery-1.9.1.js"></script>
<script th:fragment="js" src="/mobile/layui/layui.all.js"></script>
</div>
<style type="text/css">
.line-limit-length {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.indexP p a {
color: #4c6978;
}
.Readarea {
font-size: 18px;
line-height: 35px;
padding: 10px;
color: #333;
}
div, p {
wrap-work: break-word;
word-break: break-all;
word-wrap: break-word;
word-break: normal;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-ms-box-sizing: border-box;
}
.indexDiv a {
margin-left: 20px;
}
.Readpage {
font-size: 14px;
padding: 0;
background: #d4eaf2;
height: 40px;
line-height: 40px;
text-align: center;
}
div, p {
wrap-work: break-word;
word-break: break-all;
word-wrap: break-word;
word-break: normal;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-ms-box-sizing: border-box;
}
* {
margin: 0;
padding: 0;
/* background-attachment: fixed; */
}
user agent stylesheet
p {
display: block;
-webkit-margin-before: 1em;
-webkit-margin-after: 1em;
-webkit-margin-start: 0px;
-webkit-margin-end: 0px;
}
.huyanon {
border: 1px solid #64c878;
box-shadow: 0 1px 2px #b9ecc4 inset, 0 -1px 0 #6c9f76 inset, 0 -2px 3px #b9ecc4 inset;
background: -webkit-linear-gradient(top, #90dfa2, #84d494);
background: -moz-linear-gradient(top, #90dfa2, #84d494);
background: linear-gradient(top, #90dfa2, #84d494);
}
.Readpage a {
font-size: 16px;
padding: 2px 2px;
line-height: 35px;
}
.lightoff, .huyanoff, .sizebgon {
border: 1px solid #333;
box-shadow: 0 1px 2px #8b8b8b inset, 0 -1px 0 #3d3d3d inset, 0 -2px 3px #8b8b8b inset;
background: -webkit-linear-gradient(top, #656565, #4c4c4c);
background: -moz-linear-gradient(top, #656565, #4a4a4a);
background: linear-gradient(top, #656565, #4a4a4a);
}
.button {
width: 40px;
line-height: 38px;
text-align: center;
font-weight: bold;
color: #fff;
text-shadow: 1px 1px 1px #333;
border-radius: 5px;
margin: 3px 0px 0px 0;
position: relative;
overflow: hidden;
}
a {
color: #4c6978;
text-decoration: none;
border: none;
cursor: pointer;
}
.lighton {
border: 1px solid #d2a000;
box-shadow: 0 1px 2px #fedd71 inset, 0 -1px 0 #a38b39 inset, 0 -2px 3px #fedd71 inset;
background: -webkit-linear-gradient(top, #fece34, #d8a605);
background: -moz-linear-gradient(top, #fece34, #d8a605);
background: linear-gradient(top, #fece34, #d8a605);
}
.screen_toolbar {
position: fixed;
width: 100%;
left: 0px;
bottom: 100px;
text-align: center;
}
</style>
</head>
<body id="read">
<div id="content">
<input type="hidden" id="bookIdHidden" th:value="${book.id}"/>
<input type="hidden" id="bookNameHidden" th:value="${book.bookName}"/>
<input type="hidden" id="contentIdHidden" th:value="${bookIndex.id}"/>
<input type="hidden" id="indexNameHidden" th:value="${bookIndex.indexName}"/>
<input type="hidden" id="indexNumHidden" th:value="${bookIndex.indexNum}"/>
<script>
var token = localStorage.getItem("token");
</script>
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
<div style="width:10%;float: left;margin-left: 10px">
<a href="javascript:history.go(-1)">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe65c;</i></a>
</div>
<a style="color: #ffffff;" th:href="'/book/'+ ${book.id} + '.html'"><b style="padding-left: 5%;float: left;width: 69%" class="line-limit-length" th:utext="${bookIndex.indexName}+' '+${book.bookName}"></b></a>
<div style="width:10%;float: right;margin-right: 10px"><a href="/">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe68e;</i>
</a>
</div>
</div>
<p class="Readpage" style="background:#FFFFFF;padding:2px;">
<a id="lightdiv" class="button lighton" onclick="nr_setbg('light')">开灯</a>
<a id="huyandiv" class="button huyanon" onclick="nr_setbg('huyan')">护眼</a>&nbsp;&nbsp;&nbsp;&nbsp;
字体:<a id="fontbig" class="sizebg" onclick="nr_setbg('big')">大</a> <a id="fontmiddle" class="button sizebgon"
onclick="nr_setbg('middle')">中</a> <a
id="fontsmall" class="sizebg" onclick="nr_setbg('small')">小</a>
</p>
<div class="indexDiv" style="height: 42px;line-height: 42px;text-align:center;background: #f2f2f2">
<a th:href="${preBookIndexId!=0?'/book/'+book.id+'/'+preBookIndexId+'.html':'#'}">上一章</a>
<a th:href="'/book/indexList-'+${book.id}+'.html'">目录</a>
<a th:href="${nextBookIndexId!=0?'/book/'+book.id+'/'+nextBookIndexId+'.html':'#'}">下一章</a>
</div>
<!--<div id="screenInput" class="screen_toolbar" style="display: none">
<div style="height: 5px" class="layui-col-xs2 layui-col-sm3 layui-col-md3 layui-col-lg3"></div>
<div class="layui-col-xs6 layui-col-sm4 layui-col-md4 layui-col-lg4">
<input type="text" id="screenBulletText" required lay-verify="required" placeholder="请输入弹幕内容,右下角开关可控制弹幕是否开启" autocomplete="off"
class="layui-input">
</div>
<div class="layui-col-xs2 layui-col-sm1 layui-col-md1 layui-col-lg1">
<button class="layui-btn send">发送</button>
</div>
</div>
<form id="screenSwitch" class="layui-form">
<div class="layui-form-item" style="position: fixed;right: 0px;bottom: 100px" title="弹幕开关">
&lt;!&ndash; <label class="layui-form-label" style="opacity:0.5;font-weight: bold;color: red;">弹幕</label>&ndash;&gt;
<div class="layui-input-block">
<input class="clear" type="checkbox" name="switch" lay-skin="switch">
</div>
</div>
</form>-->
<div th:replace="mobile/common/js :: js">
</div>
<div id="chaptercontent" class="Readarea ReadAjax_content screen_container"
style="color: rgb(0, 0, 0); font-size: 25px;" th:if="${!needBuy}">
<p style="width:100%;text-alight:center; overflow: auto;-webkit-overflow-scrolling:touch;" >&nbsp;&nbsp;&nbsp;&nbsp;
<span
th:utext="${bookContent.content}"></span></p>
</div>
<div class="Readarea ReadAjax_content screen_container"
style="color: rgb(0, 0, 0); font-size: 10px;background-color: #fff" th:if="${needBuy}">
<h5>此章为VIP章节需要订阅后才能继续阅读</h5>
价格:<span style="color: red" th:text="${bookIndex.bookPrice}+'屋币(1元=100屋币)'"></span><br/>
<a href="javascript:buyBookIndex()" type="button" class="layui-btn layui-btn-sm layui-btn-radius">购买</a>
</div>
<div class="indexDiv" style="height: 42px;line-height: 42px;text-align:center;background: #f2f2f2">
<a th:href="${preBookIndexId!=0?'/book/'+book.id+'/'+preBookIndexId+'.html':'#'}">上一章</a>
<a th:href="'/book/indexList-'+${book.id}+'.html'">目录</a>
<a th:href="${nextBookIndexId!=0?'/book/'+book.id+'/'+nextBookIndexId+'.html':'#'}">下一章</a>
</div>
</div>
<div th:replace="mobile/common/footer :: footer">
</div>
<a name="buttom"></a>
</body>
<script>
var ua = navigator.userAgent;
var ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
isIphone =!ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
isAndroid = ua.match(/(Android)\s+([\d.]+)/),
isMobile = isIphone || isAndroid;
</script>
<script>
(function () {
//添加阅读记录
$.ajax({
type: "POST",
url: "/user/addReadHistory",
data: {'bookId': $("#bookIdHidden").val(), 'preContentId': $("#contentIdHidden").val()},
dataType: "json",
success: function (data) {
},
error: function () {
}
})
$("#content").css("min-height",($(window).height()-60)+"px");
})();
</script>
<script src="/mobile/js/read.js"></script>
<script language="javascript">getset()</script>
<script language="javascript">getset1()</script>
<script language="javascript">
var books = localStorage.getItem("historyBooks");
var item = parseInt($("#bookIdHidden").val());
if (books) {
var booksArr = JSON.parse(books);
if (booksArr.length >= 50) {
booksArr.splice(0, 1);
}
booksArr.remove(item);
booksArr[booksArr.length] = item;
} else {
var booksArr = [item];
}
localStorage.setItem("historyBooks", JSON.stringify(booksArr));//
function toMyCollect() {
var token = localStorage.getItem("token");
if (token) {
window.location.href = "/book/search?token=" + token;
} else {
window.location.href = "/user/login.html";
}
}
function buyBookIndex(){
$.ajax({
type: "POST",
url: "/user/buyBookIndex",
data: {'bookId':$("#bookIdHidden").val(),"bookName":$("#bookNameHidden").val(),
"bookIndexId":$("#contentIdHidden").val(),"bookIndexName":$("#indexNameHidden").val()},
dataType: "json",
success: function (data) {
if (data.code == 200) {
location.reload();
} else if(data.code == 1001){
//未登录
}else {
layer.alert(data.msg);
}
},
error: function () {
layer.alert('网络异常');
}
})
}
$.post("/book/addVisitCount", {"bookId": $("#bookIdHidden").val()}, function () {
});
</script>
</html>

View File

@ -0,0 +1,354 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title th:utext="${book.bookName}+'小说最新章节免费阅读和下载'"></title>
<meta name="keywords" th:content="${book.bookName}+','+${book.bookName}+'最新章节,'+${book.bookName}+'免费阅读,'+${book.bookName}+'TXT下载'">
<meta name="description"
th:content="${book.bookName}+'最新章节列表,'+${book.bookName}+'最新更新章节免费无广告无弹窗在线阅读,'+${book.bookName}+'小说TXT免费下载。'">
<div th:include="mobile/common/css :: css"></div>
<style type="text/css">
.indexP p a{
color:#4c6978;
}
.tag-list {
padding-top: 0px;
padding-bottom: 20px;
position: fixed;
top:50px;
right: 0px;
width: 120px;
z-index:100000;
}
.tag-list .tag {
float: right;
width: 100%;
text-align: right;
margin-top: 5px;
}
.tag-list .tag a {
display: inline-block;
margin-right: 8px;
font-size: 12px;
}
.tag-list .highlight {
padding: 5px 9px;
border: 1px solid #f90;
color: #f90;
border-radius: 50px;
}
.tag-list .highlight .text {
color: #f90;
}
.tag-list .tag .text {
display: inline-block;
vertical-align: middle;
color: #f90;
}
ul, li {
padding: 0;
margin: 0;
list-style: none;
}
.tag-list .tag a {
display: inline-block;
margin-right: 8px;
font-size: 12px;
}
.tag-list .highlight .icn {
color: #f90;
}
.tag-list .tag .icn {
margin-right: 5px;
color: #ccc;
}
.tag-list .highlight .text {
padding-left: 3px;
color: #f90;
}
.tag-list .tag .text {
display: inline-block;
vertical-align: middle;
color: #f90;
}
.line-limit-length {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
</head>
<body>
<div id="content">
<ul class="tag-list clearfix" id="tagLi">
</ul>
<input type="hidden" id="bookIdHidden" th:value="${bookId}"/>
<input type="hidden" id="bookNamedHidden" th:value="${book.bookName}"/>
<input type="hidden" id="preContentId" th:value="${firstBookIndexId}"/>
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
<div style="float: left;margin-left: 10px">
<a href="javascript:history.go(-1)">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe65c;</i></a>
</div>
<b class="layui-icon" th:utext="${book.bookName}"></b>
<div style="float: right;margin-right: 10px">
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe68e;</i></a>
</div>
</div>
<div class="layui-row" style="background: #f2f2f2">
<div style="padding: 10px" class="layui-col-xs4 layui-col-sm2 layui-col-md2 layui-col-lg2">
<img style=" width:auto; height:auto; max-width:100%; max-height:100%;" th:src="${book.picUrl}"/>
</div>
<div style="position:relative;padding: 10px 20px" class="layui-col-xs8 layui-col-sm8 layui-col-md8 layui-col-lg8">
<a th:href="'javascript:searchBooks(\''+ ${book.authorName}+'\')'"><div style=";color: #4c6978;" th:utext="'作者'+ ${book.authorName}"></div></a>
<a th:href="'/book/book_ranking.html?catId='+${book.catId}"><div style="margin-top: 5px;color: #4c6978;" th:text="'类别'+ ${book.catName}"></div></a>
<div style="margin-top: 5px;color: #4c6978;" th:text="'状态'+ ${book.bookStatus==0?'连载':'完结'}"></div>
<div style="margin-top: 5px;color: #4c6978;">更新:<i th:text="${#dates.format(book.lastIndexUpdateTime, 'yy-MM-dd')}"></i></div>
<div style="margin-top: 5px;color: #4c6978;">评分:<i style="font-weight:bold;color: red" th:text="${book.score} + '分'"></i></div>
<div style="margin-top: 5px;color: #4c6978;">点击:<i style="font-weight:bold;color: red" th:text="${book.visitCount}"></i></div>
</div>
</div>
<div style="text-align: center;height: 45px;line-height: 45px">
<a th:href="'/book/'+${book.id}+'/'+${firstBookIndexId}+'.html'" type="button" class="layui-btn layui-btn-sm layui-btn-radius">开始阅读</a>
<!--
<button type="button" onclick="downloadFile()" class="layui-btn layui-btn-sm layui-btn-radius layui-bg-normal">下载TXT</button>
-->
</div>
<p style="line-height: 23px;padding: 10px;font-size: 14px;color: #4c6978;" th:utext="${book.bookDesc}">
</p>
<div class="layui-collapse">
<div class="layui-colla-item" >
<h2 class="layui-colla-title">
<span>最新章节</span>
<span style="margin-left: 30px">
更新: <i th:text="${#dates.format(book.lastIndexUpdateTime, 'yy-MM-dd HH:mm:ss')}"></i>
</span>
</h2>
<div class="layui-colla-content layui-show indexP layui-row" id="indexList">
</div>
</div>
</div>
<div style="height: 42px;color:#4c6978;line-height: 42px;padding-left: 30px;background: #f2f2f2" >
<a th:href="'/book/indexList-'+${book.id}+'.html'">查看完整目录</a>
</div>
<!--
<div style="position: fixed;top:0px;left:0px;z-index:-100;opacity: 0" th:utext="${attacDivForSearch}"></div>
-->
</div>
<div th:replace="mobile/common/footer :: footer">
</div>
</body>
<div th:replace="mobile/common/js :: js">
</div>
<script>
//查询是否在书架
$.ajax({
type: "GET",
url: "/user/queryIsInShelf",
data: {'bookId': $("#bookIdHidden").val()},
dataType: "json",
success: function (data) {
if (data.code == 200) {
if (data.data) {
$("#cFavs").html("<button type=\"button\" id=\"cFavs\" class=\"layui-btn layui-btn-sm layui-btn-radius layui-btn-warm\">已在书架</button>");
}
} else if (data.code == 1001) {
//未登录
} else {
layer.alert(data.msg);
}
},
error: function () {
layer.alert('网络异常');
}
})
//查询最新目录集合
$.ajax({
type: "GET",
url: "/book/queryNewIndexList",
data: {'bookId': $("#bookIdHidden").val()},
dataType: "json",
success: function (data) {
if (data.code == 200) {
var indexListHtml = "";
for(var i = 0 ; i < data.data.length ; i++){
var bookIndex = data.data[i];
indexListHtml+=("<p class=\"line-limit-length layui-col-xs12 layui-col-sm4 layui-col-md3 layui-col-lg2\" style=\"padding-left:10px;height: 50px;line-height: 50px;\"><a href=\"/book/"+$("#bookIdHidden").val()+"/"+bookIndex.id+".html\">"+bookIndex.indexName+"</a></p>");
}
$("#indexList").html(indexListHtml);
} else if (data.code == 1001) {
//未登录
} else {
layer.alert(data.msg);
}
},
error: function () {
layer.alert('网络异常');
}
})
function addInShell() {
$.ajax({
type: "POST",
url: "/user/addToBookShelf",
data: {'bookId': $("#bookIdHidden").val(), 'preContentId': $("#preContentId").val()},
dataType: "json",
success: function (data) {
if (data.code == 200) {
$("#cFavs").html("<button type=\"button\" id=\"cFavs\" class=\"layui-btn layui-btn-sm layui-btn-radius layui-btn-warm\">已在书架</button>");
} else if (data.code == 1001) {
//未登录
location.href = '/user/login.html?originUrl=' + decodeURIComponent(location.href);
} else {
layer.alert(data.msg);
}
},
error: function () {
layer.alert('网络异常');
}
})
}
$("#content").css("min-height",($(window).height()-60)+"px");
function downloadFile() {
var fileUrl = '/book/download?bookId='+$("#bookIdHidden").val()+'&bookName='+$("#bookNamedHidden").val();
window.location.href=fileUrl;
}
function toMyCollect(){
var token = localStorage.getItem("token");
if(token) {
window.location.href = "/book/search?token=" + token;
}else{
window.location.href = "/user/login.html";
}
}
function addToCollect(){
var token = localStorage.getItem("token");
if(token) {
$.get("/user/addToCollect",{"bookId":$("#bookIdHidden").val(),"token":token},function(data){
layer.alert(data.desc);
if(data.code == 1) {
$('#collectButton').unbind("click");
$("#collectButton").text("撤下书架");
$("#collectButton").click(function () {
cancelToCollect();
});
}
});
}else{
window.location.href = "/user/login.html?bookId="+$("#bookIdHidden").val();
}
}
function cancelToCollect(){
var token = localStorage.getItem("token");
if(token) {
$.get("/user/cancelToCollect",{"bookId":$("#bookIdHidden").val(),"token":token},function(data){
layer.alert(data.desc);
if(data.code == 1) {
$('#collectButton').unbind("click");
$("#collectButton").text("加入书架");
$("#collectButton").click(function () {
addToCollect();
});
}
});
}else{
window.location.href = "/user/login.html?bookId="+$("#bookIdHidden").val();
}
}
function searchBooks(keyword) {
window.location.href = "/book/book_ranking.html?keyword=" + encodeURI(keyword);
}
$.post("/book/addVisitCount", {"bookId": $("#bookIdHidden").val()}, function () {
});
</script>
</html>

View File

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title th:utext="${book.bookName}+'最新免费章节目录列表'"></title>
<meta name="keywords" th:content="${book.bookName}+','+${book.bookName}+'最新章节'">
<meta name="description"
th:content="${book.bookName}+'最新章节列表,'+${book.bookName}+'最新更新章节免费无广告无弹窗在线阅读TXT下载。'">
</div>
<div th:include="mobile/common/css :: css"></div>
<style type="text/css">
.indexP p a {
color: #4c6978;
}
.line-limit-length {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
</div>
</head>
<body>
<div id="content">
<input type="hidden" id="bookIdHidden" th:value="${book.id}"/>
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
<div style="float: left;margin-left: 10px">
<a href="javascript:history.go(-1)">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe65c;</i></a>
</div>
<a style="color: #ffffff;" th:href="'/book/'+ ${book.id} + '.html'"><b class="layui-icon" th:utext="${book.bookName}"></b></a>
<div style="float: right;margin-right: 10px">
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe68e;</i></a>
</div>
</div>
<p style="height: 30px;line-height: 30px;padding: 10px">
<a href="#buttom" style="color: red">&nbsp;&nbsp;↓直达页面底部</a>
</p>
<div class="layui-colla-content layui-show indexP layui-row">
<p class="line-limit-length layui-col-xs12 layui-col-sm4 layui-col-md3 layui-col-lg2" style="padding-left:10px;height: 50px;line-height: 50px;" th:each="index : ${bookIndexList}">
<a th:href="'/book/'+${index.bookId}+'/'+${index.id}+'.html'" th:utext="${index.indexName}">
</a>
</p>
</div>
</div>
<div th:replace="mobile/common/footer :: footer">
</div>
<a name="buttom"></a>
</body>
<div th:replace="mobile/common/js :: js">
</div>
<script>
$("#content").css("min-height",($(window).height()-60)+"px");
$.get("/book/addVisit",{"bookId":$("#bookIdHidden").val()},function(){});
function toMyCollect(){
var token = localStorage.getItem("token");
if(token) {
window.location.href = "/book/search?token=" + token;
}else{
window.location.href = "/user/login.html";
}
}
</script>
</html>

View File

@ -0,0 +1,320 @@
<!DOCTYPE html>
<html lang="en">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title th:text="#{website.name}+'列表'"></title>
<meta name="keywords"
th:content="#{website.name}+',精品小说,弹幕网站,弹幕,弹幕小说网站,免费小说,小说阅读,小说排行,轻小说,txt小说下载,电子书下载,动漫轻小说,日本轻小说'">
<meta name="description"
th:content="#{website.name}+'是国内优秀的小说弹幕网站,'+#{website.name}+'提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。'">
<div th:include="mobile/common/css :: css"></div>
</div>
<style type="text/css">
.line-limit-length {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.indexP p a {
color: #4c6978;
}
.Readarea {
font-size: 18px;
line-height: 35px;
padding: 10px;
color: #333;
}
div, p {
wrap-work: break-word;
word-break: break-all;
word-wrap: break-word;
word-break: normal;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-ms-box-sizing: border-box;
}
.indexDiv a {
margin-left: 20px;
}
img {
width: 130px;
height: 180px;
}
</style>
</head>
<body>
<input type="hidden" id="limit" th:value="${limit}"/>
<input type="hidden" id="curr" th:value="${curr}"/>
<input type="hidden" id="total" th:value="${total}"/>
<input type="hidden" id="ids" th:value="${ids}"/>
<input type="hidden" id="bookStatus" th:value="${bookStatus}"/>
<input type="hidden" id="token" th:value="${token}"/>
<input type="hidden" id="keyword" th:value="${keyword}"/>
<input type="hidden" id="catId" th:value="${catId}"/>
<input type="hidden" id="sortBy" th:value="${sortBy}"/>
<input type="hidden" id="sort" th:value="${sort}"/>
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
<div style="float: left;margin-left: 10px">
<a href="javascript:history.go(-1)">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe65c;</i></a>
</div>
<b class="layui-icon">小说列表</b>
<div style="float: right;margin-right: 10px">
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe68e;</i></a>
</div>
</div>
<div class="layui-container">
<div class="layui-row">
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
autocomplete="off"
class="layui-input" th:value="${keyword}">
</div>
<div class="layui-col-xs1" style="padding: 1%">
<button onclick="search(1,20)" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
</div>
</div>
</div>
<div id="bookList">
</div>
<div id="books" style="text-align: center"></div>
<div th:replace="mobile/common/footer :: footer">
</div>
<a name="buttom"></a>
</body>
<div th:replace="mobile/common/js :: js"></div>
<script>
var catId = getQueryVariable("catId");
var bookStatus = getQueryVariable("bookStatus");
var sortBy = getQueryVariable("sortBy");
var keyword = getQueryVariable("keyword");
if(keyword != false){
$("#title").val(decodeURI(keyword));
}else{
keyword = "";
}
search(1,20);
function search(curr,limit) {
var searchData = {};
searchData.curr = curr;
searchData.limit = limit;
keyword = $("#title").val();
if(catId != false){
searchData.catId = catId;
}
if(bookStatus != false){
searchData.bookStatus = bookStatus;
}
if(sortBy != false){
searchData.sort = sortBy;
}else if(!keyword){
sortBy = "last_index_update_time";
}
if(keyword){
searchData.keyword = keyword;
}
$.ajax({
type: "GET",
url: "/book/searchByPage",
data: searchData,
dataType: "json",
success: function (data) {
if (data.code == 200) {
var bookList = data.data.list;
var bookListHtml = "";
for (var i = 0; i < bookList.length; i++) {
var book = bookList[i];
/*var end = book.bookDesc.indexOf("<");
if(end != -1) {
book.bookDesc = book.bookDesc.substring(0,end);
}*/
if(book.bookDesc){
book.bookDesc = book.bookDesc.replace(/<[^>]+>/g,"").replace(/\s+/g,"").replace(/&nbsp;/g,"");
}
bookListHtml += ("<div class=\"layui-row\" style=\"margin-bottom:10px;padding:10px;background: #f2f2f2\">\n" +
" <a href=\"/book/"+book.id+".html\">\n" +
" <div class=\"layui-col-xs6 layui-col-sm3 layui-col-md2 layui-col-lg2\" style=\"text-align: center\">\n" +
" <img width='150' height='180' align=\"center\"\n" +
" src=\""+book.picUrl+"\"/>\n" +
"\n" +
" </div>\n" +
" </a>\n" +
" <div style=\"padding: 10px\" class=\"layui-col-xs6 layui-col-sm8 layui-col-md8 layui-col-lg8\">\n" +
" <a href=\"/book/"+book.id+".html\">\n" +
" <div class=\"line-limit-length\" style=\";color: #4c6978;font-weight: bold;font-size: 15px\">"+book.bookName+"</div>\n" +
" </a>\n" +
" <div style=\";color: #4c6978;float: right;\"><i style=\"color: red\"></i></div>\n" +
" <a href=\"/book/book_ranking.html?keyword="+encodeURI(book.authorName)+"\">\n" +
" <div style=\";color: #4c6978;\" class=\"line-limit-length\">作者:"+book.authorName+"</div>\n" +
" </a>\n" +
" <div style=\"margin-top: 5px;color: #4c6978;\">类别:"+book.catName+"</div>\n" +
" <div style=\"margin-top: 5px;color: #4c6978;\">状态:"+(book.bookStatus==0?'连载':'完结')+"</div>\n" +
" <div style=\"margin-top: 5px;color: #4c6978;\">更新:<i>"+book.lastIndexUpdateTime.substr(0,11)+"</i>\n" +
" </div>\n" +
" <div style=\"margin-top: 5px;color: #4c6978;\">简介:"+(book.bookDesc?(book.bookDesc.length>20?(book.bookDesc.substr(0,20)+"..."):book.bookDesc):book.bookDesc)+"</div>\n" +
"\n" +
"\n" +
" </div>\n" +
"\n" +
" </div>");
}
$("#bookList").html(bookListHtml);
layui.use('laypage', function () {
var laypage = layui.laypage;
//执行一个laypage实例
laypage.render({
elem: 'books' //注意,这里的 test1 是 ID不用加 # 号
, count: data.data.total //数据总数,从服务端得到,
, curr: data.data.pageNum
, limit: data.data.pageSize
, jump: function (obj, first) {
//obj包含了当前分页的所有参数比如
console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。
console.log(obj.limit); //得到每页显示的条数
//首次不执行
if (!first) {
search(obj.curr, obj.limit);
} else {
}
}
});
});
} else {
layer.alert(data.msg);
}
},
error: function () {
layer.alert('网络异常');
}
})
}
function searchByAllCondition(curr, limit, newKeyword) {
var toUrl = "/book/search?curr=" + curr + "&limit=" + limit;
var ids = $("#ids").val();
if (ids) {
toUrl += ("&historyBookIds=" + ids);
}
var token = $("#token").val();
if (token) {
toUrl += ("&token=" + token);
}
var keyword = $("#keyword").val();
if (newKeyword) {
toUrl += encodeURI("&keyword=" + newKeyword);
} else if (keyword) {
toUrl += encodeURI("&keyword=" + keyword);
}
var bookStatus = $("#bookStatus").val();
if (bookStatus) {
toUrl += ("&bookStatus=" + bookStatus);
}
var catId = $("#catId").val();
if (catId) {
toUrl += ("&catId=" + catId);
}
var sortBy = $("#sortBy").val();
if (sortBy) {
toUrl += ("&sortBy=" + sortBy);
}
var sort = $("#sort").val();
if (sort) {
toUrl += ("&sort=" + sort);
}
window.location.href = toUrl;
}
function searchBooks() {
var keywords = $("#title").val();
$("#keyword").val("");
searchByAllCondition(1, 20, keywords);
}
</script>
<script>
function toMyCollect() {
var token = localStorage.getItem("token");
if (token) {
window.location.href = "/book/search?token=" + token;
} else {
window.location.href = "/user/login.html";
}
}
</script>
</html>

View File

@ -0,0 +1,88 @@
<!DOCTYPE html>
<html lang="en">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>小说提交</title>
<div th:include="common/css :: css"></div>
</head>
<body id="read" >
</div>
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
<div style="float: left;margin-left: 10px">
<a href="javascript:history.go(-1)">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe65c;</i></a>
</div>
<b class="layui-icon">单本小说提交</b>
<div style="float: right;margin-right: 10px"><a href="/">
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon">&#xe68e;</i>
</a>
</div>
</div>
<div style="height: 800px;padding: 20px;border: 1px solid #eee;">
<form class="layui-form" action="">
<div class="layui-form-item">
<label class="layui-form-label">详情页Url:</label>
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1" >
<input type="text" id="bookUrl" name="bookUrl" required lay-verify="required" placeholder="请输入源站小说详情页Url" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">小说名:</label>
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1" >
<input type="text" id="bookName" name="bookName" required lay-verify="required" placeholder="请输入小说名" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">小说评分:</label>
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1">
<input type="number" id="score" name="score" required lay-verify="required" placeholder="请输入小说评分" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="formDemo">提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</div>
<div th:replace="common/footer :: footer">
</div>
<a name="buttom"></a>
</body>
<div th:replace="common/js :: js"></div>
<script>
//Demo
layui.use('form', function(){
var form = layui.form;
//监听提交
form.on('submit(formDemo)', function(){
$.post("/book/submit",{"bookUrl":$("#bookUrl").val(),"bookName":$("#bookName").val(),"score":$("#score").val()},function (data) {
if(data.code == 1 ){
layer.alert("提交成功任务排队中请过一段时间后再搜索查看");
}else{
layer.alert("提交失败");
}
});
return false;
});
});
</script>
</html>

View File

@ -0,0 +1,270 @@
<!DOCTYPE html>
<html lang="en">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title th:text="${application.seoConfig.page['mh-search.title']}"></title>
<meta name="keywords" th:content="${application.seoConfig.page['mh-search.keyword']}">
<meta name="description"
th:content="${application.seoConfig.page['mh-search.description']}">
<div th:include="common/css :: css"></div>
</div>
<style type="text/css">
.line-limit-length {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.indexP p a {
color: #4c6978;
}
.Readarea {
font-size: 18px;
line-height: 35px;
padding: 10px;
color: #333;
}
div, p {
wrap-work: break-word;
word-break: break-all;
word-wrap: break-word;
word-break: normal;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-ms-box-sizing: border-box;
}
.indexDiv a {
margin-left: 20px;
}
img {
width: 147px;
height: 197px;
}
</style>
</head>
<body>
<input type="hidden" id="limit" th:value="${limit}"/>
<input type="hidden" id="curr" th:value="${curr}"/>
<input type="hidden" id="total" th:value="${total}"/>
<input type="hidden" id="ids" th:value="${ids}"/>
<input type="hidden" id="keyword" th:value="${keyword}"/>
<input type="hidden" id="softTag" th:value="${softTag}"/>
<input type="hidden" id="sortBy" th:value="${sortBy}"/>
<input type="hidden" id="sort" th:value="${sort}"/>
<input type="hidden" id="bookStatus" th:value="${bookStatus}"/>
<input type="hidden" id="softCat" th:value="${softCat}"/>
<ul class="layui-nav" lay-filter="" style="padding:0 20px;text-align: center" >
<li id="menunew" class="layui-nav-item"><a href="/book/searchSoftBook.html?catId=9">最新</a></li>
<li id="menu21" class="layui-nav-item"><a href="/book/searchSoftBook.html?catId=9&softCat=3262">少年漫</a></li>
<li id="menu22" class="layui-nav-item"><a href="/book/searchSoftBook.html?catId=9&softCat=3263">少女漫</a></li>
<li id="menucomplete" class="layui-nav-item"><a >完本</a>
<dl class="layui-nav-child"> <!-- 二级菜单 -->
<dd><a href="/book/searchSoftBook.html?catId=9&bookStatus=已完成">全部</a></dd>
<dd><a href="/book/searchSoftBook.html?catId=9&bookStatus=已完成&softCat=3262">少年漫</a></dd>
<dd><a href="/book/searchSoftBook.html?catId=9&bookStatus=已完成&softCat=3263">少女漫</a></dd>
</dl>
</li>
<li id="menuhot" class="layui-nav-item"><a >排行</a>
<dl class="layui-nav-child"> <!-- 二级菜单 -->
<dd><a href="/book/searchSoftBook.html?catId=9&sortBy=score">全部</a></dd>
<dd><a href="/book/searchSoftBook.html?catId=9&sortBy=score&softCat=3262">少年漫</a></dd>
<dd><a href="/book/searchSoftBook.html?catId=9&bookStatus=已完成&softCat=3263">少女漫</a></dd>
</dl>
</li>
</ul>
<div class="layui-container">
<div class="layui-row">
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
autocomplete="off"
class="layui-input" th:value="${keyword}">
</div>
<div class="layui-col-xs1" style="padding: 1%">
<button onclick="searchBooks()" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
</div>
</div>
</div>
<div th:each="book : ${books}" class="layui-row" style="margin-bottom:10px;padding:10px;background: #f2f2f2">
<a th:href="'/book/'+ ${book.id} + '.html'">
<div class="layui-col-xs6 layui-col-sm3 layui-col-md2 layui-col-lg2" style="text-align: center" th:switch = "${application.noLazy}">
<img th:case="'1'" align="center"
th:attr="data-src=${book.picUrl}"/>
<img th:case="*" align="center"
class="lazyload" th:attr="data-src=${book.picUrl}"/>
</div>
</a>
<div style="padding: 20px" class="layui-col-xs6 layui-col-sm8 layui-col-md8 layui-col-lg8">
<a th:href="'/book/'+ ${book.id} + '.html'">
<div class="line-limit-length" style=";color: #4c6978;font-weight: bold;font-size: 15px"
th:text="${book.bookName}"></div>
</a>
<div style=";color: #4c6978;float: right;"><i style="color: red" th:text="${book.score} + '分'"></i></div>
<a th:href="'/book/searchSoftBook.html?catId=9&keyword='+ ${book.author}">
<div style=";color: #4c6978;" class="line-limit-length" th:text="'作者'+ ${book.author}"></div>
</a>
<div style="margin-top: 5px;color: #4c6978;" th:text="'类别'+ ${book.cateName}"></div>
<div style="margin-top: 5px;color: #4c6978;" th:text="'状态'+ ${book.bookStatus}"></div>
<div style="margin-top: 5px;color: #4c6978;">更新:<i th:text="${#dates.format(book.updateTime, 'yy-MM-dd')}"></i>
</div>
<div class="layui-collapse" style="margin-top: 5px;">
<div class="layui-colla-item">
<h2 style="color: #4c6978;" class="layui-colla-title">简介:</h2>
<div style="color: #4c6978;" class="layui-colla-content" th:utext="${book.bookDesc}">
</div>
</div>
</div>
</div>
</div>
<div id="books" style="text-align: center"></div>
<div th:replace="common/soft_footer :: footer">
</div>
<a name="buttom"></a>
</body>
<div th:replace="common/js :: js"></div>
<script src="/js/lazyload.js"></script>
<script>
lazyload();
layui.use('laypage', function () {
var laypage = layui.laypage;
//执行一个laypage实例
laypage.render({
elem: 'books' //注意,这里的 test1 是 ID不用加 # 号
, count: $("#total").val() //数据总数,从服务端得到,
, curr: $("#curr").val()
, limit: $("#limit").val()
, jump: function (obj, first) {
//obj包含了当前分页的所有参数比如
console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。
console.log(obj.limit); //得到每页显示的条数
//首次不执行
if (!first) {
searchByAllCondition(obj.curr,obj.limit);
} else {
}
}
});
});
function searchByAllCondition(curr,limit,newKeyword){
var toUrl = "/book/searchSoftBook.html?catId=9&curr=" + curr + "&limit=" + limit;
var ids = $("#ids").val();
if(ids){
toUrl += ("&historyBookIds=" + ids);
}
var keyword = $("#keyword").val();
if(newKeyword){
toUrl += encodeURI("&keyword=" + newKeyword);
}else if (keyword) {
toUrl += encodeURI("&keyword=" + keyword);
}
var bookStatus = $("#bookStatus").val();
if(bookStatus){
toUrl += ("&bookStatus=" + bookStatus);
}
var softCat = $("#softCat").val();
if (softCat) {
toUrl += ("&softCat=" + softCat);
}
var softTag = $("#softTag").val();
if (softTag) {
toUrl += ("&softTag=" + softTag);
}
var sortBy = $("#sortBy").val();
if (sortBy) {
toUrl += ("&sortBy=" + sortBy);
}
var sort = $("#sort").val();
if (sort) {
toUrl += ("&sort=" + sort);
}
window.location.href = toUrl;
}
function searchBooks() {
var keywords = $("#title").val();
$("#keyword").val("");
searchByAllCondition(1,20,keywords);
}
</script>
<script>
(function(){
var sortCat = $("#softCat").val();
var sortBy = $("#sortBy").val();
if(sortBy == 'score'){
$("#menuhot").addClass("layui-this");
}else if($("#bookStatus").val()){
$("#menucomplete").addClass("layui-this");
}else if(sortCat){
$("#menu"+sortCat).addClass("layui-this");
}else{
$("#menunew").addClass("layui-this");
}
})();
function toMyCollect(){
var token = localStorage.getItem("token");
if(token) {
window.location.href = "/book/search?token=" + token;
}else{
window.location.href = "/user/login.html";
}
}
</script>
</html>

View File

@ -0,0 +1,294 @@
<!DOCTYPE html>
<html lang="en">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title th:text="${application.seoConfig.page['soft-search.title']}"></title>
<meta name="keywords" th:content="${application.seoConfig.page['soft-search.keyword']}">
<meta name="description"
th:content="${application.seoConfig.page['soft-search.description']}">
<div th:include="common/css :: css"></div>
</div>
<style type="text/css">
.line-limit-length {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.indexP p a {
color: #4c6978;
}
.Readarea {
font-size: 18px;
line-height: 35px;
padding: 10px;
color: #333;
}
div, p {
wrap-work: break-word;
word-break: break-all;
word-wrap: break-word;
word-break: normal;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-ms-box-sizing: border-box;
}
.indexDiv a {
margin-left: 20px;
}
img {
width: 147px;
height: 197px;
}
</style>
</head>
<body>
<input type="hidden" id="limit" th:value="${limit}"/>
<input type="hidden" id="curr" th:value="${curr}"/>
<input type="hidden" id="total" th:value="${total}"/>
<input type="hidden" id="ids" th:value="${ids}"/>
<input type="hidden" id="keyword" th:value="${keyword}"/>
<input type="hidden" id="softTag" th:value="${softTag}"/>
<input type="hidden" id="sortBy" th:value="${sortBy}"/>
<input type="hidden" id="sort" th:value="${sort}"/>
<input type="hidden" id="bookStatus" th:value="${bookStatus}"/>
<input type="hidden" id="softCat" th:value="${softCat}"/>
<ul class="layui-nav" lay-filter="" style="padding:0 20px;text-align: center">
<li id="menunew" class="layui-nav-item"><a href="/book/searchSoftBook.html">最新</a></li>
<li id="menu21" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=21">魔幻</a></li>
<li id="menu22" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=22">玄幻</a></li>
<li id="menu23" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=23">古风</a></li>
<li id="menu24" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=24">科幻</a></li>
<li id="menu25" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=25">校园</a></li>
<li id="menu26" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=26">都市</a></li>
<li id="menu27" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=27">游戏</a></li>
<li id="menu28" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=28">同人</a></li>
<li id="menu29" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=29">悬疑</a></li>
<li id="menu0" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=0">动漫</a></li>
<li id="menucomplete" class="layui-nav-item"><a>完本</a>
<dl class="layui-nav-child"> <!-- 二级菜单 -->
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成">全部</a></dd>
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=21">魔幻</a></dd>
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=22">玄幻</a></dd>
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=23">古风</a></dd>
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=24">科幻</a></dd>
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=25">校园</a></dd>
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=26">都市</a></dd>
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=27">游戏</a></dd>
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=28">同人</a></dd>
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=29">悬疑</a></dd>
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=0">动漫</a></dd>
</dl>
</li>
<li id="menuhot" class="layui-nav-item"><a>排行</a>
<dl class="layui-nav-child"> <!-- 二级菜单 -->
<dd><a href="/book/searchSoftBook.html?sortBy=score">全部</a></dd>
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=21">魔幻</a></dd>
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=22">玄幻</a></dd>
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=23">古风</a></dd>
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=24">科幻</a></dd>
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=25">校园</a></dd>
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=26">都市</a></dd>
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=27">游戏</a></dd>
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=28">同人</a></dd>
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=29">悬疑</a></dd>
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=0">动漫</a></dd>
</dl>
</li>
</ul>
<div class="layui-container">
<div class="layui-row">
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
autocomplete="off"
class="layui-input" th:value="${keyword}">
</div>
<div class="layui-col-xs1" style="padding: 1%">
<button onclick="searchBooks()" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
</div>
</div>
</div>
<div th:each="book : ${books}" class="layui-row" style="margin-bottom:10px;padding:10px;background: #f2f2f2">
<a th:href="'/book/'+ ${book.id} + '.html'">
<div class="layui-col-xs6 layui-col-sm3 layui-col-md2 layui-col-lg2" style="text-align: center"
th:switch="${application.noLazy}">
<img th:case="'1'" align="center"
th:attr="data-src=${book.picUrl}"/>
<img th:case="*" align="center"
class="lazyload" th:attr="data-src=${book.picUrl}"/>
</div>
</a>
<div style="padding: 20px" class="layui-col-xs6 layui-col-sm8 layui-col-md8 layui-col-lg8">
<a th:href="'/book/'+ ${book.id} + '.html'">
<div class="line-limit-length" style=";color: #4c6978;font-weight: bold;font-size: 15px"
th:text="${book.bookName}"></div>
</a>
<div style=";color: #4c6978;float: right;"><i style="color: red" th:text="${book.score} + '分'"></i></div>
<a th:href="'/book/searchSoftBook.html?keyword='+ ${book.author}">
<div style=";color: #4c6978;" class="line-limit-length" th:text="'作者'+ ${book.author}"></div>
</a>
<div style="margin-top: 5px;color: #4c6978;" th:text="'类别'+ ${book.cateName}"></div>
<div style="margin-top: 5px;color: #4c6978;" th:text="'状态'+ ${book.bookStatus}"></div>
<div style="margin-top: 5px;color: #4c6978;">更新:<i th:text="${#dates.format(book.updateTime, 'yy-MM-dd')}"></i>
</div>
<div class="layui-collapse" style="margin-top: 5px;">
<div class="layui-colla-item">
<h2 style="color: #4c6978;" class="layui-colla-title">简介:</h2>
<div style="color: #4c6978;" class="layui-colla-content" th:utext="${book.bookDesc}">
</div>
</div>
</div>
</div>
</div>
<div id="books" style="text-align: center"></div>
<div th:replace="common/soft_footer :: footer">
</div>
<a name="buttom"></a>
</body>
<div th:replace="common/js :: js"></div>
<script src="/js/lazyload.js"></script>
<script>
lazyload();
layui.use('laypage', function () {
var laypage = layui.laypage;
//执行一个laypage实例
laypage.render({
elem: 'books' //注意,这里的 test1 是 ID不用加 # 号
, count: $("#total").val() //数据总数,从服务端得到,
, curr: $("#curr").val()
, limit: $("#limit").val()
, jump: function (obj, first) {
//obj包含了当前分页的所有参数比如
console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。
console.log(obj.limit); //得到每页显示的条数
//首次不执行
if (!first) {
searchByAllCondition(obj.curr, obj.limit);
} else {
}
}
});
});
function searchByAllCondition(curr, limit, newKeyword) {
var toUrl = "/book/searchSoftBook.html?curr=" + curr + "&limit=" + limit;
var ids = $("#ids").val();
if (ids) {
toUrl += ("&historyBookIds=" + ids);
}
var keyword = $("#keyword").val();
if (newKeyword) {
toUrl += encodeURI("&keyword=" + newKeyword);
} else if (keyword) {
toUrl += encodeURI("&keyword=" + keyword);
}
var bookStatus = $("#bookStatus").val();
if (bookStatus) {
toUrl += ("&bookStatus=" + bookStatus);
}
var softCat = $("#softCat").val();
if (softCat) {
toUrl += ("&softCat=" + softCat);
}
var softTag = $("#softTag").val();
if (softTag) {
toUrl += ("&softTag=" + softTag);
}
var sortBy = $("#sortBy").val();
if (sortBy) {
toUrl += ("&sortBy=" + sortBy);
}
var sort = $("#sort").val();
if (sort) {
toUrl += ("&sort=" + sort);
}
window.location.href = toUrl;
}
function searchBooks() {
var keywords = $("#title").val();
$("#keyword").val("");
searchByAllCondition(1, 20, keywords);
}
</script>
<script>
(function () {
var sortCat = $("#softCat").val();
var sortBy = $("#sortBy").val();
if (sortBy == 'score') {
$("#menuhot").addClass("layui-this");
} else if ($("#bookStatus").val()) {
$("#menucomplete").addClass("layui-this");
} else if (sortCat) {
$("#menu" + sortCat).addClass("layui-this");
} else {
$("#menunew").addClass("layui-this");
}
})();
function toMyCollect() {
var token = localStorage.getItem("token");
if (token) {
window.location.href = "/book/search?token=" + token;
} else {
window.location.href = "/user/login.html";
}
}
</script>
</html>

View File

@ -0,0 +1,24 @@
<div th:fragment="css">
<link rel="stylesheet" href="/mobile/layui/css/layui.css">
<style type="text/css">
.app {
display: none;
}
@media (max-width: 360px) {
.app {
display: block !important;
}
}
.pc {
display: block;
}
@media (max-width: 360px) {
.pc {
display: none;
}
}
</style>
</div>

View File

@ -0,0 +1,11 @@
<div th:fragment="footer" style="height: 60px;line-height: 60px;text-align: center" class="layui-footer footer footer-demo layui-bg-cyan">
<!--<a href="/mobile/book/searchSoftBook.html" style="font-size: 14px;color: #92B8B1;">轻小说</a>
<a href="/mobile/book/searchSoftBook.html?catId=9" style="font-size: 14px;color: #92B8B1;margin-left: 8px">漫画</a>-->
<a href="/?to=pc" style="font-size: 14px;color: #92B8B1;margin-left: 8px">电脑站</a>
<!--<a href="https://www.zinglizingli.xyz/me/index.html" style="font-size: 14px;color: #92B8B1;margin-left: 8px">开发者</a>-->
<div style="float: right"><a href="#top"><i class="layui-icon"
style="margin-right:15px;font-size: 30px;color:#92B8B1 ">&#xe604;</i></a>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show More