Compare commits
60 Commits
Author | SHA1 | Date | |
---|---|---|---|
d8e559ab50 | |||
3849a9b86f | |||
71b9d1d916 | |||
4b9dbe969c | |||
2136f7490f | |||
3586ffbc0a | |||
f78a2a36cf | |||
a8219253e9 | |||
5c35f7af0a | |||
d55e1a3e22 | |||
21a6a49ce9 | |||
3735023cef | |||
89992dc781 | |||
976db9420e | |||
e33db86081 | |||
48a70c2aca | |||
ea5c0e8bd1 | |||
b0c249cdca | |||
730fcb4c76 | |||
b976a00389 | |||
6d9b563583 | |||
bfb7d6cc5c | |||
9d4dc409c6 | |||
34d211afbf | |||
2d218076c4 | |||
674e4df84c | |||
331f56d112 | |||
f494aae2c7 | |||
2fc533f8ae | |||
82758271e3 | |||
4c82c2d720 | |||
4665b5c4b9 | |||
7bbabb3492 | |||
d6093d8182 | |||
f77792aa3c | |||
c62da9bb3a | |||
8a63cff0b5 | |||
07bed12fa5 | |||
0d6e0ffb06 | |||
e7005004bb | |||
ff68cdd829 | |||
b61dc4d0d5 | |||
98f1f804c3 | |||
5978d6cbcc | |||
ef290bed9c | |||
5543e5aa57 | |||
0332802fe5 | |||
a55f456b3d | |||
f6d66e69fb | |||
96960789e1 | |||
1998dcd460 | |||
a33d8f68a2 | |||
30959da038 | |||
5406783344 | |||
d84345918b | |||
a5394cb426 | |||
2275b85752 | |||
2062123edd | |||
255b3f8c4b | |||
00179359bd |
12
README.md
@ -57,9 +57,17 @@ novel-plus -- 父工程
|
|||||||
| Thymeleaf | 模板引擎
|
| Thymeleaf | 模板引擎
|
||||||
| Layui | 前端 UI 框架
|
| Layui | 前端 UI 框架
|
||||||
|
|
||||||
## 项目演示
|
## 项目截图
|
||||||
|
|
||||||
https://www.bilibili.com/video/BV1Zo4y187Mi
|
### 绿色主题模版
|
||||||
|
|
||||||
|
[](https://www.xxyopen.com/images/green_novel.png)
|
||||||
|
[](https://www.xxyopen.com/images/resource/os/novel-plus/green3.png)
|
||||||
|
[](https://www.xxyopen.com/images/resource/os/novel-plus/green2.png)
|
||||||
|
|
||||||
|
## 演示视频
|
||||||
|
|
||||||
|
https://www.bilibili.com/video/BV18e41197xs
|
||||||
|
|
||||||
## 增值服务
|
## 增值服务
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 411 KiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 263 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 461 KiB |
Before Width: | Height: | Size: 111 KiB |
Before Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 12 KiB |
BIN
assets/jk.png
Before Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 36 KiB |
BIN
assets/jk_wc.png
Before Width: | Height: | Size: 82 KiB |
BIN
assets/login.png
Before Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 310 KiB |
Before Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 223 KiB |
Before Width: | Height: | Size: 4.5 KiB |
BIN
assets/mini4.png
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 155 KiB |
Before Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 360 KiB |
Before Width: | Height: | Size: 357 KiB |
Before Width: | Height: | Size: 307 KiB |
Before Width: | Height: | Size: 929 KiB |
Before Width: | Height: | Size: 194 KiB |
Before Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 185 KiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 77 KiB |
BIN
assets/精品小说楼.png
Before Width: | Height: | Size: 764 KiB |
Before Width: | Height: | Size: 1.1 MiB |
116
doc/api/api.md
@ -1,116 +0,0 @@
|
|||||||
|
|
||||||
<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>
|
|
||||||
|
|
3
doc/sql/20240512.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
update crawl_source
|
||||||
|
set crawl_rule = replace(crawl_rule, 'ibiquge.net', 'ibiquzw.org')
|
||||||
|
where id = 16;
|
2
doc/sql/Dockerfile
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
FROM mysql:8.0
|
||||||
|
COPY novel_plus.sql /docker-entrypoint-initdb.d/init.sql
|
@ -1,20 +1,7 @@
|
|||||||
/*
|
CREATE database if NOT EXISTS `novel_plus` default character set utf8mb4 collate utf8mb4_unicode_ci;
|
||||||
Navicat MySQL Data Transfer
|
use `novel_plus`;
|
||||||
|
|
||||||
Source Server : localhost
|
SET NAMES utf8mb4;
|
||||||
Source Server Version : 50725
|
|
||||||
Source Host : localhost:3306
|
|
||||||
Source Database : novel_plus
|
|
||||||
|
|
||||||
Target Server Type : MYSQL
|
|
||||||
Target Server Version : 50725
|
|
||||||
File Encoding : 65001
|
|
||||||
|
|
||||||
Date: 2020-05-18 13:59:04
|
|
||||||
*/
|
|
||||||
|
|
||||||
SET
|
|
||||||
FOREIGN_KEY_CHECKS=0;
|
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for author
|
-- Table structure for author
|
||||||
@ -33,7 +20,9 @@ CREATE TABLE `author`
|
|||||||
`status` tinyint(4) DEFAULT '0' COMMENT '0:正常,1:封禁',
|
`status` tinyint(4) DEFAULT '0' COMMENT '0:正常,1:封禁',
|
||||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='作者表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 3
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='作者表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of author
|
-- Records of author
|
||||||
@ -58,7 +47,9 @@ CREATE TABLE `author_code`
|
|||||||
`create_user_id` bigint(20) DEFAULT NULL COMMENT '创建人ID',
|
`create_user_id` bigint(20) DEFAULT NULL COMMENT '创建人ID',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_code` (`invite_code`) USING BTREE
|
UNIQUE KEY `key_code` (`invite_code`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='作家邀请码表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 6
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='作家邀请码表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of author_code
|
-- Records of author_code
|
||||||
@ -105,7 +96,9 @@ CREATE TABLE `book`
|
|||||||
UNIQUE KEY `key_uq_bookName_authorName` (`book_name`, `author_name`) USING BTREE,
|
UNIQUE KEY `key_uq_bookName_authorName` (`book_name`, `author_name`) USING BTREE,
|
||||||
KEY `key_lastIndexUpdateTime` (`last_index_update_time`) USING BTREE,
|
KEY `key_lastIndexUpdateTime` (`last_index_update_time`) USING BTREE,
|
||||||
KEY `key_createTime` (`create_time`) USING BTREE
|
KEY `key_createTime` (`create_time`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1262260513468559361 DEFAULT CHARSET=utf8mb4 COMMENT='小说表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 1262260513468559361
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of book
|
-- Records of book
|
||||||
@ -130,7 +123,9 @@ CREATE TABLE `book_author`
|
|||||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||||
`update_user_id` bigint(20) DEFAULT NULL COMMENT '更新人ID',
|
`update_user_id` bigint(20) DEFAULT NULL COMMENT '更新人ID',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1254957873655066625 DEFAULT CHARSET=utf8mb4 COMMENT='作者表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 1254957873655066625
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='作者表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of book_author
|
-- Records of book_author
|
||||||
@ -151,7 +146,9 @@ CREATE TABLE `book_category`
|
|||||||
`update_user_id` bigint(20) DEFAULT NULL,
|
`update_user_id` bigint(20) DEFAULT NULL,
|
||||||
`update_time` datetime DEFAULT NULL,
|
`update_time` datetime DEFAULT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COMMENT='小说类别表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 8
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说类别表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of book_category
|
-- Records of book_category
|
||||||
@ -186,7 +183,9 @@ CREATE TABLE `book_comment`
|
|||||||
`create_user_id` bigint(20) DEFAULT NULL COMMENT '评价人',
|
`create_user_id` bigint(20) DEFAULT NULL COMMENT '评价人',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_bookid_userid` (`book_id`, `create_user_id`) USING BTREE
|
UNIQUE KEY `key_uq_bookid_userid` (`book_id`, `create_user_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COMMENT='小说评论表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 13
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说评论表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of book_comment
|
-- Records of book_comment
|
||||||
@ -209,7 +208,8 @@ CREATE TABLE `book_comment_reply`
|
|||||||
`create_time` datetime DEFAULT NULL COMMENT '回复用户ID',
|
`create_time` datetime DEFAULT NULL COMMENT '回复用户ID',
|
||||||
`create_user_id` bigint(20) DEFAULT NULL COMMENT '回复时间',
|
`create_user_id` bigint(20) DEFAULT NULL COMMENT '回复时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='小说评论回复表';
|
) ENGINE = InnoDB
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说评论回复表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of book_comment_reply
|
-- Records of book_comment_reply
|
||||||
@ -226,7 +226,9 @@ CREATE TABLE `book_content`
|
|||||||
`content` mediumtext COMMENT '小说章节内容',
|
`content` mediumtext COMMENT '小说章节内容',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=3347665 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 3347665
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说内容表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of book_content
|
-- Records of book_content
|
||||||
@ -250,7 +252,9 @@ CREATE TABLE `book_index`
|
|||||||
UNIQUE KEY `key_uq_bookId_indexNum` (`book_id`, `index_num`) USING BTREE,
|
UNIQUE KEY `key_uq_bookId_indexNum` (`book_id`, `index_num`) USING BTREE,
|
||||||
KEY `key_bookId` (`book_id`) USING BTREE,
|
KEY `key_bookId` (`book_id`) USING BTREE,
|
||||||
KEY `key_indexNum` (`index_num`) USING BTREE
|
KEY `key_indexNum` (`index_num`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1262260612777095169 DEFAULT CHARSET=utf8mb4 COMMENT='小说目录表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 1262260612777095169
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说目录表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of book_index
|
-- Records of book_index
|
||||||
@ -268,7 +272,9 @@ CREATE TABLE `book_screen_bullet`
|
|||||||
`create_time` datetime NOT NULL COMMENT '创建时间',
|
`create_time` datetime NOT NULL COMMENT '创建时间',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `key_contentId` (`content_id`) USING BTREE
|
KEY `key_contentId` (`content_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=79 DEFAULT CHARSET=utf8mb4 COMMENT='小说弹幕表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 79
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说弹幕表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of book_screen_bullet
|
-- Records of book_screen_bullet
|
||||||
@ -289,7 +295,9 @@ CREATE TABLE `book_setting`
|
|||||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||||
`update_user_id` bigint(20) DEFAULT NULL COMMENT '更新人ID',
|
`update_user_id` bigint(20) DEFAULT NULL COMMENT '更新人ID',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=64 DEFAULT CHARSET=utf8mb4 COMMENT='首页小说设置表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 64
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='首页小说设置表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of book_setting
|
-- Records of book_setting
|
||||||
@ -373,7 +381,8 @@ CREATE TABLE `crawl_batch_task`
|
|||||||
`start_time` datetime DEFAULT NULL COMMENT '任务开始时间',
|
`start_time` datetime DEFAULT NULL COMMENT '任务开始时间',
|
||||||
`end_time` datetime DEFAULT NULL COMMENT '任务结束时间',
|
`end_time` datetime DEFAULT NULL COMMENT '任务结束时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='批量抓取任务表';
|
) ENGINE = InnoDB
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='批量抓取任务表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of crawl_batch_task
|
-- Records of crawl_batch_task
|
||||||
@ -392,7 +401,8 @@ CREATE TABLE `crawl_single_task`
|
|||||||
`exc_count` tinyint(2) DEFAULT '0' COMMENT '已经执行次数,最多执行5次',
|
`exc_count` tinyint(2) DEFAULT '0' COMMENT '已经执行次数,最多执行5次',
|
||||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='抓取单本小说任务表';
|
) ENGINE = InnoDB
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='抓取单本小说任务表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of crawl_single_task
|
-- Records of crawl_single_task
|
||||||
@ -411,7 +421,9 @@ CREATE TABLE `crawl_source`
|
|||||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='爬虫源表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 5
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='爬虫源表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of crawl_source
|
-- Records of crawl_source
|
||||||
@ -449,7 +461,9 @@ CREATE TABLE `friend_link`
|
|||||||
`update_user_id` bigint(20) DEFAULT NULL COMMENT '更新者用户id',
|
`update_user_id` bigint(20) DEFAULT NULL COMMENT '更新者用户id',
|
||||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 6
|
||||||
|
DEFAULT CHARSET = utf8mb4;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of friend_link
|
-- Records of friend_link
|
||||||
@ -474,7 +488,9 @@ CREATE TABLE `news`
|
|||||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||||
`update_user_id` bigint(20) DEFAULT NULL COMMENT '更新人ID',
|
`update_user_id` bigint(20) DEFAULT NULL COMMENT '更新人ID',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='新闻表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 3
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='新闻表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of news
|
-- Records of news
|
||||||
@ -502,7 +518,9 @@ CREATE TABLE `news_category`
|
|||||||
`update_user_id` bigint(20) DEFAULT NULL,
|
`update_user_id` bigint(20) DEFAULT NULL,
|
||||||
`update_time` datetime DEFAULT NULL,
|
`update_time` datetime DEFAULT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='新闻类别表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 4
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='新闻类别表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of news_category
|
-- Records of news_category
|
||||||
@ -528,7 +546,9 @@ CREATE TABLE `order_pay`
|
|||||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COMMENT='充值订单';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 15
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='充值订单';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of order_pay
|
-- Records of order_pay
|
||||||
@ -551,7 +571,9 @@ CREATE TABLE `sys_data_perm`
|
|||||||
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
|
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
|
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=216 DEFAULT CHARSET=utf8 COMMENT='数据权限管理';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 216
|
||||||
|
DEFAULT CHARSET = utf8 COMMENT ='数据权限管理';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_data_perm
|
-- Records of sys_data_perm
|
||||||
@ -581,7 +603,9 @@ CREATE TABLE `sys_dept`
|
|||||||
`order_num` int(11) DEFAULT NULL COMMENT '排序',
|
`order_num` int(11) DEFAULT NULL COMMENT '排序',
|
||||||
`del_flag` tinyint(4) DEFAULT '0' COMMENT '是否删除 -1:已删除 0:正常',
|
`del_flag` tinyint(4) DEFAULT '0' COMMENT '是否删除 -1:已删除 0:正常',
|
||||||
PRIMARY KEY (`dept_id`)
|
PRIMARY KEY (`dept_id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 COMMENT='部门管理';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 17
|
||||||
|
DEFAULT CHARSET = utf8 COMMENT ='部门管理';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_dept
|
-- Records of sys_dept
|
||||||
@ -618,7 +642,10 @@ CREATE TABLE `sys_dict`
|
|||||||
KEY `sys_dict_value` (`value`),
|
KEY `sys_dict_value` (`value`),
|
||||||
KEY `sys_dict_label` (`name`),
|
KEY `sys_dict_label` (`name`),
|
||||||
KEY `sys_dict_del_flag` (`del_flag`)
|
KEY `sys_dict_del_flag` (`del_flag`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=142 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='字典表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 142
|
||||||
|
DEFAULT CHARSET = utf8
|
||||||
|
COLLATE = utf8_bin COMMENT ='字典表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_dict
|
-- Records of sys_dict
|
||||||
@ -895,7 +922,9 @@ CREATE TABLE `sys_file`
|
|||||||
`url` varchar(200) DEFAULT NULL COMMENT 'URL地址',
|
`url` varchar(200) DEFAULT NULL COMMENT 'URL地址',
|
||||||
`create_date` datetime DEFAULT NULL COMMENT '创建时间',
|
`create_date` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=183 DEFAULT CHARSET=utf8 COMMENT='文件上传';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 183
|
||||||
|
DEFAULT CHARSET = utf8 COMMENT ='文件上传';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_file
|
-- Records of sys_file
|
||||||
@ -1001,7 +1030,9 @@ CREATE TABLE `sys_gen_columns`
|
|||||||
`is_required` tinyint(1) DEFAULT NULL COMMENT '是否必填',
|
`is_required` tinyint(1) DEFAULT NULL COMMENT '是否必填',
|
||||||
`dict_type` varchar(100) CHARACTER SET utf8 DEFAULT '' COMMENT '页面显示为下拉时使用,字典类型从字典表中取出',
|
`dict_type` varchar(100) CHARACTER SET utf8 DEFAULT '' COMMENT '页面显示为下拉时使用,字典类型从字典表中取出',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=815 DEFAULT CHARSET=utf8mb4;
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 815
|
||||||
|
DEFAULT CHARSET = utf8mb4;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_gen_columns
|
-- Records of sys_gen_columns
|
||||||
@ -1189,7 +1220,8 @@ CREATE TABLE `sys_gen_table`
|
|||||||
`update_date` datetime NOT NULL COMMENT '更新时间',
|
`update_date` datetime NOT NULL COMMENT '更新时间',
|
||||||
`remarks` varchar(500) DEFAULT NULL COMMENT '备注信息',
|
`remarks` varchar(500) DEFAULT NULL COMMENT '备注信息',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='代码生成表';
|
) ENGINE = InnoDB
|
||||||
|
DEFAULT CHARSET = utf8 COMMENT ='代码生成表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_gen_table
|
-- Records of sys_gen_table
|
||||||
@ -1225,7 +1257,8 @@ CREATE TABLE `sys_gen_table_column`
|
|||||||
`options` varchar(1000) DEFAULT NULL COMMENT '其它生成选项',
|
`options` varchar(1000) DEFAULT NULL COMMENT '其它生成选项',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `idx_gen_table_column_tn` (`table_id`) USING BTREE
|
KEY `idx_gen_table_column_tn` (`table_id`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='代码生成表列';
|
) ENGINE = InnoDB
|
||||||
|
DEFAULT CHARSET = utf8 COMMENT ='代码生成表列';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_gen_table_column
|
-- Records of sys_gen_table_column
|
||||||
@ -1247,7 +1280,9 @@ CREATE TABLE `sys_log`
|
|||||||
`ip` varchar(64) DEFAULT NULL COMMENT 'IP地址',
|
`ip` varchar(64) DEFAULT NULL COMMENT 'IP地址',
|
||||||
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
|
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1412 DEFAULT CHARSET=utf8 COMMENT='系统日志';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 1412
|
||||||
|
DEFAULT CHARSET = utf8 COMMENT ='系统日志';
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
@ -1267,7 +1302,9 @@ CREATE TABLE `sys_menu`
|
|||||||
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
|
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
|
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
|
||||||
PRIMARY KEY (`menu_id`)
|
PRIMARY KEY (`menu_id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=234 DEFAULT CHARSET=utf8 COMMENT='菜单管理';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 234
|
||||||
|
DEFAULT CHARSET = utf8 COMMENT ='菜单管理';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_menu
|
-- Records of sys_menu
|
||||||
@ -1417,7 +1454,9 @@ CREATE TABLE `sys_role`
|
|||||||
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
|
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
`gmt_modified` datetime DEFAULT NULL COMMENT '创建时间',
|
`gmt_modified` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
PRIMARY KEY (`role_id`)
|
PRIMARY KEY (`role_id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=62 DEFAULT CHARSET=utf8 COMMENT='角色';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 62
|
||||||
|
DEFAULT CHARSET = utf8 COMMENT ='角色';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_role
|
-- Records of sys_role
|
||||||
@ -1435,7 +1474,9 @@ CREATE TABLE `sys_role_data_perm`
|
|||||||
`role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',
|
`role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',
|
||||||
`perm_id` bigint(20) DEFAULT NULL COMMENT '权限ID',
|
`perm_id` bigint(20) DEFAULT NULL COMMENT '权限ID',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=79 DEFAULT CHARSET=utf8 COMMENT='角色与数据权限对应关系';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 79
|
||||||
|
DEFAULT CHARSET = utf8 COMMENT ='角色与数据权限对应关系';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_role_data_perm
|
-- Records of sys_role_data_perm
|
||||||
@ -1473,7 +1514,9 @@ CREATE TABLE `sys_role_menu`
|
|||||||
`role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',
|
`role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',
|
||||||
`menu_id` bigint(20) DEFAULT NULL COMMENT '菜单ID',
|
`menu_id` bigint(20) DEFAULT NULL COMMENT '菜单ID',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=4830 DEFAULT CHARSET=utf8 COMMENT='角色与菜单对应关系';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 4830
|
||||||
|
DEFAULT CHARSET = utf8 COMMENT ='角色与菜单对应关系';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_role_menu
|
-- Records of sys_role_menu
|
||||||
@ -2255,7 +2298,9 @@ CREATE TABLE `sys_user`
|
|||||||
`city` varchar(255) DEFAULT NULL COMMENT '所在城市',
|
`city` varchar(255) DEFAULT NULL COMMENT '所在城市',
|
||||||
`district` varchar(255) DEFAULT NULL COMMENT '所在地区',
|
`district` varchar(255) DEFAULT NULL COMMENT '所在地区',
|
||||||
PRIMARY KEY (`user_id`)
|
PRIMARY KEY (`user_id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=139 DEFAULT CHARSET=utf8;
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 139
|
||||||
|
DEFAULT CHARSET = utf8;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_user
|
-- Records of sys_user
|
||||||
@ -2275,7 +2320,9 @@ CREATE TABLE `sys_user_role`
|
|||||||
`user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
|
`user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
|
||||||
`role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',
|
`role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=137 DEFAULT CHARSET=utf8 COMMENT='用户与角色对应关系';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 137
|
||||||
|
DEFAULT CHARSET = utf8 COMMENT ='用户与角色对应关系';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_user_role
|
-- Records of sys_user_role
|
||||||
@ -2367,7 +2414,9 @@ CREATE TABLE `user`
|
|||||||
`update_time` datetime NOT NULL COMMENT '更新时间',
|
`update_time` datetime NOT NULL COMMENT '更新时间',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_username` (`username`) USING BTREE
|
UNIQUE KEY `key_uq_username` (`username`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1255664783722586113 DEFAULT CHARSET=utf8mb4;
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 1255664783722586113
|
||||||
|
DEFAULT CHARSET = utf8mb4;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of user
|
-- Records of user
|
||||||
@ -2408,7 +2457,9 @@ CREATE TABLE `user_bookshelf`
|
|||||||
`update_time` datetime DEFAULT NULL,
|
`update_time` datetime DEFAULT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_userid_bookid` (`user_id`, `book_id`) USING BTREE
|
UNIQUE KEY `key_uq_userid_bookid` (`user_id`, `book_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=utf8mb4 COMMENT='用户书架表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 42
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='用户书架表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of user_bookshelf
|
-- Records of user_bookshelf
|
||||||
@ -2441,7 +2492,9 @@ CREATE TABLE `user_buy_record`
|
|||||||
`create_time` datetime DEFAULT NULL COMMENT '购买时间',
|
`create_time` datetime DEFAULT NULL COMMENT '购买时间',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_userId_indexId` (`user_id`, `book_index_id`)
|
UNIQUE KEY `key_userId_indexId` (`user_id`, `book_index_id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='用户消费记录表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 3
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='用户消费记录表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of user_buy_record
|
-- Records of user_buy_record
|
||||||
@ -2464,7 +2517,9 @@ CREATE TABLE `user_feedback`
|
|||||||
`content` varchar(512) DEFAULT NULL COMMENT '反馈内容',
|
`content` varchar(512) DEFAULT NULL COMMENT '反馈内容',
|
||||||
`create_time` datetime DEFAULT NULL COMMENT '反馈时间',
|
`create_time` datetime DEFAULT NULL COMMENT '反馈时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4;
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 9
|
||||||
|
DEFAULT CHARSET = utf8mb4;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of user_feedback
|
-- Records of user_feedback
|
||||||
@ -2486,7 +2541,9 @@ CREATE TABLE `user_read_history`
|
|||||||
`update_time` datetime DEFAULT NULL,
|
`update_time` datetime DEFAULT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_userid_bookid` (`user_id`, `book_id`) USING BTREE
|
UNIQUE KEY `key_uq_userid_bookid` (`user_id`, `book_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=119 DEFAULT CHARSET=utf8mb4 COMMENT='用户阅读记录表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 119
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='用户阅读记录表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of user_read_history
|
-- Records of user_read_history
|
||||||
@ -2552,7 +2609,9 @@ CREATE TABLE `book_content0`
|
|||||||
`content` mediumtext COMMENT '小说章节内容',
|
`content` mediumtext COMMENT '小说章节内容',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1155 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 1155
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说内容表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for book_content1
|
-- Table structure for book_content1
|
||||||
@ -2565,7 +2624,9 @@ CREATE TABLE `book_content1`
|
|||||||
`content` mediumtext COMMENT '小说章节内容',
|
`content` mediumtext COMMENT '小说章节内容',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=406 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 406
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说内容表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for book_content2
|
-- Table structure for book_content2
|
||||||
@ -2578,7 +2639,9 @@ CREATE TABLE `book_content2`
|
|||||||
`content` mediumtext COMMENT '小说章节内容',
|
`content` mediumtext COMMENT '小说章节内容',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1222 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 1222
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说内容表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for book_content3
|
-- Table structure for book_content3
|
||||||
@ -2591,7 +2654,9 @@ CREATE TABLE `book_content3`
|
|||||||
`content` mediumtext COMMENT '小说章节内容',
|
`content` mediumtext COMMENT '小说章节内容',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=410 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 410
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说内容表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for book_content4
|
-- Table structure for book_content4
|
||||||
@ -2604,7 +2669,9 @@ CREATE TABLE `book_content4`
|
|||||||
`content` mediumtext COMMENT '小说章节内容',
|
`content` mediumtext COMMENT '小说章节内容',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1188 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 1188
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说内容表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for book_content5
|
-- Table structure for book_content5
|
||||||
@ -2617,7 +2684,9 @@ CREATE TABLE `book_content5`
|
|||||||
`content` mediumtext COMMENT '小说章节内容',
|
`content` mediumtext COMMENT '小说章节内容',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=416 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 416
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说内容表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for book_content6
|
-- Table structure for book_content6
|
||||||
@ -2630,7 +2699,9 @@ CREATE TABLE `book_content6`
|
|||||||
`content` mediumtext COMMENT '小说章节内容',
|
`content` mediumtext COMMENT '小说章节内容',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1180 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 1180
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说内容表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for book_content7
|
-- Table structure for book_content7
|
||||||
@ -2643,7 +2714,9 @@ CREATE TABLE `book_content7`
|
|||||||
`content` mediumtext COMMENT '小说章节内容',
|
`content` mediumtext COMMENT '小说章节内容',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=404 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 404
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说内容表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for book_content8
|
-- Table structure for book_content8
|
||||||
@ -2656,7 +2729,9 @@ CREATE TABLE `book_content8`
|
|||||||
`content` mediumtext COMMENT '小说章节内容',
|
`content` mediumtext COMMENT '小说章节内容',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1134 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 1134
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说内容表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for book_content9
|
-- Table structure for book_content9
|
||||||
@ -2669,7 +2744,9 @@ CREATE TABLE `book_content9`
|
|||||||
`content` mediumtext COMMENT '小说章节内容',
|
`content` mediumtext COMMENT '小说章节内容',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=415 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 415
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='小说内容表';
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `crawl_single_task`;
|
DROP TABLE IF EXISTS `crawl_single_task`;
|
||||||
@ -2686,7 +2763,9 @@ CREATE TABLE `crawl_single_task`
|
|||||||
`exc_count` tinyint(2) DEFAULT '0' COMMENT '已经执行次数,最多执行5次',
|
`exc_count` tinyint(2) DEFAULT '0' COMMENT '已经执行次数,最多执行5次',
|
||||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COMMENT='抓取单本小说任务表';
|
) ENGINE = InnoDB
|
||||||
|
AUTO_INCREMENT = 8
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='抓取单本小说任务表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of crawl_single_task
|
-- Records of crawl_single_task
|
||||||
@ -2716,7 +2795,8 @@ CREATE TABLE `author_income_detail`
|
|||||||
`income_number` int(11) NOT NULL DEFAULT '0' COMMENT '订阅人数',
|
`income_number` int(11) NOT NULL DEFAULT '0' COMMENT '订阅人数',
|
||||||
`create_time` datetime DEFAULT NULL,
|
`create_time` datetime DEFAULT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='稿费收入明细统计表';
|
) ENGINE = InnoDB
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='稿费收入明细统计表';
|
||||||
|
|
||||||
CREATE TABLE `author_income`
|
CREATE TABLE `author_income`
|
||||||
(
|
(
|
||||||
@ -2732,7 +2812,8 @@ CREATE TABLE `author_income`
|
|||||||
`detail` varchar(255) DEFAULT NULL COMMENT '详情',
|
`detail` varchar(255) DEFAULT NULL COMMENT '详情',
|
||||||
`create_time` datetime DEFAULT NULL,
|
`create_time` datetime DEFAULT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='稿费收入统计表';
|
) ENGINE = InnoDB
|
||||||
|
DEFAULT CHARSET = utf8mb4 COMMENT ='稿费收入统计表';
|
||||||
|
|
||||||
|
|
||||||
alter table book
|
alter table book
|
||||||
@ -3006,3 +3087,58 @@ INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`,
|
|||||||
VALUES (305, '301', '修改', null, 'novel:websiteInfo:edit', '2', null, '6');
|
VALUES (305, '301', '修改', null, 'novel:websiteInfo:edit', '2', null, '6');
|
||||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||||
VALUES (1, 305);
|
VALUES (1, 305);
|
||||||
|
|
||||||
|
|
||||||
|
update website_info
|
||||||
|
set logo = 'https://youdoc.gitee.io/resource/images/logo%20(1).png',
|
||||||
|
logo_dark='https://youdoc.gitee.io/resource/images/logo%20(1).png'
|
||||||
|
where id = 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
update crawl_source
|
||||||
|
set crawl_rule = replace(crawl_rule, 'ibiquge.net', 'ibiquzw.org')
|
||||||
|
where id = 16;
|
||||||
|
|
||||||
|
update website_info
|
||||||
|
set logo = '/images/logo.png',
|
||||||
|
logo_dark='/images/logo.png'
|
||||||
|
where id = 1;
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO crawl_source (source_name, crawl_rule, source_status, create_time, update_time)
|
||||||
|
VALUES ('香书小说网', '{
|
||||||
|
"bookListUrl": "http://www.xbiqugu.net/fenlei/{catId}_{page}.html",
|
||||||
|
"catIdRule": {
|
||||||
|
"catId1": "1",
|
||||||
|
"catId2": "2",
|
||||||
|
"catId3": "3",
|
||||||
|
"catId4": "4",
|
||||||
|
"catId5": "6",
|
||||||
|
"catId6": "5"
|
||||||
|
},
|
||||||
|
"bookIdPatten": "<a\\\\s+href=\\"http://www.xbiqugu.net/(\\\\d+/\\\\d+)/\\"\\\\s+target=\\"_blank\\">",
|
||||||
|
"pagePatten": "<em\\\\s+id=\\"pagestats\\">(\\\\d+)/\\\\d+</em>",
|
||||||
|
"totalPagePatten": "<em\\\\s+id=\\"pagestats\\">\\\\d+/(\\\\d+)</em>",
|
||||||
|
"bookDetailUrl": "http://www.xbiqugu.net/{bookId}/",
|
||||||
|
"bookNamePatten": "<h1>([^/]+)</h1>",
|
||||||
|
"authorNamePatten": "者:([^/]+)</p>",
|
||||||
|
"picUrlPatten": "src=\\"(http://www.xbiqugu.net/files/article/image/\\\\d+/\\\\d+/\\\\d+s\\\\.jpg)\\"",
|
||||||
|
"bookStatusRule": {},
|
||||||
|
"descStart": "<div id=\\"intro\\">",
|
||||||
|
"descEnd": "</div>",
|
||||||
|
"upadateTimePatten": "<p>最后更新:(\\\\d+-\\\\d+-\\\\d+\\\\s\\\\d+:\\\\d+:\\\\d+)</p>",
|
||||||
|
"upadateTimeFormatPatten": "yyyy-MM-dd HH:mm:ss",
|
||||||
|
"bookIndexUrl": "http://www.xbiqugu.net/{bookId}/",
|
||||||
|
"indexIdPatten": "<a\\\\s+href=''/\\\\d+/\\\\d+/(\\\\d+)\\\\.html''\\\\s+>[^/]+</a>",
|
||||||
|
"indexNamePatten": "<a\\\\s+href=''/\\\\d+/\\\\d+/\\\\d+\\\\.html''\\\\s+>([^/]+)</a>",
|
||||||
|
"bookContentUrl": "http://www.xbiqugu.net/{bookId}/{indexId}.html",
|
||||||
|
"contentStart": "<div id=\\"content\\">",
|
||||||
|
"contentEnd": "<p>",
|
||||||
|
"filterContent":"<div\\\\s+id=\\"content_tip\\">\\\\s*<b>([^/]+)</b>\\\\s*</div>"
|
||||||
|
}', 0, '2024-06-01 10:11:39', '2024-06-01 10:11:39');
|
||||||
|
|
||||||
|
|
||||||
|
update crawl_source
|
||||||
|
set crawl_rule = replace(crawl_rule, 'ibiquzw.org', 'biquxs.info')
|
||||||
|
where id = 16;
|
@ -1,6 +0,0 @@
|
|||||||
FROM java:8
|
|
||||||
ADD novel-admin-1.0.0.jar /root
|
|
||||||
ENV dburl=""
|
|
||||||
ENV username=""
|
|
||||||
ENV password=""
|
|
||||||
ENTRYPOINT ["sh","-c","java -Dspring.datasource.url=${dburl} -Dspring.datasource.username=${username} -Dspring.datasource.password=${password} -jar /root/novel-admin-1.0.0.jar"]
|
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<groupId>com.java2nb</groupId>
|
<groupId>com.java2nb</groupId>
|
||||||
<artifactId>novel-admin</artifactId>
|
<artifactId>novel-admin</artifactId>
|
||||||
<version>4.2.0</version>
|
<version>4.4.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>novel-admin</name>
|
<name>novel-admin</name>
|
||||||
@ -296,6 +296,9 @@
|
|||||||
<zip destfile='${project.build.directory}/build/${project.artifactId}.zip'>
|
<zip destfile='${project.build.directory}/build/${project.artifactId}.zip'>
|
||||||
<zipfileset filemode="755" dir='${project.build.directory}/build/'/>
|
<zipfileset filemode="755" dir='${project.build.directory}/build/'/>
|
||||||
</zip>
|
</zip>
|
||||||
|
|
||||||
|
<copy file="${basedir}/src/main/build/docker/Dockerfile"
|
||||||
|
tofile="${project.build.directory}/build/Dockerfile"/>
|
||||||
</tasks>
|
</tasks>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
|
9
novel-admin/src/main/build/docker/Dockerfile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
FROM openjdk:8
|
||||||
|
ADD novel-admin.jar /root
|
||||||
|
ENV dburl=""
|
||||||
|
ENV username=""
|
||||||
|
ENV password=""
|
||||||
|
ENV redishost = ""
|
||||||
|
ENV redisport = ""
|
||||||
|
ENV redispwd = ""
|
||||||
|
ENTRYPOINT ["sh","-c","java -Dspring.datasource.url=${dburl} -Dspring.datasource.username=${username} -Dspring.datasource.password=${password} -Dspring.redis.host=${redishost} -Dspring.redis.port=${redisport} -Dspring.redis.password=${redispwd} -jar /root/novel-admin.jar"]
|
@ -68,6 +68,7 @@ public class ShiroConfig {
|
|||||||
filterChainDefinitionMap.put("/js/**", "anon");
|
filterChainDefinitionMap.put("/js/**", "anon");
|
||||||
filterChainDefinitionMap.put("/fonts/**", "anon");
|
filterChainDefinitionMap.put("/fonts/**", "anon");
|
||||||
filterChainDefinitionMap.put("/img/**", "anon");
|
filterChainDefinitionMap.put("/img/**", "anon");
|
||||||
|
filterChainDefinitionMap.put("/favicon.ico", "anon");
|
||||||
filterChainDefinitionMap.put("/docs/**", "anon");
|
filterChainDefinitionMap.put("/docs/**", "anon");
|
||||||
filterChainDefinitionMap.put("/layuimini/**", "anon");
|
filterChainDefinitionMap.put("/layuimini/**", "anon");
|
||||||
filterChainDefinitionMap.put("/upload/**", "anon");
|
filterChainDefinitionMap.put("/upload/**", "anon");
|
||||||
|
@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -83,7 +84,7 @@ public class FriendLinkController {
|
|||||||
@ResponseBody
|
@ResponseBody
|
||||||
@PostMapping("/save")
|
@PostMapping("/save")
|
||||||
@RequiresPermissions("novel:friendLink:add")
|
@RequiresPermissions("novel:friendLink:add")
|
||||||
public R save(FriendLinkDO friendLink) {
|
public R save(@Validated FriendLinkDO friendLink) {
|
||||||
if (friendLinkService.save(friendLink) > 0) {
|
if (friendLinkService.save(friendLink) > 0) {
|
||||||
redisTemplate.delete(CacheKey.INDEX_LINK_KEY);
|
redisTemplate.delete(CacheKey.INDEX_LINK_KEY);
|
||||||
return R.ok();
|
return R.ok();
|
||||||
@ -98,7 +99,7 @@ public class FriendLinkController {
|
|||||||
@ResponseBody
|
@ResponseBody
|
||||||
@RequestMapping("/update")
|
@RequestMapping("/update")
|
||||||
@RequiresPermissions("novel:friendLink:edit")
|
@RequiresPermissions("novel:friendLink:edit")
|
||||||
public R update(FriendLinkDO friendLink) {
|
public R update(@Validated FriendLinkDO friendLink) {
|
||||||
friendLinkService.update(friendLink);
|
friendLinkService.update(friendLink);
|
||||||
redisTemplate.delete(CacheKey.INDEX_LINK_KEY);
|
redisTemplate.delete(CacheKey.INDEX_LINK_KEY);
|
||||||
return R.ok();
|
return R.ok();
|
||||||
|
@ -1,27 +1,21 @@
|
|||||||
package com.java2nb.novel.domain;
|
package com.java2nb.novel.domain;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
import com.java2nb.common.jsonserializer.LongToStringSerializer;
|
import com.java2nb.common.jsonserializer.LongToStringSerializer;
|
||||||
|
import org.hibernate.validator.constraints.URL;
|
||||||
|
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author xiongxy
|
* @author xiongxy
|
||||||
* @email 1179705413@qq.com
|
* @email 1179705413@qq.com
|
||||||
* @date 2023-04-14 15:12:25
|
* @date 2023-04-14 15:12:25
|
||||||
*/
|
*/
|
||||||
public class FriendLinkDO implements Serializable {
|
public class FriendLinkDO implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|
||||||
@ -30,6 +24,7 @@ public class FriendLinkDO implements Serializable {
|
|||||||
//链接名
|
//链接名
|
||||||
private String linkName;
|
private String linkName;
|
||||||
//链接url
|
//链接url
|
||||||
|
@URL
|
||||||
private String linkUrl;
|
private String linkUrl;
|
||||||
//排序号
|
//排序号
|
||||||
private Integer sort;
|
private Integer sort;
|
||||||
@ -58,102 +53,119 @@ public class FriendLinkDO implements Serializable {
|
|||||||
public void setId(Integer id) {
|
public void setId(Integer id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取:主键
|
* 获取:主键
|
||||||
*/
|
*/
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置:链接名
|
* 设置:链接名
|
||||||
*/
|
*/
|
||||||
public void setLinkName(String linkName) {
|
public void setLinkName(String linkName) {
|
||||||
this.linkName = linkName;
|
this.linkName = linkName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取:链接名
|
* 获取:链接名
|
||||||
*/
|
*/
|
||||||
public String getLinkName() {
|
public String getLinkName() {
|
||||||
return linkName;
|
return linkName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置:链接url
|
* 设置:链接url
|
||||||
*/
|
*/
|
||||||
public void setLinkUrl(String linkUrl) {
|
public void setLinkUrl(String linkUrl) {
|
||||||
this.linkUrl = linkUrl;
|
this.linkUrl = linkUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取:链接url
|
* 获取:链接url
|
||||||
*/
|
*/
|
||||||
public String getLinkUrl() {
|
public String getLinkUrl() {
|
||||||
return linkUrl;
|
return linkUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置:排序号
|
* 设置:排序号
|
||||||
*/
|
*/
|
||||||
public void setSort(Integer sort) {
|
public void setSort(Integer sort) {
|
||||||
this.sort = sort;
|
this.sort = sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取:排序号
|
* 获取:排序号
|
||||||
*/
|
*/
|
||||||
public Integer getSort() {
|
public Integer getSort() {
|
||||||
return sort;
|
return sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置:是否开启,0:不开启,1:开启
|
* 设置:是否开启,0:不开启,1:开启
|
||||||
*/
|
*/
|
||||||
public void setIsOpen(Integer isOpen) {
|
public void setIsOpen(Integer isOpen) {
|
||||||
this.isOpen = isOpen;
|
this.isOpen = isOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取:是否开启,0:不开启,1:开启
|
* 获取:是否开启,0:不开启,1:开启
|
||||||
*/
|
*/
|
||||||
public Integer getIsOpen() {
|
public Integer getIsOpen() {
|
||||||
return isOpen;
|
return isOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置:创建人id
|
* 设置:创建人id
|
||||||
*/
|
*/
|
||||||
public void setCreateUserId(Long createUserId) {
|
public void setCreateUserId(Long createUserId) {
|
||||||
this.createUserId = createUserId;
|
this.createUserId = createUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取:创建人id
|
* 获取:创建人id
|
||||||
*/
|
*/
|
||||||
public Long getCreateUserId() {
|
public Long getCreateUserId() {
|
||||||
return createUserId;
|
return createUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置:创建时间
|
* 设置:创建时间
|
||||||
*/
|
*/
|
||||||
public void setCreateTime(Date createTime) {
|
public void setCreateTime(Date createTime) {
|
||||||
this.createTime = createTime;
|
this.createTime = createTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取:创建时间
|
* 获取:创建时间
|
||||||
*/
|
*/
|
||||||
public Date getCreateTime() {
|
public Date getCreateTime() {
|
||||||
return createTime;
|
return createTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置:更新者用户id
|
* 设置:更新者用户id
|
||||||
*/
|
*/
|
||||||
public void setUpdateUserId(Long updateUserId) {
|
public void setUpdateUserId(Long updateUserId) {
|
||||||
this.updateUserId = updateUserId;
|
this.updateUserId = updateUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取:更新者用户id
|
* 获取:更新者用户id
|
||||||
*/
|
*/
|
||||||
public Long getUpdateUserId() {
|
public Long getUpdateUserId() {
|
||||||
return updateUserId;
|
return updateUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置:更新时间
|
* 设置:更新时间
|
||||||
*/
|
*/
|
||||||
public void setUpdateTime(Date updateTime) {
|
public void setUpdateTime(Date updateTime) {
|
||||||
this.updateTime = updateTime;
|
this.updateTime = updateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取:更新时间
|
* 获取:更新时间
|
||||||
*/
|
*/
|
||||||
|
@ -18,10 +18,11 @@ spring:
|
|||||||
profiles:
|
profiles:
|
||||||
active: dev
|
active: dev
|
||||||
|
|
||||||
#上传文件的最大值(10M)
|
#上传文件的最大值(100M)
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
max-file-size: 10485760
|
max-file-size: 100MB
|
||||||
|
max-request-size: 100MB
|
||||||
|
|
||||||
devtools:
|
devtools:
|
||||||
restart:
|
restart:
|
||||||
|
BIN
novel-admin/src/main/resources/favicon.ico
Normal file
After Width: | Height: | Size: 162 KiB |
Before Width: | Height: | Size: 8.9 KiB |
@ -23,7 +23,7 @@
|
|||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<input id="linkUrl" name="linkUrl"
|
<input id="linkUrl" name="linkUrl"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
type="text" required>
|
type="url" required>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<input id="linkUrl" name="linkUrl"
|
<input id="linkUrl" name="linkUrl"
|
||||||
th:value="${friendLink.linkUrl}"
|
th:value="${friendLink.linkUrl}"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
type="text" required>
|
type="url" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>novel</artifactId>
|
<artifactId>novel</artifactId>
|
||||||
<groupId>com.java2nb</groupId>
|
<groupId>com.java2nb</groupId>
|
||||||
<version>4.2.0</version>
|
<version>4.4.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -14,7 +14,10 @@ import org.springframework.http.ResponseEntity;
|
|||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -37,10 +40,13 @@ public class FileUtil {
|
|||||||
//本地图片保存
|
//本地图片保存
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
|
HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
|
||||||
ResponseEntity<Resource> resEntity = RestTemplateUtil.getInstance(Charsets.ISO_8859_1.name()).exchange(picSrc, HttpMethod.GET, requestEntity, Resource.class);
|
ResponseEntity<Resource> resEntity = RestTemplates.newInstance(Charsets.ISO_8859_1.name())
|
||||||
|
.exchange(picSrc, HttpMethod.GET, requestEntity, Resource.class);
|
||||||
input = Objects.requireNonNull(resEntity.getBody()).getInputStream();
|
input = Objects.requireNonNull(resEntity.getBody()).getInputStream();
|
||||||
Date currentDate = new Date();
|
Date currentDate = new Date();
|
||||||
picSrc = visitPrefix + DateUtils.formatDate(currentDate, "yyyy") + "/" + DateUtils.formatDate(currentDate, "MM") + "/" + DateUtils.formatDate(currentDate, "dd") + "/"
|
picSrc =
|
||||||
|
visitPrefix + DateUtils.formatDate(currentDate, "yyyy") + "/" + DateUtils.formatDate(currentDate, "MM")
|
||||||
|
+ "/" + DateUtils.formatDate(currentDate, "dd") + "/"
|
||||||
+ UUIDUtil.getUUID32()
|
+ UUIDUtil.getUUID32()
|
||||||
+ picSrc.substring(picSrc.lastIndexOf("."));
|
+ picSrc.substring(picSrc.lastIndexOf("."));
|
||||||
File picFile = new File(picSavePath + picSrc);
|
File picFile = new File(picSavePath + picSrc);
|
||||||
@ -67,7 +73,6 @@ public class FileUtil {
|
|||||||
closeStream(input, out);
|
closeStream(input, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return picSrc;
|
return picSrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,38 +1,24 @@
|
|||||||
package com.java2nb.novel.core.utils;
|
package com.java2nb.novel.core.utils;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.*;
|
import org.springframework.http.*;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Administrator
|
* @author Administrator
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class HttpUtil {
|
public class HttpUtil {
|
||||||
|
|
||||||
private static RestTemplate restTemplate = RestTemplateUtil.getInstance("utf-8");
|
private static final RestTemplate REST_TEMPLATE = RestTemplates.newInstance("utf-8");
|
||||||
|
|
||||||
|
|
||||||
public static String getByHttpClient(String url) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
|
|
||||||
if (forEntity.getStatusCode() == HttpStatus.OK) {
|
|
||||||
return forEntity.getBody();
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getByHttpClientWithChrome(String url) {
|
public static String getByHttpClientWithChrome(String url) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
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");
|
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);
|
HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
|
||||||
ResponseEntity<String> forEntity = restTemplate.exchange(url.toString(), HttpMethod.GET, requestEntity, String.class);
|
ResponseEntity<String> forEntity = REST_TEMPLATE.exchange(url, HttpMethod.GET, requestEntity, String.class);
|
||||||
|
|
||||||
if (forEntity.getStatusCode() == HttpStatus.OK) {
|
if (forEntity.getStatusCode() == HttpStatus.OK) {
|
||||||
return forEntity.getBody();
|
return forEntity.getBody();
|
||||||
@ -40,8 +26,9 @@ public class HttpUtil {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
log.error(e.getMessage(), e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,16 +26,16 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class RestTemplateUtil {
|
public class RestTemplates {
|
||||||
|
|
||||||
private static HttpProxyProperties httpProxyProperties;
|
private static HttpProxyProperties httpProxyProperties;
|
||||||
|
|
||||||
RestTemplateUtil(HttpProxyProperties properties) {
|
RestTemplates(HttpProxyProperties properties) {
|
||||||
httpProxyProperties = properties;
|
httpProxyProperties = properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static RestTemplate getInstance(String charset) {
|
public static RestTemplate newInstance(String charset) {
|
||||||
|
|
||||||
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
|
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
|
||||||
|
|
@ -16,6 +16,7 @@ public class User {
|
|||||||
|
|
||||||
@NotBlank(groups = {AddGroup.class}, message = "手机号不能为空!")
|
@NotBlank(groups = {AddGroup.class}, message = "手机号不能为空!")
|
||||||
@Pattern(groups = {AddGroup.class}, regexp = "^1[3|4|5|6|7|8|9][0-9]{9}$", message = "手机号格式不正确!")
|
@Pattern(groups = {AddGroup.class}, regexp = "^1[3|4|5|6|7|8|9][0-9]{9}$", message = "手机号格式不正确!")
|
||||||
|
@Null(groups = {UpdateGroup.class})
|
||||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
@ -25,10 +26,14 @@ public class User {
|
|||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@Null(groups = {AddGroup.class})
|
@Null(groups = {AddGroup.class})
|
||||||
|
@Pattern(groups = {
|
||||||
|
UpdateGroup.class}, regexp = "[\u4E00-\u9FA5A-Za-z0-9_]{1,11}", message = "昵称格式不正确!")
|
||||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||||
private String nickName;
|
private String nickName;
|
||||||
|
|
||||||
@Null(groups = {AddGroup.class})
|
@Null(groups = {AddGroup.class})
|
||||||
|
@Pattern(groups = {
|
||||||
|
UpdateGroup.class}, regexp = "^/localPic/\\d{4}/\\d{2}/\\d{2}/[A-Za-z0-9]+\\.(jpg|jpeg|swf|gif|png|JPG|JPEG|SWF|GIF|PNG)$", message = "只能上传图片格式的文件!")
|
||||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||||
private String userPhoto;
|
private String userPhoto;
|
||||||
|
|
||||||
|
@ -11,10 +11,11 @@ spring:
|
|||||||
generator:
|
generator:
|
||||||
write-numbers-as-strings: true
|
write-numbers-as-strings: true
|
||||||
|
|
||||||
#上传文件的最大值(1M)
|
#上传文件的最大值(100M)
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
max-file-size: 1048576
|
max-file-size: 100MB
|
||||||
|
max-request-size: 100MB
|
||||||
|
|
||||||
mybatis:
|
mybatis:
|
||||||
configuration:
|
configuration:
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
FROM java:8
|
|
||||||
ADD novel-crawl-1.1.0.jar /root
|
|
||||||
ENV dburl=""
|
|
||||||
ENV username=""
|
|
||||||
ENV password=""
|
|
||||||
ENTRYPOINT ["sh","-c","java -Dspring.datasource.url=${dburl} -Dspring.datasource.username=${username} -Dspring.datasource.password=${password} -jar /root/novel-crawl-1.1.0.jar"]
|
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>novel</artifactId>
|
<artifactId>novel</artifactId>
|
||||||
<groupId>com.java2nb</groupId>
|
<groupId>com.java2nb</groupId>
|
||||||
<version>4.2.0</version>
|
<version>4.4.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@ -72,6 +72,9 @@
|
|||||||
<zip destfile='${project.build.directory}/build/${project.artifactId}.zip'>
|
<zip destfile='${project.build.directory}/build/${project.artifactId}.zip'>
|
||||||
<zipfileset filemode="755" dir='${project.build.directory}/build/'/>
|
<zipfileset filemode="755" dir='${project.build.directory}/build/'/>
|
||||||
</zip>
|
</zip>
|
||||||
|
|
||||||
|
<copy file="${basedir}/src/main/build/docker/Dockerfile"
|
||||||
|
tofile="${project.build.directory}/build/Dockerfile"/>
|
||||||
</tasks>
|
</tasks>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
|
9
novel-crawl/src/main/build/docker/Dockerfile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
FROM openjdk:8
|
||||||
|
ADD novel-crawl.jar /root
|
||||||
|
ENV dburl=""
|
||||||
|
ENV username=""
|
||||||
|
ENV password=""
|
||||||
|
ENV redishost = ""
|
||||||
|
ENV redisport = ""
|
||||||
|
ENV redispwd = ""
|
||||||
|
ENTRYPOINT ["sh","-c","java -Dspring.datasource.url=${dburl} -Dspring.datasource.username=${username} -Dspring.datasource.password=${password} -Dspring.redis.host=${redishost} -Dspring.redis.port=${redisport} -Dspring.redis.password=${redispwd} -jar /root/novel-crawl.jar"]
|
@ -53,8 +53,12 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||||||
http.csrf().disable()
|
http.csrf().disable()
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
.antMatchers("/css/**").permitAll()
|
.antMatchers("/css/**").permitAll()
|
||||||
|
.antMatchers("/favicon.ico").permitAll()
|
||||||
.antMatchers("/**").hasRole("ADMIN")
|
.antMatchers("/**").hasRole("ADMIN")
|
||||||
.and().formLogin().loginPage("/login.html").loginProcessingUrl("/login").permitAll()
|
.and().formLogin().loginPage("/login.html").loginProcessingUrl("/login").permitAll()
|
||||||
|
.and().logout()
|
||||||
|
.logoutUrl("/logout")
|
||||||
|
.logoutSuccessUrl("/")
|
||||||
.and().httpBasic();
|
.and().httpBasic();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
package com.java2nb.novel.core.crawl;
|
package com.java2nb.novel.core.crawl;
|
||||||
|
|
||||||
import com.java2nb.novel.core.utils.HttpUtil;
|
|
||||||
import com.java2nb.novel.core.utils.RandomBookInfoUtil;
|
import com.java2nb.novel.core.utils.RandomBookInfoUtil;
|
||||||
import com.java2nb.novel.core.utils.RestTemplateUtil;
|
|
||||||
import com.java2nb.novel.core.utils.StringUtil;
|
import com.java2nb.novel.core.utils.StringUtil;
|
||||||
import com.java2nb.novel.entity.Book;
|
import com.java2nb.novel.entity.Book;
|
||||||
import com.java2nb.novel.entity.BookContent;
|
import com.java2nb.novel.entity.BookContent;
|
||||||
import com.java2nb.novel.entity.BookIndex;
|
import com.java2nb.novel.entity.BookIndex;
|
||||||
import com.java2nb.novel.utils.Constants;
|
import com.java2nb.novel.utils.Constants;
|
||||||
|
import com.java2nb.novel.utils.CrawlHttpClient;
|
||||||
import io.github.xxyopen.util.IdWorker;
|
import io.github.xxyopen.util.IdWorker;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -26,20 +26,19 @@ import java.util.regex.Pattern;
|
|||||||
*
|
*
|
||||||
* @author Administrator
|
* @author Administrator
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class CrawlParser {
|
public class CrawlParser {
|
||||||
|
|
||||||
private static final IdWorker idWorker = IdWorker.INSTANCE;
|
private final IdWorker ID_WORKER = IdWorker.INSTANCE;
|
||||||
|
|
||||||
private static final RestTemplate restTemplate = RestTemplateUtil.getInstance("utf-8");
|
private final CrawlHttpClient crawlHttpClient;
|
||||||
|
|
||||||
private static final ThreadLocal<Integer> retryCount = new ThreadLocal<>();
|
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static void parseBook(RuleBean ruleBean, String bookId, CrawlBookHandler handler) {
|
public void parseBook(RuleBean ruleBean, String bookId, CrawlBookHandler handler) {
|
||||||
Book book = new Book();
|
Book book = new Book();
|
||||||
String bookDetailUrl = ruleBean.getBookDetailUrl().replace("{bookId}", bookId);
|
String bookDetailUrl = ruleBean.getBookDetailUrl().replace("{bookId}", bookId);
|
||||||
String bookDetailHtml = getByHttpClientWithChrome(bookDetailUrl);
|
String bookDetailHtml = crawlHttpClient.get(bookDetailUrl);
|
||||||
if (bookDetailHtml != null) {
|
if (bookDetailHtml != null) {
|
||||||
Pattern bookNamePatten = PatternFactory.getPattern(ruleBean.getBookNamePatten());
|
Pattern bookNamePatten = PatternFactory.getPattern(ruleBean.getBookNamePatten());
|
||||||
Matcher bookNameMatch = bookNamePatten.matcher(bookDetailHtml);
|
Matcher bookNameMatch = bookNamePatten.matcher(bookDetailHtml);
|
||||||
@ -89,7 +88,8 @@ public class CrawlParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String desc = bookDetailHtml.substring(bookDetailHtml.indexOf(ruleBean.getDescStart()) + ruleBean.getDescStart().length());
|
String desc = bookDetailHtml.substring(
|
||||||
|
bookDetailHtml.indexOf(ruleBean.getDescStart()) + ruleBean.getDescStart().length());
|
||||||
desc = desc.substring(0, desc.indexOf(ruleBean.getDescEnd()));
|
desc = desc.substring(0, desc.indexOf(ruleBean.getDescEnd()));
|
||||||
//过滤掉简介中的特殊标签
|
//过滤掉简介中的特殊标签
|
||||||
desc = desc.replaceAll("<a[^<]+</a>", "")
|
desc = desc.replaceAll("<a[^<]+</a>", "")
|
||||||
@ -112,14 +112,16 @@ public class CrawlParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(ruleBean.getUpadateTimePatten()) && StringUtils.isNotBlank(ruleBean.getUpadateTimeFormatPatten())) {
|
if (StringUtils.isNotBlank(ruleBean.getUpadateTimePatten()) && StringUtils.isNotBlank(
|
||||||
|
ruleBean.getUpadateTimeFormatPatten())) {
|
||||||
Pattern updateTimePatten = PatternFactory.getPattern(ruleBean.getUpadateTimePatten());
|
Pattern updateTimePatten = PatternFactory.getPattern(ruleBean.getUpadateTimePatten());
|
||||||
Matcher updateTimeMatch = updateTimePatten.matcher(bookDetailHtml);
|
Matcher updateTimeMatch = updateTimePatten.matcher(bookDetailHtml);
|
||||||
boolean isFindUpdateTime = updateTimeMatch.find();
|
boolean isFindUpdateTime = updateTimeMatch.find();
|
||||||
if (isFindUpdateTime) {
|
if (isFindUpdateTime) {
|
||||||
String updateTime = updateTimeMatch.group(1);
|
String updateTime = updateTimeMatch.group(1);
|
||||||
//设置更新时间
|
//设置更新时间
|
||||||
book.setLastIndexUpdateTime(new SimpleDateFormat(ruleBean.getUpadateTimeFormatPatten()).parse(updateTime));
|
book.setLastIndexUpdateTime(
|
||||||
|
new SimpleDateFormat(ruleBean.getUpadateTimeFormatPatten()).parse(updateTime));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +143,8 @@ public class CrawlParser {
|
|||||||
handler.handle(book);
|
handler.handle(book);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean parseBookIndexAndContent(String sourceBookId, Book book, RuleBean ruleBean, Map<Integer, BookIndex> existBookIndexMap, CrawlBookChapterHandler handler) {
|
public boolean parseBookIndexAndContent(String sourceBookId, Book book, RuleBean ruleBean,
|
||||||
|
Map<Integer, BookIndex> existBookIndexMap, CrawlBookChapterHandler handler) {
|
||||||
|
|
||||||
Date currentDate = new Date();
|
Date currentDate = new Date();
|
||||||
|
|
||||||
@ -149,11 +152,12 @@ public class CrawlParser {
|
|||||||
List<BookContent> contentList = new ArrayList<>();
|
List<BookContent> contentList = new ArrayList<>();
|
||||||
//读取目录
|
//读取目录
|
||||||
String indexListUrl = ruleBean.getBookIndexUrl().replace("{bookId}", sourceBookId);
|
String indexListUrl = ruleBean.getBookIndexUrl().replace("{bookId}", sourceBookId);
|
||||||
String indexListHtml = getByHttpClientWithChrome(indexListUrl);
|
String indexListHtml = crawlHttpClient.get(indexListUrl);
|
||||||
|
|
||||||
if (indexListHtml != null) {
|
if (indexListHtml != null) {
|
||||||
if (StringUtils.isNotBlank(ruleBean.getBookIndexStart())) {
|
if (StringUtils.isNotBlank(ruleBean.getBookIndexStart())) {
|
||||||
indexListHtml = indexListHtml.substring(indexListHtml.indexOf(ruleBean.getBookIndexStart()) + ruleBean.getBookIndexStart().length());
|
indexListHtml = indexListHtml.substring(
|
||||||
|
indexListHtml.indexOf(ruleBean.getBookIndexStart()) + ruleBean.getBookIndexStart().length());
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern indexIdPatten = PatternFactory.getPattern(ruleBean.getIndexIdPatten());
|
Pattern indexIdPatten = PatternFactory.getPattern(ruleBean.getIndexIdPatten());
|
||||||
@ -174,14 +178,16 @@ public class CrawlParser {
|
|||||||
BookIndex hasIndex = existBookIndexMap.get(indexNum);
|
BookIndex hasIndex = existBookIndexMap.get(indexNum);
|
||||||
String indexName = indexNameMatch.group(1);
|
String indexName = indexNameMatch.group(1);
|
||||||
|
|
||||||
if (hasIndex == null || !StringUtils.deleteWhitespace(hasIndex.getIndexName()).equals(StringUtils.deleteWhitespace(indexName))) {
|
if (hasIndex == null || !StringUtils.deleteWhitespace(hasIndex.getIndexName())
|
||||||
|
.equals(StringUtils.deleteWhitespace(indexName))) {
|
||||||
|
|
||||||
String sourceIndexId = indexIdMatch.group(1);
|
String sourceIndexId = indexIdMatch.group(1);
|
||||||
String bookContentUrl = ruleBean.getBookContentUrl();
|
String bookContentUrl = ruleBean.getBookContentUrl();
|
||||||
int calStart = bookContentUrl.indexOf("{cal_");
|
int calStart = bookContentUrl.indexOf("{cal_");
|
||||||
if (calStart != -1) {
|
if (calStart != -1) {
|
||||||
//内容页URL需要进行计算才能得到
|
//内容页URL需要进行计算才能得到
|
||||||
String calStr = bookContentUrl.substring(calStart, calStart + bookContentUrl.substring(calStart).indexOf("}"));
|
String calStr = bookContentUrl.substring(calStart,
|
||||||
|
calStart + bookContentUrl.substring(calStart).indexOf("}"));
|
||||||
String[] calArr = calStr.split("_");
|
String[] calArr = calStr.split("_");
|
||||||
int calType = Integer.parseInt(calArr[1]);
|
int calType = Integer.parseInt(calArr[1]);
|
||||||
if (calType == 1) {
|
if (calType == 1) {
|
||||||
@ -206,13 +212,25 @@ public class CrawlParser {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String contentUrl = bookContentUrl.replace("{bookId}", sourceBookId).replace("{indexId}", sourceIndexId);
|
String contentUrl = bookContentUrl.replace("{bookId}", sourceBookId)
|
||||||
|
.replace("{indexId}", sourceIndexId);
|
||||||
|
|
||||||
//查询章节内容
|
//查询章节内容
|
||||||
String contentHtml = getByHttpClientWithChrome(contentUrl);
|
String contentHtml = crawlHttpClient.get(contentUrl);
|
||||||
if (contentHtml != null && !contentHtml.contains("正在手打中")) {
|
if (contentHtml != null && !contentHtml.contains("正在手打中")) {
|
||||||
String content = contentHtml.substring(contentHtml.indexOf(ruleBean.getContentStart()) + ruleBean.getContentStart().length());
|
String content = contentHtml.substring(
|
||||||
|
contentHtml.indexOf(ruleBean.getContentStart()) + ruleBean.getContentStart().length());
|
||||||
content = content.substring(0, content.indexOf(ruleBean.getContentEnd()));
|
content = content.substring(0, content.indexOf(ruleBean.getContentEnd()));
|
||||||
|
// 小说内容过滤
|
||||||
|
String filterContent = ruleBean.getFilterContent();
|
||||||
|
if (StringUtils.isNotBlank(filterContent)) {
|
||||||
|
String[] filterRules = filterContent.replace("\r\n", "\n").split("\n");
|
||||||
|
for (String filterRule : filterRules) {
|
||||||
|
if (StringUtils.isNotBlank(filterRule)) {
|
||||||
|
content = content.replaceAll(filterRule, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
//插入章节目录和章节内容
|
//插入章节目录和章节内容
|
||||||
BookIndex bookIndex = new BookIndex();
|
BookIndex bookIndex = new BookIndex();
|
||||||
bookIndex.setIndexName(indexName);
|
bookIndex.setIndexName(indexName);
|
||||||
@ -235,7 +253,7 @@ public class CrawlParser {
|
|||||||
} else {
|
} else {
|
||||||
//章节插入
|
//章节插入
|
||||||
//设置目录和章节内容
|
//设置目录和章节内容
|
||||||
Long indexId = idWorker.nextId();
|
Long indexId = ID_WORKER.nextId();
|
||||||
bookIndex.setId(indexId);
|
bookIndex.setId(indexId);
|
||||||
bookIndex.setBookId(book.getId());
|
bookIndex.setBookId(book.getId());
|
||||||
|
|
||||||
@ -257,7 +275,6 @@ public class CrawlParser {
|
|||||||
isFindIndex = indexIdMatch.find() & indexNameMatch.find();
|
isFindIndex = indexIdMatch.find() & indexNameMatch.find();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (indexList.size() > 0) {
|
if (indexList.size() > 0) {
|
||||||
//如果有爬到最新章节,则设置小说主表的最新章节信息
|
//如果有爬到最新章节,则设置小说主表的最新章节信息
|
||||||
//获取爬取到的最新章节
|
//获取爬取到的最新章节
|
||||||
@ -290,56 +307,4 @@ public class CrawlParser {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static String getByHttpClient(String url) {
|
|
||||||
try {
|
|
||||||
ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
|
|
||||||
if (forEntity.getStatusCode() == HttpStatus.OK) {
|
|
||||||
String body = forEntity.getBody();
|
|
||||||
assert body != null;
|
|
||||||
if (body.length() < Constants.INVALID_HTML_LENGTH) {
|
|
||||||
return processErrorHttpResult(url);
|
|
||||||
}
|
|
||||||
//成功获得html内容
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return processErrorHttpResult(url);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
Integer count = retryCount.get();
|
|
||||||
if (count == null) {
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
if (count < Constants.HTTP_FAIL_RETRY_COUNT) {
|
|
||||||
Thread.sleep(new Random().nextInt(10 * 1000));
|
|
||||||
retryCount.set(++count);
|
|
||||||
return getByHttpClient(url);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 爬虫解析规则bean
|
* 爬虫解析规则bean
|
||||||
|
*
|
||||||
* @author Administrator
|
* @author Administrator
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@ -13,12 +14,12 @@ public class RuleBean {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 小说更新列表url
|
* 小说更新列表url
|
||||||
* */
|
*/
|
||||||
private String updateBookListUrl;
|
private String updateBookListUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分类列表页URL规则
|
* 分类列表页URL规则
|
||||||
* */
|
*/
|
||||||
private String bookListUrl;
|
private String bookListUrl;
|
||||||
|
|
||||||
private Map<String, String> catIdRule;
|
private Map<String, String> catIdRule;
|
||||||
@ -51,5 +52,7 @@ public class RuleBean {
|
|||||||
|
|
||||||
private String bookIndexStart;
|
private String bookIndexStart;
|
||||||
|
|
||||||
|
private String filterContent;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package com.java2nb.novel.core.listener;
|
package com.java2nb.novel.core.listener;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.java2nb.novel.core.crawl.ChapterBean;
|
|
||||||
import com.java2nb.novel.core.crawl.CrawlParser;
|
import com.java2nb.novel.core.crawl.CrawlParser;
|
||||||
import com.java2nb.novel.core.crawl.RuleBean;
|
import com.java2nb.novel.core.crawl.RuleBean;
|
||||||
import com.java2nb.novel.entity.*;
|
import com.java2nb.novel.entity.Book;
|
||||||
|
import com.java2nb.novel.entity.BookIndex;
|
||||||
|
import com.java2nb.novel.entity.CrawlSingleTask;
|
||||||
|
import com.java2nb.novel.entity.CrawlSource;
|
||||||
import com.java2nb.novel.service.BookService;
|
import com.java2nb.novel.service.BookService;
|
||||||
import com.java2nb.novel.service.CrawlService;
|
import com.java2nb.novel.service.CrawlService;
|
||||||
import com.java2nb.novel.utils.Constants;
|
import com.java2nb.novel.utils.Constants;
|
||||||
@ -33,6 +35,8 @@ public class StarterListener implements ServletContextListener {
|
|||||||
|
|
||||||
private final CrawlService crawlService;
|
private final CrawlService crawlService;
|
||||||
|
|
||||||
|
private final CrawlParser crawlParser;
|
||||||
|
|
||||||
@Value("${crawl.update.thread}")
|
@Value("${crawl.update.thread}")
|
||||||
private int updateThreadCount;
|
private int updateThreadCount;
|
||||||
|
|
||||||
@ -56,19 +60,23 @@ public class StarterListener implements ServletContextListener {
|
|||||||
CrawlSource source = crawlService.queryCrawlSource(needUpdateBook.getCrawlSourceId());
|
CrawlSource source = crawlService.queryCrawlSource(needUpdateBook.getCrawlSourceId());
|
||||||
RuleBean ruleBean = new ObjectMapper().readValue(source.getCrawlRule(), RuleBean.class);
|
RuleBean ruleBean = new ObjectMapper().readValue(source.getCrawlRule(), RuleBean.class);
|
||||||
//解析小说基本信息
|
//解析小说基本信息
|
||||||
CrawlParser.parseBook(ruleBean, needUpdateBook.getCrawlBookId(),book -> {
|
crawlParser.parseBook(ruleBean, needUpdateBook.getCrawlBookId(), book -> {
|
||||||
//这里只做老书更新
|
//这里只做老书更新
|
||||||
book.setId(needUpdateBook.getId());
|
book.setId(needUpdateBook.getId());
|
||||||
book.setWordCount(needUpdateBook.getWordCount());
|
book.setWordCount(needUpdateBook.getWordCount());
|
||||||
if (needUpdateBook.getPicUrl() != null && needUpdateBook.getPicUrl().contains(Constants.LOCAL_PIC_PREFIX)) {
|
if (needUpdateBook.getPicUrl() != null && needUpdateBook.getPicUrl()
|
||||||
|
.contains(Constants.LOCAL_PIC_PREFIX)) {
|
||||||
//本地图片则不更新
|
//本地图片则不更新
|
||||||
book.setPicUrl(null);
|
book.setPicUrl(null);
|
||||||
}
|
}
|
||||||
//查询已存在的章节
|
//查询已存在的章节
|
||||||
Map<Integer, BookIndex> existBookIndexMap = bookService.queryExistBookIndexMap(needUpdateBook.getId());
|
Map<Integer, BookIndex> existBookIndexMap = bookService.queryExistBookIndexMap(
|
||||||
|
needUpdateBook.getId());
|
||||||
//解析章节目录
|
//解析章节目录
|
||||||
CrawlParser.parseBookIndexAndContent(needUpdateBook.getCrawlBookId(), book, ruleBean, existBookIndexMap,chapter -> {
|
crawlParser.parseBookIndexAndContent(needUpdateBook.getCrawlBookId(), book,
|
||||||
bookService.updateBookAndIndexAndContent(book, chapter.getBookIndexList(), chapter.getBookContentList(), existBookIndexMap);
|
ruleBean, existBookIndexMap, chapter -> {
|
||||||
|
bookService.updateBookAndIndexAndContent(book, chapter.getBookIndexList(),
|
||||||
|
chapter.getBookContentList(), existBookIndexMap);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -88,7 +96,6 @@ public class StarterListener implements ServletContextListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
log.info("程序启动,开始执行单本采集任务线程。。。");
|
log.info("程序启动,开始执行单本采集任务线程。。。");
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -103,7 +110,8 @@ public class StarterListener implements ServletContextListener {
|
|||||||
CrawlSource source = crawlService.queryCrawlSource(task.getSourceId());
|
CrawlSource source = crawlService.queryCrawlSource(task.getSourceId());
|
||||||
RuleBean ruleBean = new ObjectMapper().readValue(source.getCrawlRule(), RuleBean.class);
|
RuleBean ruleBean = new ObjectMapper().readValue(source.getCrawlRule(), RuleBean.class);
|
||||||
|
|
||||||
if (crawlService.parseBookAndSave(task.getCatId(), ruleBean, task.getSourceId(), task.getSourceBookId())) {
|
if (crawlService.parseBookAndSave(task.getCatId(), ruleBean, task.getSourceId(),
|
||||||
|
task.getSourceBookId())) {
|
||||||
//采集成功
|
//采集成功
|
||||||
crawlStatus = 1;
|
crawlStatus = 1;
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,11 @@ package com.java2nb.novel.service.impl;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import io.github.xxyopen.model.page.PageBean;
|
|
||||||
import com.java2nb.novel.core.cache.CacheKey;
|
import com.java2nb.novel.core.cache.CacheKey;
|
||||||
import com.java2nb.novel.core.cache.CacheService;
|
import com.java2nb.novel.core.cache.CacheService;
|
||||||
import com.java2nb.novel.core.crawl.CrawlParser;
|
import com.java2nb.novel.core.crawl.CrawlParser;
|
||||||
import com.java2nb.novel.core.crawl.RuleBean;
|
import com.java2nb.novel.core.crawl.RuleBean;
|
||||||
import com.java2nb.novel.core.enums.ResponseStatus;
|
import com.java2nb.novel.core.enums.ResponseStatus;
|
||||||
import io.github.xxyopen.model.page.builder.pagehelper.PageBuilder;
|
|
||||||
import io.github.xxyopen.util.IdWorker;
|
|
||||||
import io.github.xxyopen.util.ThreadUtil;
|
|
||||||
import io.github.xxyopen.web.exception.BusinessException;
|
|
||||||
import io.github.xxyopen.web.util.BeanUtil;
|
|
||||||
import com.java2nb.novel.entity.Book;
|
import com.java2nb.novel.entity.Book;
|
||||||
import com.java2nb.novel.entity.CrawlSingleTask;
|
import com.java2nb.novel.entity.CrawlSingleTask;
|
||||||
import com.java2nb.novel.entity.CrawlSource;
|
import com.java2nb.novel.entity.CrawlSource;
|
||||||
@ -22,8 +16,15 @@ import com.java2nb.novel.mapper.CrawlSourceDynamicSqlSupport;
|
|||||||
import com.java2nb.novel.mapper.CrawlSourceMapper;
|
import com.java2nb.novel.mapper.CrawlSourceMapper;
|
||||||
import com.java2nb.novel.service.BookService;
|
import com.java2nb.novel.service.BookService;
|
||||||
import com.java2nb.novel.service.CrawlService;
|
import com.java2nb.novel.service.CrawlService;
|
||||||
|
import com.java2nb.novel.utils.CrawlHttpClient;
|
||||||
import com.java2nb.novel.vo.CrawlSingleTaskVO;
|
import com.java2nb.novel.vo.CrawlSingleTaskVO;
|
||||||
import com.java2nb.novel.vo.CrawlSourceVO;
|
import com.java2nb.novel.vo.CrawlSourceVO;
|
||||||
|
import io.github.xxyopen.model.page.PageBean;
|
||||||
|
import io.github.xxyopen.model.page.builder.pagehelper.PageBuilder;
|
||||||
|
import io.github.xxyopen.util.IdWorker;
|
||||||
|
import io.github.xxyopen.util.ThreadUtil;
|
||||||
|
import io.github.xxyopen.web.exception.BusinessException;
|
||||||
|
import io.github.xxyopen.web.util.BeanUtil;
|
||||||
import io.github.xxyopen.web.util.SpringUtil;
|
import io.github.xxyopen.web.util.SpringUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
@ -38,7 +39,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static com.java2nb.novel.core.utils.HttpUtil.getByHttpClientWithChrome;
|
|
||||||
import static com.java2nb.novel.mapper.CrawlSourceDynamicSqlSupport.*;
|
import static com.java2nb.novel.mapper.CrawlSourceDynamicSqlSupport.*;
|
||||||
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
|
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
|
||||||
import static org.mybatis.dynamic.sql.select.SelectDSL.select;
|
import static org.mybatis.dynamic.sql.select.SelectDSL.select;
|
||||||
@ -51,6 +51,7 @@ import static org.mybatis.dynamic.sql.select.SelectDSL.select;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class CrawlServiceImpl implements CrawlService {
|
public class CrawlServiceImpl implements CrawlService {
|
||||||
|
|
||||||
|
private final CrawlParser crawlParser;
|
||||||
|
|
||||||
private final CrawlSourceMapper crawlSourceMapper;
|
private final CrawlSourceMapper crawlSourceMapper;
|
||||||
|
|
||||||
@ -62,6 +63,8 @@ public class CrawlServiceImpl implements CrawlService {
|
|||||||
|
|
||||||
private final IdWorker idWorker = IdWorker.INSTANCE;
|
private final IdWorker idWorker = IdWorker.INSTANCE;
|
||||||
|
|
||||||
|
private final CrawlHttpClient crawlHttpClient;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addCrawlSource(CrawlSource source) {
|
public void addCrawlSource(CrawlSource source) {
|
||||||
@ -71,6 +74,7 @@ public class CrawlServiceImpl implements CrawlService {
|
|||||||
crawlSourceMapper.insertSelective(source);
|
crawlSourceMapper.insertSelective(source);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateCrawlSource(CrawlSource source) {
|
public void updateCrawlSource(CrawlSource source) {
|
||||||
if (source.getId() != null) {
|
if (source.getId() != null) {
|
||||||
@ -89,6 +93,7 @@ public class CrawlServiceImpl implements CrawlService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageBean<CrawlSource> listCrawlByPage(int page, int pageSize) {
|
public PageBean<CrawlSource> listCrawlByPage(int page, int pageSize) {
|
||||||
PageHelper.startPage(page, pageSize);
|
PageHelper.startPage(page, pageSize);
|
||||||
@ -113,7 +118,8 @@ public class CrawlServiceImpl implements CrawlService {
|
|||||||
if (sourceStatus == (byte) 0) {
|
if (sourceStatus == (byte) 0) {
|
||||||
//关闭,直接修改数据库状态,并直接修改数据库状态后获取该爬虫正在运行的线程集合全部停止
|
//关闭,直接修改数据库状态,并直接修改数据库状态后获取该爬虫正在运行的线程集合全部停止
|
||||||
SpringUtil.getBean(CrawlService.class).updateCrawlSourceStatus(sourceId, sourceStatus);
|
SpringUtil.getBean(CrawlService.class).updateCrawlSourceStatus(sourceId, sourceStatus);
|
||||||
Set<Long> runningCrawlThreadId = (Set<Long>) cacheService.getObject(CacheKey.RUNNING_CRAWL_THREAD_KEY_PREFIX + sourceId);
|
Set<Long> runningCrawlThreadId = (Set<Long>) cacheService.getObject(
|
||||||
|
CacheKey.RUNNING_CRAWL_THREAD_KEY_PREFIX + sourceId);
|
||||||
if (runningCrawlThreadId != null) {
|
if (runningCrawlThreadId != null) {
|
||||||
for (Long ThreadId : runningCrawlThreadId) {
|
for (Long ThreadId : runningCrawlThreadId) {
|
||||||
Thread thread = ThreadUtil.findThread(ThreadId);
|
Thread thread = ThreadUtil.findThread(ThreadId);
|
||||||
@ -157,7 +163,8 @@ public class CrawlServiceImpl implements CrawlService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CrawlSource queryCrawlSource(Integer sourceId) {
|
public CrawlSource queryCrawlSource(Integer sourceId) {
|
||||||
SelectStatementProvider render = select(CrawlSourceDynamicSqlSupport.sourceStatus, CrawlSourceDynamicSqlSupport.crawlRule)
|
SelectStatementProvider render = select(CrawlSourceDynamicSqlSupport.sourceStatus,
|
||||||
|
CrawlSourceDynamicSqlSupport.crawlRule)
|
||||||
.from(crawlSource)
|
.from(crawlSource)
|
||||||
.where(id, isEqualTo(sourceId))
|
.where(id, isEqualTo(sourceId))
|
||||||
.build()
|
.build()
|
||||||
@ -200,7 +207,8 @@ public class CrawlServiceImpl implements CrawlService {
|
|||||||
@Override
|
@Override
|
||||||
public CrawlSingleTask getCrawlSingleTask() {
|
public CrawlSingleTask getCrawlSingleTask() {
|
||||||
|
|
||||||
List<CrawlSingleTask> list = crawlSingleTaskMapper.selectMany(select(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask.allColumns())
|
List<CrawlSingleTask> list = crawlSingleTaskMapper.selectMany(
|
||||||
|
select(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask.allColumns())
|
||||||
.from(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask)
|
.from(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask)
|
||||||
.where(CrawlSingleTaskDynamicSqlSupport.taskStatus, isEqualTo((byte) 2))
|
.where(CrawlSingleTaskDynamicSqlSupport.taskStatus, isEqualTo((byte) 2))
|
||||||
.orderBy(CrawlSingleTaskDynamicSqlSupport.createTime)
|
.orderBy(CrawlSingleTaskDynamicSqlSupport.createTime)
|
||||||
@ -254,7 +262,7 @@ public class CrawlServiceImpl implements CrawlService {
|
|||||||
.replace("{catId}", ruleBean.getCatIdRule().get("catId" + catId))
|
.replace("{catId}", ruleBean.getCatIdRule().get("catId" + catId))
|
||||||
.replace("{page}", page + "");
|
.replace("{page}", page + "");
|
||||||
|
|
||||||
String bookListHtml = getByHttpClientWithChrome(catBookListUrl);
|
String bookListHtml = crawlHttpClient.get(catBookListUrl);
|
||||||
if (bookListHtml != null) {
|
if (bookListHtml != null) {
|
||||||
Pattern bookIdPatten = Pattern.compile(ruleBean.getBookIdPatten());
|
Pattern bookIdPatten = Pattern.compile(ruleBean.getBookIdPatten());
|
||||||
Matcher bookIdMatcher = bookIdPatten.matcher(bookListHtml);
|
Matcher bookIdMatcher = bookIdPatten.matcher(bookListHtml);
|
||||||
@ -268,14 +276,12 @@ public class CrawlServiceImpl implements CrawlService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String bookId = bookIdMatcher.group(1);
|
String bookId = bookIdMatcher.group(1);
|
||||||
parseBookAndSave(catId, ruleBean, sourceId, bookId);
|
parseBookAndSave(catId, ruleBean, sourceId, bookId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
isFindBookId = bookIdMatcher.find();
|
isFindBookId = bookIdMatcher.find();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +312,7 @@ public class CrawlServiceImpl implements CrawlService {
|
|||||||
|
|
||||||
final AtomicBoolean parseResult = new AtomicBoolean(false);
|
final AtomicBoolean parseResult = new AtomicBoolean(false);
|
||||||
|
|
||||||
CrawlParser.parseBook(ruleBean, bookId, book -> {
|
crawlParser.parseBook(ruleBean, bookId, book -> {
|
||||||
if (book.getBookName() == null || book.getAuthorName() == null) {
|
if (book.getBookName() == null || book.getAuthorName() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -330,8 +336,10 @@ public class CrawlServiceImpl implements CrawlService {
|
|||||||
book.setCrawlLastTime(new Date());
|
book.setCrawlLastTime(new Date());
|
||||||
book.setId(idWorker.nextId());
|
book.setId(idWorker.nextId());
|
||||||
//解析章节目录
|
//解析章节目录
|
||||||
boolean parseIndexContentResult = CrawlParser.parseBookIndexAndContent(bookId, book, ruleBean, new HashMap<>(0), chapter -> {
|
boolean parseIndexContentResult = crawlParser.parseBookIndexAndContent(bookId, book, ruleBean,
|
||||||
bookService.saveBookAndIndexAndContent(book, chapter.getBookIndexList(), chapter.getBookContentList());
|
new HashMap<>(0), chapter -> {
|
||||||
|
bookService.saveBookAndIndexAndContent(book, chapter.getBookIndexList(),
|
||||||
|
chapter.getBookContentList());
|
||||||
});
|
});
|
||||||
parseResult.set(parseIndexContentResult);
|
parseResult.set(parseIndexContentResult);
|
||||||
|
|
||||||
@ -356,7 +364,8 @@ public class CrawlServiceImpl implements CrawlService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CrawlSource> queryCrawlSourceByStatus(Byte sourceStatus) {
|
public List<CrawlSource> queryCrawlSourceByStatus(Byte sourceStatus) {
|
||||||
SelectStatementProvider render = select(CrawlSourceDynamicSqlSupport.id, CrawlSourceDynamicSqlSupport.sourceStatus, CrawlSourceDynamicSqlSupport.crawlRule)
|
SelectStatementProvider render = select(CrawlSourceDynamicSqlSupport.id,
|
||||||
|
CrawlSourceDynamicSqlSupport.sourceStatus, CrawlSourceDynamicSqlSupport.crawlRule)
|
||||||
.from(crawlSource)
|
.from(crawlSource)
|
||||||
.where(CrawlSourceDynamicSqlSupport.sourceStatus, isEqualTo(sourceStatus))
|
.where(CrawlSourceDynamicSqlSupport.sourceStatus, isEqualTo(sourceStatus))
|
||||||
.build()
|
.build()
|
||||||
|
@ -7,7 +7,7 @@ public class Constants {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 本地图片保存前缀
|
* 本地图片保存前缀
|
||||||
* */
|
*/
|
||||||
public static final String LOCAL_PIC_PREFIX = "/localPic/";
|
public static final String LOCAL_PIC_PREFIX = "/localPic/";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,5 +23,5 @@ public class Constants {
|
|||||||
/**
|
/**
|
||||||
* 爬取小说http请求失败重试次数
|
* 爬取小说http请求失败重试次数
|
||||||
*/
|
*/
|
||||||
public static final Integer HTTP_FAIL_RETRY_COUNT = 5;
|
public static final Integer HTTP_FAIL_RETRY_COUNT = 3;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.java2nb.novel.utils;
|
||||||
|
|
||||||
|
import com.java2nb.novel.core.utils.HttpUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Administrator
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class CrawlHttpClient {
|
||||||
|
|
||||||
|
@Value("${crawl.interval.min}")
|
||||||
|
private Integer intervalMin;
|
||||||
|
|
||||||
|
@Value("${crawl.interval.max}")
|
||||||
|
private Integer intervalMax;
|
||||||
|
|
||||||
|
private final Random random = new Random();
|
||||||
|
|
||||||
|
private static final ThreadLocal<Integer> RETRY_COUNT = new ThreadLocal<>();
|
||||||
|
|
||||||
|
public String get(String url) {
|
||||||
|
if (Objects.nonNull(intervalMin) && Objects.nonNull(intervalMax) && intervalMax > intervalMin) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(random.nextInt(intervalMax - intervalMin + 1) + intervalMin);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String body = HttpUtil.getByHttpClientWithChrome(url);
|
||||||
|
if (Objects.isNull(body) || body.length() < Constants.INVALID_HTML_LENGTH) {
|
||||||
|
return processErrorHttpResult(url);
|
||||||
|
}
|
||||||
|
//成功获得html内容
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String processErrorHttpResult(String url) {
|
||||||
|
Integer count = RETRY_COUNT.get();
|
||||||
|
if (count == null) {
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
if (count < Constants.HTTP_FAIL_RETRY_COUNT) {
|
||||||
|
RETRY_COUNT.set(++count);
|
||||||
|
return get(url);
|
||||||
|
}
|
||||||
|
RETRY_COUNT.remove();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -14,12 +14,18 @@ admin:
|
|||||||
username: admin
|
username: admin
|
||||||
password: admin
|
password: admin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
crawl:
|
||||||
|
update:
|
||||||
#爬虫自动更新的线程数
|
#爬虫自动更新的线程数
|
||||||
#建议小说数量不多或者正在运行新书入库爬虫的情况下设置为1即可
|
#建议小说数量不多或者正在运行新书入库爬虫的情况下设置为1即可
|
||||||
#随着小说数量的增多可以逐渐增加,但建议不要超出CPU的线程数
|
#随着小说数量的增多可以逐渐增加,但建议不要超出CPU的线程数
|
||||||
crawl:
|
|
||||||
update:
|
|
||||||
thread: 1
|
thread: 1
|
||||||
|
# 采集间隔时间,单位:毫秒
|
||||||
|
interval:
|
||||||
|
min: 300
|
||||||
|
max: 500
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BIN
novel-crawl/src/main/resources/favicon.ico
Normal file
After Width: | Height: | Size: 162 KiB |
@ -1,100 +1,511 @@
|
|||||||
@charset "utf-8";
|
@charset "utf-8";
|
||||||
.updateTable .style a { color:#999 }
|
.updateTable .style a {
|
||||||
.updateTable .author a { color:#999; cursor:text }
|
color: #999
|
||||||
.bind, .updateTable .style a:hover { color:#f65167 }
|
}
|
||||||
.userBox { /*width: 998px; border: 1px solid #eaeaea;*/ margin:0 auto 50px; background: #fff; border-radius: 6px }
|
|
||||||
.channelViewhistory .userBox { margin: 0 auto }
|
.updateTable .author a {
|
||||||
.user_l { width:350px; float:left; padding:50px 50px }
|
color: #999;
|
||||||
.user_l h3 { font-size:23px; font-weight:normal; line-height:1; text-align: center }
|
cursor: text
|
||||||
.user_l #LabErr { color:#ff4040; display:block; height:40px; line-height:40px; text-align: center; font-size: 14px }
|
}
|
||||||
.user_l .log_list { width:350px }
|
|
||||||
.user_l .s_input { margin-bottom:25px; font-size:14px }
|
.bind, .updateTable .style a:hover {
|
||||||
.s_input { width:348px; height:30px; line-height:38px\9; vertical-align:middle; border:1px solid #ddd; border-radius:2px }
|
color: #f65167
|
||||||
.icon_name, .icon_key, .icon_code { width:312px; padding-left:36px}
|
}
|
||||||
.icon_key { background-position: 13px -51px }
|
|
||||||
.icon_code { background-position: 13px -117px; width:200px; float:left }
|
.userBox { /*width: 998px; border: 1px solid #eaeaea;*/
|
||||||
.code_pic { height:38px; float:right }
|
margin: 0 auto 50px;
|
||||||
.btn_phone { height:40px; width:100px; float:right; cursor:pointer; padding:0; text-align:center; border-radius:2px; background:#dfdfdf }
|
background: #fff;
|
||||||
.log_code { *padding-bottom:25px }
|
border-radius: 6px
|
||||||
.user_l .btn_red { width:100%; font-size:19px; padding:12px }
|
}
|
||||||
.autologin { color:#999; line-height:1; margin-bottom:18px }
|
|
||||||
.autologin em { vertical-align:2px; margin-left:4px }
|
.channelViewhistory .userBox {
|
||||||
.user_r { width:259px; margin:80px 0; padding:20px 70px; border-left:1px dotted #e3e3e3; float:right; text-align:center }
|
margin: 0 auto
|
||||||
.user_r .tit { font-size:16px; line-height:1; padding: 6px 0 25px }
|
}
|
||||||
.user_r .btn_ora { padding:10px 34px }
|
|
||||||
.fast_login { padding:60px 0 0 }
|
.user_l {
|
||||||
.fast_list { text-align:center; padding:0.5rem }
|
width: 350px;
|
||||||
.fast_list li { display:inline-block; *display:inline; zoom:1 }
|
float: left;
|
||||||
.fast_list li .img { width:48px; height:48px; margin:20px 0 5px }
|
padding: 50px 50px
|
||||||
.fast_list li a:hover { opacity:0.8; filter: alpha(opacity=80); -moz-opacity: 0.8 }
|
}
|
||||||
.fast_list li span { display:block }
|
|
||||||
.fast_list .login_qq { margin:0 42px }
|
.user_l h3 {
|
||||||
.fast_list .login_wb a { color:#f55c5b }
|
font-size: 23px;
|
||||||
.fast_list .login_qq a { color:#51b7ff }
|
font-weight: normal;
|
||||||
.fast_list .login_wx a { color:#66d65e }
|
line-height: 1;
|
||||||
.fast_tit { position:relative; overflow:hidden }
|
text-align: center
|
||||||
.fast_tit .lines { position:absolute; top:50%; left:0; width:100%; height:1px; line-height:1; background:#eaeaea }
|
}
|
||||||
.fast_tit .title { background:#fff; font-size:16px; padding:3px 14px; position:relative; display:inline-block; z-index:999 }
|
|
||||||
/*userinfo*/
|
.user_l #LabErr {
|
||||||
.my_l { width:198px; float:left; font-size: 13px; padding-top: 20px; }
|
color: #ff4040;
|
||||||
.my_l li a { display:block; height:42px; line-height:42px; padding-left:62px; border-left:4px solid #fff; margin-bottom:5px; color: #666 }
|
display: block;
|
||||||
.my_l li .on { background-color:#fafafa; border-left:2px solid #f80; color:#000; border-radius: 0 2px 2px 0 }
|
height: 40px;
|
||||||
.my_l .link_1 { background-position:32px -188px }
|
line-height: 40px;
|
||||||
.my_l .link_2 { background-position:32px -230px }
|
text-align: center;
|
||||||
.my_l .link_3 { background-position:32px -272px }
|
font-size: 14px
|
||||||
.my_l .link_4 { background-position:32px -314px }
|
}
|
||||||
.my_l .link_5 { background-position:32px -356px }
|
|
||||||
.my_l .link_6 { background-position:32px -397px }
|
.user_l .log_list {
|
||||||
.my_l .link_7 { background-position:32px -440px }
|
width: 350px
|
||||||
.my_l .link_8 { background-position:32px -481px }
|
}
|
||||||
.my_r { width:739px; padding:0 30px 30px; float:right; border-left:1px solid #efefef; min-height:470px }
|
|
||||||
.my_info { padding:30px 0 5px }
|
.user_l .s_input {
|
||||||
.user_big_head { /*width:110px; height:110px; padding:4px; border:1px solid #eaeaea;*/ margin-right:30px; float:left; width: 80px;
|
margin-bottom: 25px;
|
||||||
height: 80px;
|
font-size: 14px
|
||||||
border-radius: 50%; }
|
}
|
||||||
.my_r .my_name { font-size:18px; line-height:1; padding:5px 0 12px 0 }
|
|
||||||
.my_r .s_input { width:318px; padding:0 10px }
|
.s_input {
|
||||||
.my_list li { line-height:28px }
|
width: 348px;
|
||||||
.my_list li i, .my_list li em.red { margin-right:6px }
|
height: 30px;
|
||||||
.my_list .binded { color:#999; margin-left:6px }
|
line-height: 38px \9;
|
||||||
.my_list .btn_link { margin-left:12px }
|
vertical-align: middle;
|
||||||
.mytab_list li { line-height:30px; padding:10px 0; font-size:14px }
|
border: 1px solid #ddd;
|
||||||
.mytab_list li .tit { width:70px; color: #aaa; text-align:right; display:inline-block; margin-right:18px }
|
border-radius: 2px
|
||||||
.mytab_list .user_img { width:48px; height:48px; vertical-align:middle; border-radius:50% }
|
}
|
||||||
.my_bookshelf .title { padding:20px 0 15px; line-height:30px }
|
|
||||||
.my_bookshelf h4 { font-size:14px; color:#666 }
|
.icon_name, .icon_key, .icon_code {
|
||||||
.my_bookshelf h2 { font-size:18px; font-weight:normal }
|
width: 312px;
|
||||||
.updateTable { width: 739px; color: #999 }
|
padding-left: 36px
|
||||||
.updateTable table { width: 100%; margin-bottom:14px }
|
}
|
||||||
.updateTable th, .updateTable td { height: 40px; line-height: 40px; vertical-align: middle; padding-left: 6px; font-weight:normal; text-align:left }
|
|
||||||
.updateTable th { background:#f9f9f9; color:#333; border-top:1px solid #eee }
|
.icon_key {
|
||||||
.updateTable td { height:40px; line-height:40px }
|
background-position: 13px -51px
|
||||||
.updateTable .style { width:80px; padding-left:10px }
|
}
|
||||||
.updateTable .name { width: 178px; padding-right: 10px }
|
|
||||||
.updateTable .name a, .updateTable .chapter a { max-width: 168px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
.icon_code {
|
||||||
.updateTable .chapter { padding-right: 5px }
|
background-position: 13px -117px;
|
||||||
.updateTable .chapter a { max-width:220px; float: left }
|
width: 200px;
|
||||||
.updateTable .author { width: 72px; text-align: left }
|
float: left
|
||||||
.updateTable .goread { width: 80px; text-align:center }
|
}
|
||||||
.updateTable .time { width: 86px }
|
|
||||||
.updateTable .word { width: 64px; padding-right:10px; text-align: right }
|
.code_pic {
|
||||||
.updateTable .rank { width: 30px; padding-right:10px; text-align: center }
|
height: 38px;
|
||||||
.updateTable .name a, .updateTable .chapter a, .updateTable .author a { height: 40px; line-height: 40px; display: inline-block; overflow: hidden }
|
float: right
|
||||||
.updateTable tr:nth-child(2n) td { background:#fafafa }
|
}
|
||||||
.dataTable { width: 739px }
|
|
||||||
.dataTable table { width: 100%; margin-bottom:14px; border-collapse:collapse }
|
.btn_phone {
|
||||||
.dataTable th, .dataTable td { height: 40px; line-height: 40px; vertical-align: middle; padding:0 10px; font-weight:normal; text-align:center; border:1px solid #eaeaea }
|
height: 40px;
|
||||||
.dataTable th { background:#f8f8f8 }
|
width: 100px;
|
||||||
.nodate { border-top: 1px solid #eaeaea; padding:60px 0 }
|
float: right;
|
||||||
.viewhistoryBox { /*padding: 0 30px 30px; */ padding: 0 20px 10px }
|
cursor: pointer;
|
||||||
.viewhistoryBox .updateTable { width:100% }
|
padding: 0;
|
||||||
/*.btn_gray, .btn_red, .btn_ora { font-size:14px; padding:8px 28px }*/
|
text-align: center;
|
||||||
.book_tit { height: 48px; line-height:48px; margin: 0 14px; border-bottom: 1px solid #eaeaea; overflow:hidden }
|
border-radius: 2px;
|
||||||
.book_tit .fl { font-size:14px; color:#999 }
|
background: #dfdfdf
|
||||||
.book_tit .fl h3 { font-size:18px; color:#333; font-weight:normal; margin-right:5px; display:inline }
|
}
|
||||||
.book_tit .fr { font-size:14px }
|
|
||||||
|
.log_code {
|
||||||
|
*padding-bottom: 25px
|
||||||
|
}
|
||||||
|
|
||||||
|
.user_l .btn_red {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 19px;
|
||||||
|
padding: 12px
|
||||||
|
}
|
||||||
|
|
||||||
|
.autologin {
|
||||||
|
color: #999;
|
||||||
|
line-height: 1;
|
||||||
|
margin-bottom: 18px
|
||||||
|
}
|
||||||
|
|
||||||
|
.autologin em {
|
||||||
|
vertical-align: 2px;
|
||||||
|
margin-left: 4px
|
||||||
|
}
|
||||||
|
|
||||||
|
.user_r {
|
||||||
|
width: 259px;
|
||||||
|
margin: 80px 0;
|
||||||
|
padding: 20px 70px;
|
||||||
|
border-left: 1px dotted #e3e3e3;
|
||||||
|
float: right;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.user_r .tit {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 6px 0 25px
|
||||||
|
}
|
||||||
|
|
||||||
|
.user_r .btn_ora {
|
||||||
|
padding: 10px 34px
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_login {
|
||||||
|
padding: 60px 0 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_list {
|
||||||
|
text-align: center;
|
||||||
|
padding: 0.5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_list li {
|
||||||
|
display: inline-block;
|
||||||
|
*display: inline;
|
||||||
|
zoom: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_list li .img {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
margin: 20px 0 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_list li a:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
filter: alpha(opacity=80);
|
||||||
|
-moz-opacity: 0.8
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_list li span {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_list .login_qq {
|
||||||
|
margin: 0 42px
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_list .login_wb a {
|
||||||
|
color: #f55c5b
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_list .login_qq a {
|
||||||
|
color: #51b7ff
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_list .login_wx a {
|
||||||
|
color: #66d65e
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_tit {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_tit .lines {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
line-height: 1;
|
||||||
|
background: #eaeaea
|
||||||
|
}
|
||||||
|
|
||||||
|
.fast_tit .title {
|
||||||
|
background: #fff;
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 3px 14px;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
z-index: 999
|
||||||
|
}
|
||||||
|
|
||||||
|
/*userinfo*/
|
||||||
|
.my_l {
|
||||||
|
width: 198px;
|
||||||
|
float: left;
|
||||||
|
font-size: 13px;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_l li a {
|
||||||
|
display: block;
|
||||||
|
height: 42px;
|
||||||
|
line-height: 42px;
|
||||||
|
padding-left: 62px;
|
||||||
|
border-left: 4px solid #fff;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
color: #666
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_l li .on {
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-left: 2px solid #3eaf7c;
|
||||||
|
color: #000;
|
||||||
|
border-radius: 0 2px 2px 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_l .link_1 {
|
||||||
|
background-position: 32px -188px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_l .link_2 {
|
||||||
|
background-position: 32px -230px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_l .link_3 {
|
||||||
|
background-position: 32px -272px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_l .link_4 {
|
||||||
|
background-position: 32px -314px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_l .link_5 {
|
||||||
|
background-position: 32px -356px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_l .link_6 {
|
||||||
|
background-position: 32px -397px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_l .link_7 {
|
||||||
|
background-position: 32px -440px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_l .link_8 {
|
||||||
|
background-position: 32px -481px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_r {
|
||||||
|
width: 739px;
|
||||||
|
padding: 0 30px 30px;
|
||||||
|
float: right;
|
||||||
|
border-left: 1px solid #efefef;
|
||||||
|
min-height: 470px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_info {
|
||||||
|
padding: 30px 0 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.user_big_head { /*width:110px; height:110px; padding:4px; border:1px solid #eaeaea;*/
|
||||||
|
margin-right: 30px;
|
||||||
|
float: left;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_r .my_name {
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 5px 0 12px 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_r .s_input {
|
||||||
|
width: 318px;
|
||||||
|
padding: 0 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_list li {
|
||||||
|
line-height: 28px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_list li i, .my_list li em.red {
|
||||||
|
margin-right: 6px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_list .binded {
|
||||||
|
color: #999;
|
||||||
|
margin-left: 6px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_list .btn_link {
|
||||||
|
margin-left: 12px
|
||||||
|
}
|
||||||
|
|
||||||
|
.mytab_list li {
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 10px 0;
|
||||||
|
font-size: 14px
|
||||||
|
}
|
||||||
|
|
||||||
|
.mytab_list li .tit {
|
||||||
|
width: 70px;
|
||||||
|
color: #aaa;
|
||||||
|
text-align: right;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 18px
|
||||||
|
}
|
||||||
|
|
||||||
|
.mytab_list .user_img {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
vertical-align: middle;
|
||||||
|
border-radius: 50%
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_bookshelf .title {
|
||||||
|
padding: 20px 0 15px;
|
||||||
|
line-height: 30px
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_bookshelf h4 {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_bookshelf h2 {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: normal
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable {
|
||||||
|
width: 739px;
|
||||||
|
color: #999
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable table {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 14px
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable th, .updateTable td {
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding-left: 6px;
|
||||||
|
font-weight: normal;
|
||||||
|
text-align: left
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable th {
|
||||||
|
background: #f9f9f9;
|
||||||
|
color: #333;
|
||||||
|
border-top: 1px solid #eee
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable td {
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable .style {
|
||||||
|
width: 80px;
|
||||||
|
padding-left: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable .name {
|
||||||
|
width: 178px;
|
||||||
|
padding-right: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable .name a, .updateTable .chapter a {
|
||||||
|
max-width: 168px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable .chapter {
|
||||||
|
padding-right: 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable .chapter a {
|
||||||
|
max-width: 220px;
|
||||||
|
float: left
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable .author {
|
||||||
|
width: 72px;
|
||||||
|
text-align: left
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable .goread {
|
||||||
|
width: 80px;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable .time {
|
||||||
|
width: 86px
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable .word {
|
||||||
|
width: 64px;
|
||||||
|
padding-right: 10px;
|
||||||
|
text-align: right
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable .rank {
|
||||||
|
width: 30px;
|
||||||
|
padding-right: 10px;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable .name a, .updateTable .chapter a, .updateTable .author a {
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
display: inline-block;
|
||||||
|
overflow: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateTable tr:nth-child(2n) td {
|
||||||
|
background: #fafafa
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataTable {
|
||||||
|
width: 739px
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataTable table {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
border-collapse: collapse
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataTable th, .dataTable td {
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-weight: normal;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid #eaeaea
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataTable th {
|
||||||
|
background: #f8f8f8
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodate {
|
||||||
|
border-top: 1px solid #eaeaea;
|
||||||
|
padding: 60px 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewhistoryBox { /*padding: 0 30px 30px; */
|
||||||
|
padding: 0 20px 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewhistoryBox .updateTable {
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
/*.btn_gray, .btn_red, .btn_ora { font-size:14px; padding:8px 28px }*/
|
||||||
|
.book_tit {
|
||||||
|
height: 48px;
|
||||||
|
line-height: 48px;
|
||||||
|
margin: 0 14px;
|
||||||
|
border-bottom: 1px solid #eaeaea;
|
||||||
|
overflow: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.book_tit .fl {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999
|
||||||
|
}
|
||||||
|
|
||||||
|
.book_tit .fl h3 {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-right: 5px;
|
||||||
|
display: inline
|
||||||
|
}
|
||||||
|
|
||||||
|
.book_tit .fr {
|
||||||
|
font-size: 14px
|
||||||
|
}
|
||||||
|
|
||||||
|
.commentBar, .feedback_list {
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
margin-bottom: 15px
|
||||||
|
}
|
||||||
|
|
||||||
.commentBar, .feedback_list { border-top:1px solid #eee; margin-bottom:15px }
|
|
||||||
/*.comment_list { padding: 16px 0; border-bottom: 1px solid #eee }
|
/*.comment_list { padding: 16px 0; border-bottom: 1px solid #eee }
|
||||||
.comment_list .user_head { width:54px; height:54px; border-radius:50%; float: left; margin-right: 14px }
|
.comment_list .user_head { width:54px; height:54px; border-radius:50%; float: left; margin-right: 14px }
|
||||||
.comment_list .li_1 { overflow: hidden }
|
.comment_list .li_1 { overflow: hidden }
|
||||||
@ -105,33 +516,128 @@
|
|||||||
.comment_list .num { color: #ed4259; margin: 0 3px }
|
.comment_list .num { color: #ed4259; margin: 0 3px }
|
||||||
.comment_list .li_4 { line-height:34px; padding-top:8px; margin-top:15px; border-top:1px solid #eaeaea }
|
.comment_list .li_4 { line-height:34px; padding-top:8px; margin-top:15px; border-top:1px solid #eaeaea }
|
||||||
.comment_list .li_4 .more { background:#f7f7f7; border-radius:2px; color:#ed4259; text-align:center }*/
|
.comment_list .li_4 .more { background:#f7f7f7; border-radius:2px; color:#ed4259; text-align:center }*/
|
||||||
.no_contet { padding:190px 0 40px; text-align:center; color:#999; border-top:1px solid #eee }
|
.no_contet {
|
||||||
.no_comment { background:url(../images/no_comment.png) no-repeat center 80px }
|
padding: 190px 0 40px;
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
border-top: 1px solid #eee
|
||||||
|
}
|
||||||
|
|
||||||
|
.no_comment {
|
||||||
|
background: url(../images/no_comment.png) no-repeat center 80px
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list {
|
||||||
|
padding: 20px 0;
|
||||||
|
border-bottom: 1px solid #eee
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list:last-child {
|
||||||
|
border: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .user_heads { /*width: 54px; height: 54px; float: left;*/
|
||||||
|
position: relative;
|
||||||
|
margin-right: 20px
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .user_head {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #f6f6f6
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .user_heads span {
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
left: 12px;
|
||||||
|
bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list ul { /*width: 640px;*/
|
||||||
|
width: 660px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .li_0 {
|
||||||
|
font-family: "宋体"
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .li_0 strong {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #f00
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .li_1 {
|
||||||
|
overflow: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .user_name {
|
||||||
|
color: #ed4259
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .li_2 {
|
||||||
|
padding: 6px 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .li_3 {
|
||||||
|
color: #999
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .reply {
|
||||||
|
padding-left: 12px
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .num {
|
||||||
|
color: #ed4259;
|
||||||
|
margin: 0 3px
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment_list .li_4 {
|
||||||
|
line-height: 34px;
|
||||||
|
padding-top: 8px;
|
||||||
|
margin-top: 15px;
|
||||||
|
border-top: 1px solid #eaeaea
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl_bar li {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl_bar .name {
|
||||||
|
color: #666;
|
||||||
|
padding-top: 2px;
|
||||||
|
font-size: 14px
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl_bar .dec {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.8;
|
||||||
|
padding: 12px 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl_bar .other {
|
||||||
|
line-height: 24px;
|
||||||
|
color: #999;
|
||||||
|
font-size: 13px
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl_bar .other a {
|
||||||
|
display: inline-block;
|
||||||
|
color: #999
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl_bar .reply {
|
||||||
|
padding-left: 22px;
|
||||||
|
background: url(../images/icon_reply.png) no-repeat 0 2px
|
||||||
|
}
|
||||||
|
|
||||||
.comment_list { padding: 20px 0; border-bottom: 1px solid #eee }
|
|
||||||
.comment_list:last-child { border: none }
|
|
||||||
.comment_list .user_heads { /*width: 54px; height: 54px; float: left;*/ position:relative; margin-right: 20px }
|
|
||||||
.comment_list .user_head { width: 50px; height: 50px; border-radius: 50%; background: #f6f6f6 }
|
|
||||||
.comment_list .user_heads span { display: block; margin: 0; position: absolute; left: 12px; bottom: 0 }
|
|
||||||
.comment_list ul { /*width: 640px;*/ width: 660px; }
|
|
||||||
.comment_list .li_0 { font-family: "宋体" }
|
|
||||||
.comment_list .li_0 strong { font-size: 14px; color: #f00 }
|
|
||||||
.comment_list .li_1 { overflow: hidden }
|
|
||||||
.comment_list .user_name { color: #ed4259 }
|
|
||||||
.comment_list .li_2 { padding: 6px 0 }
|
|
||||||
.comment_list .li_3 { color: #999 }
|
|
||||||
.comment_list .reply { padding-left: 12px }
|
|
||||||
.comment_list .num { color: #ed4259; margin: 0 3px }
|
|
||||||
.comment_list .li_4 { line-height: 34px; padding-top: 8px; margin-top: 15px; border-top: 1px solid #eaeaea }
|
|
||||||
.pl_bar li { display: block }
|
|
||||||
.pl_bar .name { color: #666; padding-top: 2px; font-size: 14px }
|
|
||||||
.pl_bar .dec { font-size: 14px; line-height: 1.8; padding: 12px 0 }
|
|
||||||
.pl_bar .other { line-height: 24px; color: #999; font-size: 13px }
|
|
||||||
.pl_bar .other a { display: inline-block; color: #999 }
|
|
||||||
.pl_bar .reply { padding-left: 22px; background: url(../images/icon_reply.png) no-repeat 0 2px }
|
|
||||||
/*.no_comment { padding: 70px 14px 115px; color: #CCCCCC; text-align: center; font-size: 14px; }*/
|
/*.no_comment { padding: 70px 14px 115px; color: #CCCCCC; text-align: center; font-size: 14px; }*/
|
||||||
.reply_bar {
|
.reply_bar {
|
||||||
background: #f9f9f9;
|
background: #f9f9f9;
|
||||||
border: 1px solid #eee; border-radius: 6px;
|
border: 1px solid #eee;
|
||||||
|
border-radius: 6px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
line-height: 1.8;}
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
@ -457,8 +457,8 @@ html #layuicss-layer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.layui-layer-btn .layui-layer-btn0 {
|
.layui-layer-btn .layui-layer-btn0 {
|
||||||
border-color: #f70;
|
border-color: #3eaf7c;
|
||||||
background-color: #f70;
|
background-color: #3eaf7c;
|
||||||
color: #fff
|
color: #fff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,15 +12,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="">
|
<body class="">
|
||||||
|
|
||||||
<div class="header">
|
<div th:replace="crawl/header :: header">
|
||||||
<div class="mainNav" id="mainNav">
|
|
||||||
<div class="box_center cf"
|
|
||||||
style="text-align: center;height: 44px;line-height: 48px;color: #fff;font-size: 16px;">
|
|
||||||
|
|
||||||
小说精品屋爬虫管理
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="main box_center cf">
|
<div class="main box_center cf">
|
||||||
@ -165,7 +157,14 @@
|
|||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/crawl/addCrawlSingleTask",
|
url: "/crawl/addCrawlSingleTask",
|
||||||
data: {'sourceId': sourceId, 'sourceName': sourceName,'catId':catId,'sourceBookId' : sourceBookId,'bookName':bookName,'authorName':authorName},
|
data: {
|
||||||
|
'sourceId': sourceId,
|
||||||
|
'sourceName': sourceName,
|
||||||
|
'catId': catId,
|
||||||
|
'sourceBookId': sourceBookId,
|
||||||
|
'bookName': bookName,
|
||||||
|
'authorName': authorName
|
||||||
|
},
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
|
@ -12,15 +12,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="">
|
<body class="">
|
||||||
|
|
||||||
<div class="header">
|
<div th:replace="crawl/header :: header">
|
||||||
<div class="mainNav" id="mainNav">
|
|
||||||
<div class="box_center cf"
|
|
||||||
style="text-align: center;height: 44px;line-height: 48px;color: #fff;font-size: 16px;">
|
|
||||||
|
|
||||||
小说精品屋爬虫管理
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="main box_center cf">
|
<div class="main box_center cf">
|
||||||
|
@ -12,15 +12,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="">
|
<body class="">
|
||||||
|
|
||||||
<div class="header">
|
<div th:replace="crawl/header :: header">
|
||||||
<div class="mainNav" id="mainNav">
|
|
||||||
<div class="box_center cf"
|
|
||||||
style="text-align: center;height: 44px;line-height: 48px;color: #fff;font-size: 16px;">
|
|
||||||
|
|
||||||
小说精品屋爬虫管理
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="main box_center cf">
|
<div class="main box_center cf">
|
||||||
@ -152,6 +144,9 @@
|
|||||||
示例:<b><script></b>
|
示例:<b><script></b>
|
||||||
<li><input type="text" id="contentEnd" class="s_input icon_key"
|
<li><input type="text" id="contentEnd" class="s_input icon_key"
|
||||||
placeholder="小说内容结束截取字符串:"></li>
|
placeholder="小说内容结束截取字符串:"></li>
|
||||||
|
示例:<b><div\s+id="content_tip">\s*<b>([^/]+)</b>\s*</div></b>
|
||||||
|
<li><textarea id="filterContent"
|
||||||
|
placeholder="过滤内容(多个内容换行)" rows="5" cols="52"></textarea></li>
|
||||||
|
|
||||||
<li><input type="button" onclick="addCrawlSource()" name="btnRegister" value="提交"
|
<li><input type="button" onclick="addCrawlSource()" name="btnRegister" value="提交"
|
||||||
id="btnRegister" class="btn_red"></li>
|
id="btnRegister" class="btn_red"></li>
|
||||||
@ -413,6 +408,9 @@
|
|||||||
|
|
||||||
crawlRule.contentEnd = contentEnd;
|
crawlRule.contentEnd = contentEnd;
|
||||||
|
|
||||||
|
var filterContent = $("#filterContent").val();
|
||||||
|
crawlRule.filterContent = filterContent;
|
||||||
|
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
<head>
|
<head>
|
||||||
@ -12,14 +12,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="">
|
<body class="">
|
||||||
|
|
||||||
<div class="header">
|
<div th:replace="crawl/header :: header">
|
||||||
<div class="mainNav" id="mainNav">
|
|
||||||
<div class="box_center cf" style="text-align: center;height: 44px;line-height: 48px;color: #fff;font-size: 16px;">
|
|
||||||
|
|
||||||
小说精品屋爬虫管理
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="main box_center cf">
|
<div class="main box_center cf">
|
||||||
@ -41,6 +34,7 @@
|
|||||||
<h2 class="fl">爬虫源列表</h2>
|
<h2 class="fl">爬虫源列表</h2>
|
||||||
<div class="fr"><a href="/crawl/crawlSource_add.html" class="btn_red">增加爬虫源</a>
|
<div class="fr"><a href="/crawl/crawlSource_add.html" class="btn_red">增加爬虫源</a>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="divData" class="updateTable">
|
<div id="divData" class="updateTable">
|
||||||
<table cellpadding="0" cellspacing="0">
|
<table cellpadding="0" cellspacing="0">
|
||||||
@ -69,7 +63,6 @@
|
|||||||
<tbody id="crawlSourceList">
|
<tbody id="crawlSourceList">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<div class="pageBox cf" id="shellPage">
|
<div class="pageBox cf" id="shellPage">
|
||||||
@ -121,6 +114,7 @@
|
|||||||
search(1, 10);
|
search(1, 10);
|
||||||
|
|
||||||
var pageCrawlSourceList = null;
|
var pageCrawlSourceList = null;
|
||||||
|
|
||||||
function search(curr, limit) {
|
function search(curr, limit) {
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -201,6 +195,7 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCrawlSource(crawlSourceId) {
|
function updateCrawlSource(crawlSourceId) {
|
||||||
|
|
||||||
localStorage.setItem("crawlSourceId", crawlSourceId);
|
localStorage.setItem("crawlSourceId", crawlSourceId);
|
||||||
@ -244,9 +239,6 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
@ -12,15 +12,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="">
|
<body class="">
|
||||||
|
|
||||||
<div class="header">
|
<div th:replace="crawl/header :: header">
|
||||||
<div class="mainNav" id="mainNav">
|
|
||||||
<div class="box_center cf"
|
|
||||||
style="text-align: center;height: 44px;line-height: 48px;color: #fff;font-size: 16px;">
|
|
||||||
|
|
||||||
小说精品屋爬虫管理
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="main box_center cf">
|
<div class="main box_center cf">
|
||||||
@ -28,9 +20,9 @@
|
|||||||
<div class="my_l">
|
<div class="my_l">
|
||||||
|
|
||||||
<ul class="log_list">
|
<ul class="log_list">
|
||||||
<li><a class="link_1 on" href="/">爬虫源管理</a></li>
|
<li><a class="link_1" href="/">爬虫源管理</a></li>
|
||||||
<li><a class="link_1" href="/crawl/crawlSingleTask_list.html">单本采集管理</a></li>
|
<li><a class="link_1" href="/crawl/crawlSingleTask_list.html">单本采集管理</a></li>
|
||||||
<li><a class="link_1" href="/crawl/crawlSource_test.html" target="_blank" >规则测试</a></li>
|
<li><a class="link_1 on" href="/crawl/crawlSource_test.html" target="_blank">规则测试</a></li>
|
||||||
<!--<li><a class="link_1 " href="/user/userinfo.html">批量小说爬取</a></li>
|
<!--<li><a class="link_1 " href="/user/userinfo.html">批量小说爬取</a></li>
|
||||||
<li><a class="link_4 " href="/user/favorites.html">单本小说爬取</a></li>-->
|
<li><a class="link_4 " href="/user/favorites.html">单本小说爬取</a></li>-->
|
||||||
</ul>
|
</ul>
|
||||||
@ -64,12 +56,12 @@
|
|||||||
示例:<b>value=\"(\\d+)/\\d+\"</b>
|
示例:<b>value=\"(\\d+)/\\d+\"</b>
|
||||||
<li><input type="text" id="rule" class="s_input icon_name" placeholder="规则"></li>
|
<li><input type="text" id="rule" class="s_input icon_name" placeholder="规则"></li>
|
||||||
示例:<b>1强制刷新 空或0使用缓存</b>
|
示例:<b>1强制刷新 空或0使用缓存</b>
|
||||||
<li><input type="text" id="isRefresh" class="s_input icon_name" placeholder="是否强制刷新"></li>
|
<li><input type="text" id="isRefresh" class="s_input icon_name" placeholder="是否强制刷新">
|
||||||
|
</li>
|
||||||
|
|
||||||
<li><textarea rows="20" cols="100" id="resultMap"></textarea></li>
|
<li><textarea rows="20" cols="100" id="resultMap"></textarea></li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li><input type="button" onclick="testCrawlSource()" name="btnRegister" value="测试"
|
<li><input type="button" onclick="testCrawlSource()" name="btnRegister" value="测试"
|
||||||
id="btnRegister" class="btn_red"></li>
|
id="btnRegister" class="btn_red"></li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -125,6 +117,7 @@
|
|||||||
var testParseRule = localStorage.getItem("testParseRule");
|
var testParseRule = localStorage.getItem("testParseRule");
|
||||||
$("#rule").val(testParseRule);
|
$("#rule").val(testParseRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCrawlSource() {
|
function testCrawlSource() {
|
||||||
|
|
||||||
var data = {};
|
var data = {};
|
||||||
|
@ -12,15 +12,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="">
|
<body class="">
|
||||||
|
|
||||||
<div class="header">
|
<div th:replace="crawl/header :: header">
|
||||||
<div class="mainNav" id="mainNav">
|
|
||||||
<div class="box_center cf"
|
|
||||||
style="text-align: center;height: 44px;line-height: 48px;color: #fff;font-size: 16px;">
|
|
||||||
|
|
||||||
小说精品屋爬虫管理
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="main box_center cf">
|
<div class="main box_center cf">
|
||||||
@ -153,6 +145,10 @@
|
|||||||
示例:<b><script></b>
|
示例:<b><script></b>
|
||||||
<li><input type="text" id="contentEnd" class="s_input icon_key"
|
<li><input type="text" id="contentEnd" class="s_input icon_key"
|
||||||
placeholder="小说内容结束截取字符串:"></li>
|
placeholder="小说内容结束截取字符串:"></li>
|
||||||
|
示例:<b><div\s+id="content_tip">\s*<b>([^/]+)</b>\s*</div></b>
|
||||||
|
<li><textarea id="filterContent"
|
||||||
|
placeholder="过滤内容(多个内容换行)" rows="5" cols="52"></textarea></li>
|
||||||
|
|
||||||
|
|
||||||
<li><input type="button" onclick="updateCrawlSource()" name="btnRegister" value="提交"
|
<li><input type="button" onclick="updateCrawlSource()" name="btnRegister" value="提交"
|
||||||
id="btnRegister" class="btn_red"></li>
|
id="btnRegister" class="btn_red"></li>
|
||||||
@ -229,6 +225,7 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadPage(data) {
|
function loadPage(data) {
|
||||||
$("#sourceId").val(data.id);
|
$("#sourceId").val(data.id);
|
||||||
$("#sourceName").val(data.sourceName);
|
$("#sourceName").val(data.sourceName);
|
||||||
@ -276,9 +273,11 @@
|
|||||||
$("#bookContentUrl").val(crawlRule.bookContentUrl);
|
$("#bookContentUrl").val(crawlRule.bookContentUrl);
|
||||||
$("#contentStart").val(crawlRule.contentStart);
|
$("#contentStart").val(crawlRule.contentStart);
|
||||||
$("#contentEnd").val(crawlRule.contentEnd);
|
$("#contentEnd").val(crawlRule.contentEnd);
|
||||||
|
$("#filterContent").val(crawlRule.filterContent);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
load();
|
load();
|
||||||
|
|
||||||
function updateCrawlSource() {
|
function updateCrawlSource() {
|
||||||
@ -494,6 +493,9 @@
|
|||||||
|
|
||||||
crawlRule.contentEnd = contentEnd;
|
crawlRule.contentEnd = contentEnd;
|
||||||
|
|
||||||
|
var filterContent = $("#filterContent").val();
|
||||||
|
crawlRule.filterContent = filterContent;
|
||||||
|
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
|