mirror of
https://github.com/201206030/novel-plus.git
synced 2025-07-01 07:16:39 +00:00
Compare commits
70 Commits
release_v3
...
v3.5.1
Author | SHA1 | Date | |
---|---|---|---|
19d4c6b778 | |||
d22200b8c7 | |||
43fe1150fd | |||
65b65f874f | |||
3b6bc859a5 | |||
cfc55a6c92 | |||
0a80c5662d | |||
02fd0d7e25 | |||
521142a792 | |||
c567e37423 | |||
b5e0814eb4 | |||
ca6c2aec96 | |||
34859c839b | |||
039f9d9cf8 | |||
224829dd1f | |||
1a5122209a | |||
48aff7cf37 | |||
e673f9be9d | |||
20469bd669 | |||
755300db3c | |||
a790f8042d | |||
d0db2021a6 | |||
c403fc7496 | |||
e4927d7ac6 | |||
a00a2141f2 | |||
7cc7d8b541 | |||
e4822979e2 | |||
ab741ec6bf | |||
057c0646cd | |||
57a9cd09ef | |||
1a49e2a340 | |||
f8411c2337 | |||
343a741c21 | |||
f1a5fb4813 | |||
0428356bd4 | |||
c01097cd5f | |||
7e650a0a04 | |||
45c59ecc37 | |||
5e3962fef4 | |||
7f5035e369 | |||
44aad39847 | |||
6ad51908d5 | |||
f03ab953d0 | |||
5cc9dfa1bc | |||
2fbda60617 | |||
39c19ac004 | |||
7494fe431a | |||
c9f1500976 | |||
f61c252e71 | |||
6fd183c2ae | |||
c3daaecaaa | |||
1b6cc8ccd5 | |||
0a10504461 | |||
1046a7ffc1 | |||
612555dbe6 | |||
d5768e4011 | |||
5982eb623f | |||
85ad5fa3b2 | |||
bdc81f7676 | |||
f31c86f362 | |||
45d8902429 | |||
ff9696bb7e | |||
cacebcaa33 | |||
355cb80458 | |||
a8c74d061c | |||
a713b66c1b | |||
e9d915c1fe | |||
cd3520971d | |||
dc4c9138ee | |||
f830600c3e |
155
README.md
155
README.md
@ -2,26 +2,31 @@
|
||||
|
||||
# 小说精品屋-plus
|
||||
|
||||
[](https://github.com/201206030/novel-plus)
|
||||
[](https://github.com/201206030/novel-plus)
|
||||
[](https://gitee.com/novel_dev_team/novel-plus)
|
||||
[](https://gitee.com/novel_dev_team/novel-plus)
|
||||
|
||||
#### 官网
|
||||
|
||||
https://xiongxyang.gitee.io
|
||||
|
||||
#### 新项目:小说精品屋-微服务版
|
||||
|
||||
基于小说精品屋-plus构建的Spring Cloud 微服务小说门户平台。
|
||||
|
||||
Gitee仓库地址: https://gitee.com/xiongxyang/novel-cloud
|
||||
|
||||
GitHub仓库地址: https://github.com/201206030/novel-cloud
|
||||
|
||||
Gitee仓库地址: https://gitee.com/novel_dev_team/novel-cloud
|
||||
|
||||
#### 演示地址
|
||||
|
||||
[点击前往](http://47.106.243.172:8888/)
|
||||
|
||||
|
||||
#### 前言
|
||||
|
||||
小说精品屋-plus致力于打造一个完整的商用小说门户平台,使用前建议先阅读此文档。
|
||||
|
||||
#### 项目介绍
|
||||
|
||||
小说精品屋-plus是在[小说精品屋](https://github.com/201206030/fiction_house)的基础上,去除了漫画和弹幕模块,专注于小说,是一个多端(PC、移动)阅读、功能完善的小说原创/爬虫网站项目,既包含了作家专区供原创作者上传小说,又提供了爬虫工具通过规则多线程全自动采集任意小说网站数据(已兼容99%的小说网站),新书自动入库,老书自动更新。
|
||||
小说精品屋-plus是在[小说精品屋](https://github.com/201206030/fiction_house)的基础上,去除了漫画和弹幕模块,专注于小说,是一个多端(PC、WAP)阅读、功能完善的原创文学CMS系统,由前台门户系统、作家后台管理系统、平台后台管理系统、爬虫管理系统等多个子系统构成,支持会员充值、订阅模式、新闻发布和实时统计报表等功能。
|
||||
|
||||
小说精品屋-plus重新进行了数据库设计、代码重构和功能增强,提升了程序整体的可读性和性能,增加了很多商用特性。主要升级如下:
|
||||
|
||||
@ -29,6 +34,7 @@ GitHub仓库地址: https://github.com/201206030/novel-cloud
|
||||
- [x] 服务端代码重构,MyBatis3升级为MyBatis3DynamicSql。
|
||||
- [x] 移动站与PC站站点分离,浏览器自动识别跳转。
|
||||
- [x] PC站UI更新。
|
||||
- [x] 支持前端模版自定义,内置多套模版。
|
||||
- [x] 新闻模块。
|
||||
- [x] 排行榜。
|
||||
- [x] 小说评论模块。
|
||||
@ -44,9 +50,10 @@ GitHub仓库地址: https://github.com/201206030/novel-cloud
|
||||
```
|
||||
novel-plus -- 父工程
|
||||
├── novel-common -- 通用模块
|
||||
├── novel-front -- 前台门户系统
|
||||
├── novel-crawl -- 爬虫管理系统
|
||||
└── novel-admin -- 后台管理系统
|
||||
├── novel-front -- 前台门户&作家后台管理子系统(可拆分)
|
||||
├── novel-crawl -- 爬虫管理子系统
|
||||
├── novel-admin -- 平台后台管理子系统
|
||||
└── templates -- 前端模版
|
||||
```
|
||||
|
||||
#### 技术选型
|
||||
@ -76,11 +83,22 @@ novel-plus -- 父工程
|
||||
| Layui | 前端UI
|
||||
|
||||
|
||||
#### PC站截图
|
||||
#### 开发工具
|
||||
感谢Jetbrains公司提供的免费License。
|
||||
|
||||
[]( https://www.jetbrains.com/?from=小说精品屋)
|
||||
|
||||
|
||||
#### 接口文档
|
||||
|
||||
[点击查看接口文档示例](doc/api/api.md)
|
||||
|
||||
#### 橙色主题模版截图
|
||||
##### PC站截图
|
||||
|
||||
1. 首页
|
||||
|
||||

|
||||

|
||||
|
||||
2. 分类索引页
|
||||
|
||||
@ -88,7 +106,7 @@ novel-plus -- 父工程
|
||||
|
||||
3. 搜索页
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
@ -130,31 +148,31 @@ novel-plus -- 父工程
|
||||
|
||||

|
||||
|
||||
#### 手机站截图
|
||||
##### 手机站截图
|
||||
|
||||
1. 首页
|
||||
|
||||
<img src="https://s3.ax1x.com/2020/12/04/DbsSoj.jpg" alt="index" style="zoom:33%;" />
|
||||
<img src="https://s3.ax1x.com/2020/12/27/r5447n.jpg" alt="index" width="300" />
|
||||
|
||||
2. 小说列表页
|
||||
|
||||
<img src="https://s3.ax1x.com/2020/12/04/DbrfsO.jpg" alt="微信图片_20190904181558" style="zoom: 33%;" />
|
||||
<img src="https://s3.ax1x.com/2020/12/27/r55xKg.jpg" alt="微信图片_20190904181558" width="300" />
|
||||
|
||||
3. 小说详情页
|
||||
|
||||
<img src="https://s3.ax1x.com/2020/12/04/DbsklV.jpg" alt="QQ图片20191018161901" style="zoom:33%;" />
|
||||
<img src="https://s3.ax1x.com/2020/12/28/roZWOf.jpg" alt="QQ图片20191018161901" width="300" />
|
||||
|
||||
4. 小说阅读页
|
||||
|
||||
<img src="https://s3.ax1x.com/2020/12/04/Dbsew4.jpg" alt="QQ图片20191018161901" style="zoom:33%;" />
|
||||
<img src="https://s3.ax1x.com/2020/12/27/r55Stx.jpg" alt="QQ图片20191018161901" width="300" />
|
||||
|
||||
#### 爬虫管理系统截图
|
||||
##### 爬虫管理系统截图
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
#### 后台管理系统截图
|
||||
##### 后台管理系统截图
|
||||
|
||||

|
||||
|
||||
@ -164,31 +182,98 @@ novel-plus -- 父工程
|
||||
|
||||

|
||||
|
||||
#### 安装步骤
|
||||
#### 深色主题模版截图
|
||||
##### PC站截图
|
||||
|
||||
1. 首页
|
||||
|
||||

|
||||
|
||||
##### 手机站截图
|
||||
1. 首页
|
||||
|
||||

|
||||
|
||||
4. 小说详情页
|
||||
|
||||

|
||||
|
||||
5. 目录页
|
||||
|
||||

|
||||
|
||||
5. 小说阅读页
|
||||
|
||||

|
||||
|
||||
#### 蓝色主题模版截图(更新中)
|
||||
|
||||

|
||||
|
||||
#### 安装步骤(源码,小白请看其他安装教程)
|
||||
|
||||
##### 数据库安装:
|
||||
|
||||
1. 安装MySQL软件。
|
||||
2. 修改MySQL`max_allowed_packet `配置(建议100M)。
|
||||
3. 新建数据库,设置编码为utf8mb4。
|
||||
4. 执行sql/novel_plus.sql脚本文件。
|
||||
4. 执行doc/sql/novel_plus.sql脚本文件。
|
||||
|
||||
##### 爬虫管理系统安装:
|
||||
|
||||
1. 修改novel-common模块下application-dev.yml文件中的数据库的配置。
|
||||
1. 修改novel-common模块下application-common-dev.yml(dev环境,默认环境)或application-common-prod.yml(prod环境,需要在application.yml配置文件中切换)配置文件中的数据库配置。
|
||||
2. 修改novel-crawl模块下application.yml文件中的管理员账号密码。
|
||||
3. 启动程序,打开浏览器,默认8081端口访问。
|
||||
4. 选择已有或新增爬虫源(支持自定义爬虫规则),点击`开启`按钮,开始爬取小说数据。
|
||||
|
||||
##### 前台小说门户安装:
|
||||
##### 前台小说门户安装(dev环境跳过3、4步骤):
|
||||
|
||||
1. 修改novel-common模块下application-dev.yml文件中的数据库的配置。
|
||||
2. 启动程序,打开浏览器,默认8080端口访问。
|
||||
1. 修改novel-common模块下application-common-dev.yml(dev环境,默认环境)或application-common-prod.yml(prod环境,需要在application.yml配置文件中切换)配置文件中的数据库配置。
|
||||
|
||||
2. 修改novel-front模块下application-website配置文件中的网站信息。
|
||||
|
||||
```
|
||||
#网站配置
|
||||
website:
|
||||
#网站名
|
||||
name: 小说精品屋
|
||||
#域名
|
||||
domain: xiongxyang.gitee.io
|
||||
#SEO关键词
|
||||
keyword: ${website.name},小说,小说CMS,原创文学系统,开源小说系统,免费小说建站程序
|
||||
#SEO描述
|
||||
description: ${website.name}是一个多端(PC、WAP)阅读、功能完善的原创文学CMS系统,由前台门户系统、作家后台管理系统、平台后台管理系统、爬虫管理系统等多个子系统构成,支持会员充值、订阅模式、新闻发布和实时统计报表等功能,新书自动入库,老书自动更新。
|
||||
#联系QQ
|
||||
qq: 1179705413
|
||||
```
|
||||
|
||||
3. prod环境下需要修改novel-front模块下application-prod.yml配置文件中的模版名为你需要使用的模版名(templates文件夹下的模版文件夹名,内置orange和dark两套模版,prod环境下才支持多模版)。
|
||||
|
||||
```
|
||||
#模版配置
|
||||
templates:
|
||||
#模版名
|
||||
name: orange
|
||||
```
|
||||
|
||||
4. prod环境下的jar包形式部署时,需要复制templates文件夹到jar文件的相同目录下。
|
||||
|
||||
5. 启动程序,打开浏览器,默认8080端口访问。
|
||||
|
||||
**喜欢此项目的可以给我的GitHub和Gitee加个Star支持一下 。**
|
||||
|
||||
#### 其他安装教程
|
||||
|
||||
##### version>=3.5.0版本
|
||||
|
||||
包安装及低版本升级教程:[点击前往](https://my.oschina.net/java2nb/blog/4914688)
|
||||
|
||||
##### 3.3.0<=version<3.5.0版本
|
||||
|
||||
包安装教程:[点击前往](https://my.oschina.net/java2nb/blog/4842472)
|
||||
|
||||
##### version<3.3.0版本
|
||||
|
||||
包安装教程:[点击前往](https://my.oschina.net/java2nb/blog/4272630)
|
||||
|
||||
宝塔安装教程(非官方):[点击前往](https://www.daniao.org/9166.html)
|
||||
@ -197,15 +282,23 @@ docker安装教程:[点击前往](https://my.oschina.net/java2nb/blog/4271989)
|
||||
|
||||
#### 代码仓库
|
||||
|
||||
Gitee仓库地址: https://gitee.com/xiongxyang/novel-plus
|
||||
|
||||
GitHub仓库地址: https://github.com/201206030/novel-plus
|
||||
|
||||
Gitee仓库地址: https://gitee.com/novel_dev_team/novel-plus
|
||||
|
||||
#### QQ交流群
|
||||
|
||||

|
||||
[点击前往官网查看](https://xiongxyang.gitee.io/service.htm)
|
||||
|
||||
#### 微信公众号(发布最新更新资讯)
|
||||
问问题的三要素
|
||||
|
||||
1. 说明背景,使用了哪个模块,要做什么?
|
||||
|
||||
2. 怎么输入或操作的得到了什么结果? 截图,日志
|
||||
|
||||
3. 哪里不明白或有什么疑问 ?
|
||||
|
||||
#### 微信公众号(发布最新更新资讯、最新前端模版、最新爬虫规则、技术文档等)
|
||||
|
||||

|
||||
|
||||
@ -219,7 +312,7 @@ docker安装教程:[点击前往](https://my.oschina.net/java2nb/blog/4271989)
|
||||
|
||||

|
||||
|
||||
### 免责声明
|
||||
#### 免责声明
|
||||
|
||||
本项目提供的爬虫工具仅用于采集项目初期的测试数据,请勿用于商业盈利。
|
||||
用户使用本系统从事任何违法违规的事情,一切后果由用户自行承担,作者不承担任何责任。
|
||||
|
116
doc/api/api.md
Normal file
116
doc/api/api.md
Normal file
@ -0,0 +1,116 @@
|
||||
|
||||
<h1 class="curproject-name"> 小说精品屋-plus </h1>
|
||||
小说精品屋-plus接口
|
||||
|
||||
|
||||
# 作家模块
|
||||
|
||||
## 小说章节分页列表查询接口
|
||||
<a id=小说章节分页列表查询接口> </a>
|
||||
### 基本信息
|
||||
|
||||
**Path:** /book/queryIndexList
|
||||
|
||||
**Method:** GET
|
||||
|
||||
**接口描述:**
|
||||
<p>作家后台章节管理页面需要请求该接口获取小说章节分页列表信息</p>
|
||||
|
||||
|
||||
### 请求参数
|
||||
**Query**
|
||||
|
||||
| 参数名称 | 是否必须 | 示例 | 备注 |
|
||||
| ------------ | ------------ | ------------ | ------------ |
|
||||
| bookId | 是 | 1334337530296893441 | 小说ID |
|
||||
| curr | 否 | 1 | 查询页码,默认1 |
|
||||
| limit | 否 | 5 | 分页大小,默认5 |
|
||||
|
||||
### 返回数据
|
||||
|
||||
<table>
|
||||
<thead class="ant-table-thead">
|
||||
<tr>
|
||||
<th key=name>名称</th><th key=type>类型</th><th key=required>是否必须</th><th key=default>默认值</th><th key=desc>备注</th><th key=sub>其他信息</th>
|
||||
</tr>
|
||||
</thead><tbody className="ant-table-tbody"><tr key=0-0><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> code</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应状态吗,200表示成功</span></td><td key=5></td></tr><tr key=0-1><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> msg</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应信息</span></td><td key=5></td></tr><tr key=0-2><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> data</span></td><td key=1><span>object</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应数据</span></td><td key=5></td></tr><tr key=0-2-0><td key=0><span style="padding-left: 20px"><span style="color: #8c8a8a">├─</span> total</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">总数量</span></td><td key=5></td></tr><tr key=0-2-1><td key=0><span style="padding-left: 20px"><span style="color: #8c8a8a">├─</span> list</span></td><td key=1><span>object []</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">章节数据集合</span></td><td key=5><p key=3><span style="font-weight: '700'">item 类型: </span><span>object</span></p></td></tr><tr key=0-2-1-0><td key=0><span style="padding-left: 40px"><span style="color: #8c8a8a">├─</span> id</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">章节ID</span></td><td key=5></td></tr><tr key=0-2-1-1><td key=0><span style="padding-left: 40px"><span style="color: #8c8a8a">├─</span> bookId</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">小说ID</span></td><td key=5></td></tr><tr key=0-2-1-2><td key=0><span style="padding-left: 40px"><span style="color: #8c8a8a">├─</span> indexName</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">章节名</span></td><td key=5></td></tr><tr key=0-2-1-3><td key=0><span style="padding-left: 40px"><span style="color: #8c8a8a">├─</span> isVip</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">是否收费,1:收费,0:免费</span></td><td key=5></td></tr><tr key=0-2-1-4><td key=0><span style="padding-left: 40px"><span style="color: #8c8a8a">├─</span> updateTime</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">更新时间</span></td><td key=5></td></tr><tr key=0-2-2><td key=0><span style="padding-left: 20px"><span style="color: #8c8a8a">├─</span> pageNum</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">页码</span></td><td key=5></td></tr><tr key=0-2-3><td key=0><span style="padding-left: 20px"><span style="color: #8c8a8a">├─</span> pageSize</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">分页大小</span></td><td key=5></td></tr><tr key=0-2-4><td key=0><span style="padding-left: 20px"><span style="color: #8c8a8a">├─</span> size</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">当前页数量</span></td><td key=5></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## 小说章节删除接口
|
||||
<a id=小说章节删除接口> </a>
|
||||
### 基本信息
|
||||
|
||||
**Path:** /author/deleteIndex/{indexId}
|
||||
|
||||
**Method:** DELETE
|
||||
|
||||
**接口描述:**
|
||||
<p>作家后台章节管理页面点击删除按钮请求该接口删除小说章节内容</p>
|
||||
|
||||
|
||||
### 请求参数
|
||||
**Headers**
|
||||
|
||||
| 参数名称 | 参数值 | 是否必须 | 示例 | 备注 |
|
||||
| ------------ | ------------ | ------------ | ------------ | ------------ |
|
||||
| Content-Type | application/x-www-form-urlencoded | 是 | | |
|
||||
| Authorization | | 是 | eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2MDgzNDg0NzksInN1YiI6IntcImlkXCI6MTI1NTA2MDMyODMyMjAyNzUyMCxcInVzZXJuYW1lXCI6XCIxMzU2MDQyMTMyNFwiLFwibmlja05hbWVcIjpcIjEzNTYwNDIxMzI0XCJ9IiwiY3JlYXRlZCI6MTYwNzc0MzY3OTkxM30.0qhwis_zPb6t8wGNejMhDZ2iHCL9Tgh2UHd1gcQBCp8t6RW3ggSwtfo4l_RgMT_v8jOkLW91GzTVWlNnTE6LCA | 认证JWT,请求登录接口成功后返回 |
|
||||
**路径参数**
|
||||
|
||||
| 参数名称 | 示例 | 备注 |
|
||||
| ------------ | ------------ | ------------ |
|
||||
| indexId | 1337603246936645632 | 章节ID |
|
||||
|
||||
### 返回数据
|
||||
|
||||
<table>
|
||||
<thead class="ant-table-thead">
|
||||
<tr>
|
||||
<th key=name>名称</th><th key=type>类型</th><th key=required>是否必须</th><th key=default>默认值</th><th key=desc>备注</th><th key=sub>其他信息</th>
|
||||
</tr>
|
||||
</thead><tbody className="ant-table-tbody"><tr key=0-0><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> code</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应状态吗,200表示成功</span></td><td key=5></td></tr><tr key=0-1><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> msg</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应信息</span></td><td key=5></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## 小说章节发布接口
|
||||
<a id=小说章节发布接口> </a>
|
||||
### 基本信息
|
||||
|
||||
**Path:** /author/addBookContent
|
||||
|
||||
**Method:** POST
|
||||
|
||||
**接口描述:**
|
||||
<p>作家后台章节发布页面点击提交按钮请求该接口新增小说章节内容</p>
|
||||
|
||||
|
||||
### 请求参数
|
||||
**Headers**
|
||||
|
||||
| 参数名称 | 参数值 | 是否必须 | 示例 | 备注 |
|
||||
| ------------ | ------------ | ------------ | ------------ | ------------ |
|
||||
| Content-Type | application/x-www-form-urlencoded | 是 | | |
|
||||
| Authorization | | 是 | eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2MDgzNDg0NzksInN1YiI6IntcImlkXCI6MTI1NTA2MDMyODMyMjAyNzUyMCxcInVzZXJuYW1lXCI6XCIxMzU2MDQyMTMyNFwiLFwibmlja05hbWVcIjpcIjEzNTYwNDIxMzI0XCJ9IiwiY3JlYXRlZCI6MTYwNzc0MzY3OTkxM30.0qhwis_zPb6t8wGNejMhDZ2iHCL9Tgh2UHd1gcQBCp8t6RW3ggSwtfo4l_RgMT_v8jOkLW91GzTVWlNnTE6LCA | 认证JWT,请求登录接口成功后返回 |
|
||||
**Body**
|
||||
|
||||
| 参数名称 | 参数类型 | 是否必须 | 示例 | 备注 |
|
||||
| ------------ | ------------ | ------------ | ------------ | ------------ |
|
||||
| bookId | text | 是 | 1334337530296893441 | 小说ID |
|
||||
| indexName | text | 是 | 第六章未婚妻(下) | 章节名 |
|
||||
| content | text | 是 | 开始之时,李七夜还是生疏无比,那怕他对于刀术的所有奥义了然于胸,但是,他出刀之时依然会颤抖,无法达到妙及巅毫的要求。 | 章节内容 |
|
||||
| isVip | text | 是 | 1 | 是否收费,1:收费,0:免费 |
|
||||
|
||||
|
||||
|
||||
### 返回数据
|
||||
|
||||
<table>
|
||||
<thead class="ant-table-thead">
|
||||
<tr>
|
||||
<th key=name>名称</th><th key=type>类型</th><th key=required>是否必须</th><th key=default>默认值</th><th key=desc>备注</th><th key=sub>其他信息</th>
|
||||
</tr>
|
||||
</thead><tbody className="ant-table-tbody"><tr key=0-0><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> code</span></td><td key=1><span>number</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应状态吗,200表示成功</span></td><td key=5></td></tr><tr key=0-1><td key=0><span style="padding-left: 0px"><span style="color: #8c8a8a"></span> msg</span></td><td key=1><span>string</span></td><td key=2>必须</td><td key=3></td><td key=4><span style="white-space: pre-wrap">响应信息</span></td><td key=5></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -491,13 +491,6 @@ CREATE TABLE `sys_dept` (
|
||||
-- ----------------------------
|
||||
-- Records of sys_dept
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_dept` VALUES ('6', '0', '研发部', '1', '1');
|
||||
INSERT INTO `sys_dept` VALUES ('7', '6', '研發一部', '1', '1');
|
||||
INSERT INTO `sys_dept` VALUES ('8', '6', '研发二部', '2', '1');
|
||||
INSERT INTO `sys_dept` VALUES ('9', '0', '销售部', '2', '1');
|
||||
INSERT INTO `sys_dept` VALUES ('10', '9', '销售一部', '1', '1');
|
||||
INSERT INTO `sys_dept` VALUES ('11', '0', '产品部', '3', '1');
|
||||
INSERT INTO `sys_dept` VALUES ('12', '11', '产品一部', '1', '1');
|
||||
INSERT INTO `sys_dept` VALUES ('13', '0', '测试部', '5', '1');
|
||||
INSERT INTO `sys_dept` VALUES ('14', '13', '测试一部', '1', '1');
|
||||
INSERT INTO `sys_dept` VALUES ('15', '13', '测试二部', '2', '1');
|
||||
@ -894,52 +887,6 @@ CREATE TABLE `sys_log` (
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1412 DEFAULT CHARSET=utf8 COMMENT='系统日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_log
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_log` VALUES ('1369', '-1', '获取用户信息为空', '登录', '462', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:09:21');
|
||||
INSERT INTO `sys_log` VALUES ('1370', '-1', '获取用户信息为空', '登录', '19', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:09:26');
|
||||
INSERT INTO `sys_log` VALUES ('1371', '1', 'admin', '登录', '98', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:09:33');
|
||||
INSERT INTO `sys_log` VALUES ('1372', '1', 'admin', '请求访问主页', '372', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:09:33');
|
||||
INSERT INTO `sys_log` VALUES ('1373', '1', 'admin', '请求访问主页', '28', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:12:41');
|
||||
INSERT INTO `sys_log` VALUES ('1374', '1', 'admin', '编辑角色', '11', 'com.java2nb.system.controller.RoleController.edit()', null, '127.0.0.1', '2020-05-13 11:18:42');
|
||||
INSERT INTO `sys_log` VALUES ('1375', '1', 'admin', '添加菜单', '2', 'com.java2nb.system.controller.MenuController.add()', null, '127.0.0.1', '2020-05-13 11:19:55');
|
||||
INSERT INTO `sys_log` VALUES ('1376', '1', 'admin', '保存菜单', '225', 'com.java2nb.system.controller.MenuController.save()', null, '127.0.0.1', '2020-05-13 11:24:42');
|
||||
INSERT INTO `sys_log` VALUES ('1377', '1', 'admin', '编辑菜单', '15', 'com.java2nb.system.controller.MenuController.edit()', null, '127.0.0.1', '2020-05-13 11:24:54');
|
||||
INSERT INTO `sys_log` VALUES ('1378', '1', 'admin', '编辑菜单', '11', 'com.java2nb.system.controller.MenuController.edit()', null, '127.0.0.1', '2020-05-13 11:24:58');
|
||||
INSERT INTO `sys_log` VALUES ('1379', '1', 'admin', '更新菜单', '241', 'com.java2nb.system.controller.MenuController.update()', null, '127.0.0.1', '2020-05-13 11:25:12');
|
||||
INSERT INTO `sys_log` VALUES ('1380', '1', 'admin', '编辑菜单', '8', 'com.java2nb.system.controller.MenuController.edit()', null, '127.0.0.1', '2020-05-13 11:25:16');
|
||||
INSERT INTO `sys_log` VALUES ('1381', '1', 'admin', '更新菜单', '199', 'com.java2nb.system.controller.MenuController.update()', null, '127.0.0.1', '2020-05-13 11:25:26');
|
||||
INSERT INTO `sys_log` VALUES ('1382', '1', 'admin', '编辑角色', '13', 'com.java2nb.system.controller.RoleController.edit()', null, '127.0.0.1', '2020-05-13 11:26:11');
|
||||
INSERT INTO `sys_log` VALUES ('1383', '1', 'admin', '更新角色', '931', 'com.java2nb.system.controller.RoleController.update()', null, '127.0.0.1', '2020-05-13 11:26:36');
|
||||
INSERT INTO `sys_log` VALUES ('1384', '-1', '获取用户信息为空', '登录', '11', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:27:02');
|
||||
INSERT INTO `sys_log` VALUES ('1385', '1', 'admin', '登录', '19', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:27:08');
|
||||
INSERT INTO `sys_log` VALUES ('1386', '1', 'admin', '请求访问主页', '27', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:27:08');
|
||||
INSERT INTO `sys_log` VALUES ('1387', '1', 'admin', '登录', '272', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:27:56');
|
||||
INSERT INTO `sys_log` VALUES ('1388', '1', 'admin', '请求访问主页', '109', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:27:56');
|
||||
INSERT INTO `sys_log` VALUES ('1389', '1', 'admin', '编辑角色', '8', 'com.java2nb.system.controller.RoleController.edit()', null, '127.0.0.1', '2020-05-13 11:30:36');
|
||||
INSERT INTO `sys_log` VALUES ('1390', '1', 'admin', '更新角色', '567', 'com.java2nb.system.controller.RoleController.update()', null, '127.0.0.1', '2020-05-13 11:30:42');
|
||||
INSERT INTO `sys_log` VALUES ('1391', '-1', '获取用户信息为空', '登录', '246', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:31:38');
|
||||
INSERT INTO `sys_log` VALUES ('1392', '1', 'admin', '登录', '38', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:31:42');
|
||||
INSERT INTO `sys_log` VALUES ('1393', '1', 'admin', '请求访问主页', '110', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:31:43');
|
||||
INSERT INTO `sys_log` VALUES ('1394', '1', 'admin', 'error', null, 'http://127.0.0.1/test/order/list', 'org.springframework.jdbc.BadSqlGrammarException: \r\n### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Table \'novel_plus.fb_order\' doesn\'t exist\r\n### The error may exist in file [E:\\baseprojectparent\\novel-plus\\novel-admin\\target\\classes\\mybatis\\test\\OrderMapper.xml]\r\n### The error may involve defaultParameterMap\r\n### The error occurred while setting parameters\r\n### SQL: select `id`,`fb_merchant_code`,`merchant_order_sn`,`order_sn`,`platform_order_no`,`trade_no`,`order_state`,`fn_coupon`,`red_packet`,`total_fee`,`order_price`,`fee`,`body`,`attach`,`store_id`,`cashier_id`,`device_no`,`user_id`,`user_logon_id`,`pay_time`,`pay_channel`,`no_cash_coupon_fee`,`cash_coupon_fee`,`cash_fee`,`sign`,`options`,`create_time`,`push_time`,`push_ip`,`mcht_id`,`sn` from fb_order order by id desc limit ?, ?\r\n### Cause: java.sql.SQLSyntaxErrorException: Table \'novel_plus.fb_order\' doesn\'t exist\n; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Table \'novel_plus.fb_order\' doesn\'t exist', null, '2020-05-13 11:33:27');
|
||||
INSERT INTO `sys_log` VALUES ('1395', '1', 'admin', '登录', '276', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:39:20');
|
||||
INSERT INTO `sys_log` VALUES ('1396', '1', 'admin', '请求访问主页', '95', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:39:20');
|
||||
INSERT INTO `sys_log` VALUES ('1397', '1', 'admin', '登录', '285', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:47:00');
|
||||
INSERT INTO `sys_log` VALUES ('1398', '1', 'admin', '请求访问主页', '90', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:47:00');
|
||||
INSERT INTO `sys_log` VALUES ('1399', '1', 'admin', '登录', '251', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 11:48:28');
|
||||
INSERT INTO `sys_log` VALUES ('1400', '1', 'admin', '请求访问主页', '95', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 11:48:28');
|
||||
INSERT INTO `sys_log` VALUES ('1401', '1', 'admin', '登录', '302', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 14:09:33');
|
||||
INSERT INTO `sys_log` VALUES ('1402', '1', 'admin', '请求访问主页', '88', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 14:09:34');
|
||||
INSERT INTO `sys_log` VALUES ('1403', '1', 'admin', '请求更改用户密码', '3', 'com.java2nb.system.controller.UserController.resetPwd()', null, '127.0.0.1', '2020-05-13 14:11:49');
|
||||
INSERT INTO `sys_log` VALUES ('1404', '1', 'admin', 'admin提交更改用户密码', '140', 'com.java2nb.system.controller.UserController.adminResetPwd()', null, '127.0.0.1', '2020-05-13 14:11:50');
|
||||
INSERT INTO `sys_log` VALUES ('1405', '1', 'admin', '请求更改用户密码', '4', 'com.java2nb.system.controller.UserController.resetPwd()', null, '127.0.0.1', '2020-05-13 14:12:11');
|
||||
INSERT INTO `sys_log` VALUES ('1406', '1', 'admin', '登录', '275', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 14:14:26');
|
||||
INSERT INTO `sys_log` VALUES ('1407', '1', 'admin', '请求访问主页', '73', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 14:14:27');
|
||||
INSERT INTO `sys_log` VALUES ('1408', '1', 'admin', 'error', null, 'http://127.0.0.1/novel/author/update', 'org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors\nField error in object \'authorDO\' on field \'id\': rejected value [1,1]; codes [typeMismatch.authorDO.id,typeMismatch.id,typeMismatch.java.lang.Long,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [authorDO.id,id]; arguments []; default message [id]]; default message [Failed to convert property value of type \'java.lang.String\' to required type \'java.lang.Long\' for property \'id\'; nested exception is java.lang.NumberFormatException: For input string: \"1,1\"]', null, '2020-05-13 14:14:38');
|
||||
INSERT INTO `sys_log` VALUES ('1409', '1', 'admin', 'error', null, 'http://127.0.0.1/novel/author/update', 'org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors\nField error in object \'authorDO\' on field \'id\': rejected value [1,1]; codes [typeMismatch.authorDO.id,typeMismatch.id,typeMismatch.java.lang.Long,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [authorDO.id,id]; arguments []; default message [id]]; default message [Failed to convert property value of type \'java.lang.String\' to required type \'java.lang.Long\' for property \'id\'; nested exception is java.lang.NumberFormatException: For input string: \"1,1\"]', null, '2020-05-13 14:14:47');
|
||||
INSERT INTO `sys_log` VALUES ('1410', '1', 'admin', '登录', '261', 'com.java2nb.system.controller.LoginController.ajaxLogin()', null, '127.0.0.1', '2020-05-13 14:18:07');
|
||||
INSERT INTO `sys_log` VALUES ('1411', '1', 'admin', '请求访问主页', '83', 'com.java2nb.system.controller.LoginController.index()', null, '127.0.0.1', '2020-05-13 14:18:07');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_menu
|
||||
@ -1047,9 +994,6 @@ CREATE TABLE `sys_role` (
|
||||
-- Records of sys_role
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_role` VALUES ('1', '超级用户角色', 'admin', '拥有最高权限', '2', '2017-08-12 00:43:52', '2017-08-12 19:14:59');
|
||||
INSERT INTO `sys_role` VALUES ('59', '普通用户', null, '基本用户权限', null, null, null);
|
||||
INSERT INTO `sys_role` VALUES ('60', '测试', null, '<div>', null, null, null);
|
||||
INSERT INTO `sys_role` VALUES ('61', 'test', null, '测试', null, null, null);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_role_data_perm
|
||||
@ -1497,19 +1441,7 @@ CREATE TABLE `sys_user` (
|
||||
-- ----------------------------
|
||||
-- Records of sys_user
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_user` VALUES ('1', 'admin', '超级管理员', 'd633268afedf209e1e4ea0f5f43228a8', '6', 'admin@example.com', '17699999999', '1', '1', '2017-08-15 21:40:39', '2017-08-15 21:41:00', '96', '2017-12-14 00:00:00', '148', 'ccc', '122;121;', '北京市', '北京市市辖区', '东城区');
|
||||
INSERT INTO `sys_user` VALUES ('2', 'test', '临时用户', 'd0af8fa1272ef5a152d9e27763eea293', '6', 'test@bootdo.com', null, '1', '1', '2017-08-14 13:43:05', '2017-08-14 21:15:36', null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('36', 'ldh', '刘德华', 'bfd9394475754fbe45866eba97738c36', '7', 'ldh@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('123', 'zxy', '张学友', '35174ba93f5fe7267f1fb3c1bf903781', '6', 'zxy@bootdo', null, '0', null, null, null, null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('124', 'wyf', '吴亦凡', 'e179e6f687bbd57b9d7efc4746c8090a', '6', 'wyf@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('130', 'lh', '鹿晗', '7924710cd673f68967cde70e188bb097', '9', 'lh@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('131', 'lhc', '令狐冲', 'd515538e17ecb570ba40344b5618f5d4', '6', 'lhc@bootdo.com', null, '0', null, null, null, null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('132', 'lyf', '刘亦菲', '7fdb1d9008f45950c1620ba0864e5fbd', '13', 'lyf@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('134', 'lyh', '李彦宏', 'dc26092b3244d9d432863f2738180e19', '8', 'lyh@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('135', 'wjl', '王健林', '3967697dfced162cf6a34080259b83aa', '6', 'wjl@bootod.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('136', 'gdg', '郭德纲', '3bb1bda86bc02bf6478cd91e42135d2f', '9', 'gdg@bootdo.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('137', 'test2', 'test2', '649169898e69272c0e5bc899baf1e904', null, '1179705413@qq.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('138', 'test3', 'test3', '79ba2d0b58d8a2e94f6b18744c8cd280', '16', '1179705413@qq.com', null, '1', null, null, null, null, null, null, null, null, null, null, null);
|
||||
INSERT INTO `sys_user` VALUES ('1', 'admin', '超级管理员', 'd633268afedf209e1e4ea0f5f43228a8', '14', 'admin@example.com', '17699999999', '1', '1', '2017-08-15 21:40:39', '2017-08-15 21:41:00', '96', '2017-12-14 00:00:00', '148', 'ccc', '122;121;', '北京市', '北京市市辖区', '东城区');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_user_role
|
@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.java2nb</groupId>
|
||||
<artifactId>novel-admin</artifactId>
|
||||
<version>2.11.0</version>
|
||||
<version>3.5.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>novel-admin</name>
|
||||
|
@ -2,20 +2,18 @@ package com.java2nb;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
//关闭SpringSecurity的功能
|
||||
@EnableAutoConfiguration(exclude = {
|
||||
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class
|
||||
})
|
||||
|
||||
@EnableTransactionManagement
|
||||
@ServletComponentScan
|
||||
@MapperScan("com.java2nb.*.dao")
|
||||
@SpringBootApplication
|
||||
@SpringBootApplication(exclude = {
|
||||
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class
|
||||
})
|
||||
@EnableCaching
|
||||
public class AdminApplication {
|
||||
public static void main(String[] args) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
java2nb:
|
||||
uploadPath: c:/var/java2nb/uploaded_files/
|
||||
uploadPath: /var/pic/
|
||||
username: admin
|
||||
password: 111111
|
||||
logging:
|
||||
@ -9,8 +9,8 @@ logging:
|
||||
spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: test123456
|
||||
#password:
|
||||
|
@ -1,16 +1,19 @@
|
||||
java2nb:
|
||||
uploadPath: /var/java2nb/uploaded_files/
|
||||
uploadPath: /var/pic/
|
||||
username: admin
|
||||
password: 111111
|
||||
logging:
|
||||
level:
|
||||
root: error
|
||||
com.java2nb: info
|
||||
com.java2nb: error
|
||||
spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/java2nb?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: java2nb
|
||||
password: java2nb1019
|
||||
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: test123456
|
||||
#password:
|
||||
initialSize: 1
|
||||
minIdle: 3
|
||||
maxActive: 20
|
||||
@ -34,18 +37,18 @@ spring:
|
||||
# 合并多个DruidDataSource的监控数据
|
||||
#useGlobalDataSourceStat: true
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password:
|
||||
# 连接超时时间(毫秒)
|
||||
timeout: 10000
|
||||
jedis:
|
||||
pool:
|
||||
# 连接池中的最大空闲连接
|
||||
max-idle: 8
|
||||
# 连接池中的最小空闲连接
|
||||
min-idle: 10
|
||||
# 连接池最大连接数(使用负值表示没有限制)
|
||||
max-active: 100
|
||||
# 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
max-wait: -1
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password: test
|
||||
# 连接超时时间(毫秒)
|
||||
timeout: 10000
|
||||
jedis:
|
||||
pool:
|
||||
# 连接池中的最大空闲连接
|
||||
max-idle: 8
|
||||
# 连接池中的最小空闲连接
|
||||
min-idle: 10
|
||||
# 连接池最大连接数(使用负值表示没有限制)
|
||||
max-active: 100
|
||||
# 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
max-wait: -1
|
@ -1,6 +1,15 @@
|
||||
__ ________ ___.
|
||||
|__|____ ___ _______ \_____ \ ____\_ |__
|
||||
| \__ \\ \/ /\__ \ / ____/ / \| __ \
|
||||
| |/ __ \\ / / __ \_/ \| | \ \_\ \
|
||||
/\__| (____ /\_/ (____ /\_______ \___| /___ /
|
||||
\______| \/ \/ \/ \/ \/
|
||||
${AnsiColor.CYAN}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
${AnsiColor.RED}
|
||||
|| / | / /
|
||||
|| / | / / ___ // ___ ___ _ __
|
||||
|| / /||/ / //___) ) // // ) ) // ) ) // ) ) ) )
|
||||
||/ / | / // // // // / / // / / / /
|
||||
| / | / ((____ // ((____ ((___/ / // / / / / 小说精品屋欢迎您!!!
|
||||
|
||||
-------Powered By XXY
|
||||
${AnsiColor.CYAN}
|
||||
--------------------------------------------------------------------------------
|
||||
${AnsiColor.BRIGHT_YELLOW}
|
||||
::: Spring-Boot ${spring-boot.formatted-version} :::
|
@ -147,7 +147,7 @@
|
||||
<tr>
|
||||
<td>下载地址</td>
|
||||
<td>
|
||||
<a href="https://gitee.com/xiongxyang/fiction_house" target="_blank">Gitee</a> /
|
||||
<a href="https://gitee.com/novel_dev_team/fiction_house" target="_blank">Gitee</a> /
|
||||
<a href="https://github.com/201206030/fiction_house" target="_blank">Github</a>
|
||||
</td>
|
||||
</tr>
|
||||
@ -155,8 +155,8 @@
|
||||
<td>Gitee</td>
|
||||
<td style="padding-bottom: 0;">
|
||||
<div class="layui-btn-container">
|
||||
<a href='https://gitee.com/xiongxyang/fiction_house/stargazers'><img src='https://gitee.com/xiongxyang/fiction_house/badge/star.svg?theme=dark' alt='star'></img></a>
|
||||
<a href='https://gitee.com/xiongxyang/fiction_house/members'><img src='https://gitee.com/xiongxyang/fiction_house/badge/fork.svg?theme=dark' alt='fork'></img></a>
|
||||
<a href='https://gitee.com/novel_dev_team/fiction_house/stargazers'><img src='https://gitee.com/novel_dev_team/fiction_house/badge/star.svg?theme=dark' alt='star'></img></a>
|
||||
<a href='https://gitee.com/novel_dev_team/fiction_house/members'><img src='https://gitee.com/novel_dev_team/fiction_house/badge/fork.svg?theme=dark' alt='fork'></img></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -200,7 +200,7 @@
|
||||
<tr>
|
||||
<td>下载地址</td>
|
||||
<td>
|
||||
<a href="https://gitee.com/xiongxyang/novel-plus" target="_blank">Gitee</a> /
|
||||
<a href="https://gitee.com/novel_dev_team/novel-plus" target="_blank">Gitee</a> /
|
||||
<a href="https://github.com/201206030/novel-plus" target="_blank">Github</a>
|
||||
</td>
|
||||
</tr>
|
||||
@ -208,8 +208,8 @@
|
||||
<td>Gitee</td>
|
||||
<td style="padding-bottom: 0;">
|
||||
<div class="layui-btn-container">
|
||||
<a href='https://gitee.com/xiongxyang/novel-plus/stargazers'><img src='https://gitee.com/xiongxyang/novel-plus/badge/star.svg?theme=dark' alt='star'></img></a>
|
||||
<a href='https://gitee.com/xiongxyang/novel-plus/members'><img src='https://gitee.com/xiongxyang/novel-plus/badge/fork.svg?theme=dark' alt='fork'></img></a>
|
||||
<a href='https://gitee.com/novel_dev_team/novel-plus/stargazers'><img src='https://gitee.com/novel_dev_team/novel-plus/badge/star.svg?theme=dark' alt='star'></img></a>
|
||||
<a href='https://gitee.com/novel_dev_team/novel-plus/members'><img src='https://gitee.com/novel_dev_team/novel-plus/badge/fork.svg?theme=dark' alt='fork'></img></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -253,7 +253,7 @@
|
||||
<tr>
|
||||
<td>下载地址</td>
|
||||
<td>
|
||||
<a href="https://gitee.com/xiongxyang/novel-cloud" target="_blank">Gitee</a> /
|
||||
<a href="https://gitee.com/novel_dev_team/novel-cloud" target="_blank">Gitee</a> /
|
||||
<a href="https://github.com/201206030/novel-cloud" target="_blank">Github</a>
|
||||
</td>
|
||||
</tr>
|
||||
@ -261,8 +261,8 @@
|
||||
<td>Gitee</td>
|
||||
<td style="padding-bottom: 0;">
|
||||
<div class="layui-btn-container">
|
||||
<a href='https://gitee.com/xiongxyang/novel-cloud/stargazers'><img src='https://gitee.com/xiongxyang/novel-cloud/badge/star.svg?theme=dark' alt='star'></img></a>
|
||||
<a href='https://gitee.com/xiongxyang/novel-cloud/members'><img src='https://gitee.com/xiongxyang/novel-cloud/badge/fork.svg?theme=dark' alt='fork'></img></a>
|
||||
<a href='https://gitee.com/novel_dev_team/novel-cloud/stargazers'><img src='https://gitee.com/novel_dev_team/novel-cloud/badge/star.svg?theme=dark' alt='star'></img></a>
|
||||
<a href='https://gitee.com/novel_dev_team/novel-cloud/members'><img src='https://gitee.com/novel_dev_team/novel-cloud/badge/fork.svg?theme=dark' alt='fork'></img></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -1,327 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<head th:include="include :: header"></head>
|
||||
<body class="gray-bg">
|
||||
<div class="wrapper wrapper-content ">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-content">
|
||||
<form class="form-horizontal m-t" id="signupForm">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗商户号:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="fbMerchantCode" name="fbMerchantCode"
|
||||
class="form-control"
|
||||
type="text">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">第三方商户的订单号:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="merchantOrderSn" name="merchantOrderSn"
|
||||
class="form-control"
|
||||
type="text">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗订单号:</label>
|
||||
<div class="col-sm-8">
|
||||
|
||||
<select data-placeholder="--选择--" id="orderSn"
|
||||
name="orderSn"
|
||||
class="form-control chosen-select" tabindex="2"
|
||||
dict-type="color">
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">平台方订单号:</label>
|
||||
<div class="col-sm-8">
|
||||
|
||||
<select data-placeholder="--选择--" id="platformOrderNo"
|
||||
name="platformOrderNo"
|
||||
class="form-control chosen-select" tabindex="2"
|
||||
dict-type="oa_leave_type">
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">商户单号:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="hidden" id="tradeNo" name="tradeNo"/>
|
||||
<div id="contentEditortradeNo">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">订单状态,1:未支付,2:支付成功,3:支付失败,4:支付取消:</label>
|
||||
<div class="col-sm-8">
|
||||
|
||||
<select data-placeholder="--选择--" id="orderState"
|
||||
name="orderState"
|
||||
class="form-control chosen-select" tabindex="2"
|
||||
dict-type="yes_no">
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">蜂鸟优惠卷抵扣:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="fnCoupon" name="fnCoupon"
|
||||
class="form-control"
|
||||
type="number">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">红包抵扣:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="redPacket" name="redPacket"
|
||||
class="form-control"
|
||||
type="number">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">实收金额(元):</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="totalFee" name="totalFee"
|
||||
class="form-control"
|
||||
type="number">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">订单金额:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="orderPrice" name="orderPrice"
|
||||
class="form-control"
|
||||
type="number">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">手续费(元):</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="fee" name="fee"
|
||||
class="form-control"
|
||||
type="number">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">对商品或交易的描述:</label>
|
||||
<div class="col-sm-8">
|
||||
<img title="点击选择图片" id="picImagebody"
|
||||
style="cursor:pointer;width: 100px;height: 100px"
|
||||
src="/img/webuploader.png"/>
|
||||
<input id="body" name="body"
|
||||
class="form-control"
|
||||
type="hidden">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">附加数据:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="hidden" id="attach" name="attach"/>
|
||||
<div id="contentEditorattach">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗系统的门店id:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="storeId" name="storeId"
|
||||
class="form-control"
|
||||
type="number">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗系统的收银员id:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="cashierId" name="cashierId"
|
||||
class="form-control"
|
||||
type="number">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">设备终端号:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="deviceNo" name="deviceNo"
|
||||
class="form-control"
|
||||
type="text">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">微信顾客支付授权的“open_id”或者支付宝顾客的“buyer_user_id”:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="userId" name="userId"
|
||||
class="form-control"
|
||||
type="text">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">支付宝顾客的账号:</label>
|
||||
<div class="col-sm-8">
|
||||
<textarea id="userLogonId" name="userLogonId"
|
||||
class="form-control"></textarea>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">交易成功的时间:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="laydate-icon layer-date form-control"
|
||||
id="payTime"
|
||||
name="payTime"
|
||||
onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})"
|
||||
style="background-color: #fff;" readonly="readonly"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">支付通道:1微信、2支付宝、3银联:</label>
|
||||
<div class="col-sm-8">
|
||||
|
||||
<select data-placeholder="--选择--" id="payChannel"
|
||||
name="payChannel"
|
||||
class="form-control chosen-select" tabindex="2"
|
||||
dict-type="del_flag">
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">免充值代金券金额(元):</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="noCashCouponFee" name="noCashCouponFee"
|
||||
class="form-control"
|
||||
type="number">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">预充值代金券金额(元):</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="cashCouponFee" name="cashCouponFee"
|
||||
class="form-control"
|
||||
type="number">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">顾客实际支付金额(元):</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="cashFee" name="cashFee"
|
||||
class="form-control"
|
||||
type="number">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">签名:</label>
|
||||
<div class="col-sm-8">
|
||||
|
||||
<select data-placeholder="--选择--" id="sign"
|
||||
name="sign"
|
||||
class="form-control chosen-select" tabindex="2"
|
||||
dict-type="theme">
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">其它选项:</label>
|
||||
<div class="col-sm-8">
|
||||
<img title="点击选择图片" id="picImageoptions"
|
||||
style="cursor:pointer;width: 100px;height: 100px"
|
||||
src="/img/webuploader.png"/>
|
||||
<input id="options" name="options"
|
||||
class="form-control"
|
||||
type="hidden">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">创建时间:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="laydate-icon layer-date form-control"
|
||||
id="createTime"
|
||||
name="createTime"
|
||||
onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})"
|
||||
style="background-color: #fff;" readonly="readonly"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">推送时间:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="laydate-icon layer-date form-control"
|
||||
id="pushTime"
|
||||
name="pushTime"
|
||||
onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})"
|
||||
style="background-color: #fff;" readonly="readonly"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">推送IP:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="hidden" id="pushIp" name="pushIp"/>
|
||||
<div id="contentEditorpushIp">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">商户id:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="mchtId" name="mchtId"
|
||||
class="form-control"
|
||||
type="number">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">QR编号:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="sn" name="sn"
|
||||
class="form-control"
|
||||
type="text">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-8 col-sm-offset-3">
|
||||
<button type="submit" class="btn btn-primary">提交</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="include::footer"></div>
|
||||
<script type="text/javascript" src="/wangEditor/release/wangEditor.js"></script>
|
||||
<script type="text/javascript" src="/js/appjs/test/order/add.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,315 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<head th:include="include :: header"></head>
|
||||
<body class="gray-bg">
|
||||
<div class="wrapper wrapper-content ">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-content">
|
||||
<form class="form-horizontal m-t" id="signupForm">
|
||||
<input id="id" name="id" th:value="${order.id}"
|
||||
type="hidden">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗商户号:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.fbMerchantCode}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">第三方商户的订单号:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.merchantOrderSn}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗订单号:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8 dict-type" dict-type="color"
|
||||
th:attr="dict-value=${order.orderSn}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">平台方订单号:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8 dict-type" dict-type="oa_leave_type"
|
||||
th:attr="dict-value=${order.platformOrderNo}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">商户单号:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:utext="${order.tradeNo}"></div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">订单状态,1:未支付,2:支付成功,3:支付失败,4:支付取消:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8 dict-type" dict-type="yes_no"
|
||||
th:attr="dict-value=${order.orderState}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">蜂鸟优惠卷抵扣:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.fnCoupon}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">红包抵扣:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.redPacket}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">实收金额(元):</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.totalFee}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">订单金额:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.orderPrice}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">手续费(元):</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.fee}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">对商品或交易的描述:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8">
|
||||
<img id="picImagebody"
|
||||
style="cursor:pointer;width: 100px;height: 100px"
|
||||
th:src="${order.body}==null?'/img/webuploader.png':${order.body}"/>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">附加数据:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:utext="${order.attach}"></div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗系统的门店id:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.storeId}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗系统的收银员id:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.cashierId}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">设备终端号:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.deviceNo}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">微信顾客支付授权的“open_id”或者支付宝顾客的“buyer_user_id”:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.userId}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">支付宝顾客的账号:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.userLogonId}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">交易成功的时间:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.payTime}==null?null:${#dates.format(order.payTime,'yyyy-MM-dd HH:mm:ss')}">
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">支付通道:1微信、2支付宝、3银联:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8 dict-type" dict-type="del_flag"
|
||||
th:attr="dict-value=${order.payChannel}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">免充值代金券金额(元):</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.noCashCouponFee}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">预充值代金券金额(元):</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.cashCouponFee}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">顾客实际支付金额(元):</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.cashFee}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">签名:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8 dict-type" dict-type="theme"
|
||||
th:attr="dict-value=${order.sign}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">其它选项:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8">
|
||||
<img id="picImageoptions"
|
||||
style="cursor:pointer;width: 100px;height: 100px"
|
||||
th:src="${order.options}==null?'/img/webuploader.png':${order.options}"/>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">创建时间:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.createTime}==null?null:${#dates.format(order.createTime,'yyyy-MM-dd HH:mm:ss')}">
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">推送时间:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.pushTime}==null?null:${#dates.format(order.pushTime,'yyyy-MM-dd HH:mm:ss')}">
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">推送IP:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:utext="${order.pushIp}"></div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">商户id:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.mchtId}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">QR编号:</label>
|
||||
|
||||
<div style="padding-top:8px" class="col-sm-8"
|
||||
th:text="${order.sn}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="include::footer"></div>
|
||||
</body>
|
||||
</html>
|
@ -1,323 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<head th:include="include :: header"></head>
|
||||
<body class="gray-bg">
|
||||
<div class="wrapper wrapper-content ">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-content">
|
||||
<form class="form-horizontal m-t" id="signupForm">
|
||||
<input id="id" name="id" th:value="${order.id}"
|
||||
type="hidden">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗商户号:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="fbMerchantCode" name="fbMerchantCode"
|
||||
th:value="${order.fbMerchantCode}"
|
||||
class="form-control"
|
||||
type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">第三方商户的订单号:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="merchantOrderSn" name="merchantOrderSn"
|
||||
th:value="${order.merchantOrderSn}"
|
||||
class="form-control"
|
||||
type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗订单号:</label>
|
||||
<div class="col-sm-8">
|
||||
|
||||
<select data-placeholder="--选择--" id="orderSn"
|
||||
name="orderSn"
|
||||
class="form-control chosen-select" tabindex="2"
|
||||
dict-type="color"
|
||||
th:attr="dict-value=${order.orderSn}" >
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">平台方订单号:</label>
|
||||
<div class="col-sm-8">
|
||||
|
||||
<select data-placeholder="--选择--" id="platformOrderNo"
|
||||
name="platformOrderNo"
|
||||
class="form-control chosen-select" tabindex="2"
|
||||
dict-type="oa_leave_type"
|
||||
th:attr="dict-value=${order.platformOrderNo}" >
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">商户单号:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="hidden" id="tradeNo" name="tradeNo" th:value="${order.tradeNo}"/>
|
||||
<div id="contentEditortradeNo">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">订单状态,1:未支付,2:支付成功,3:支付失败,4:支付取消:</label>
|
||||
<div class="col-sm-8">
|
||||
|
||||
<select data-placeholder="--选择--" id="orderState"
|
||||
name="orderState"
|
||||
class="form-control chosen-select" tabindex="2"
|
||||
dict-type="yes_no"
|
||||
th:attr="dict-value=${order.orderState}" >
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">蜂鸟优惠卷抵扣:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="fnCoupon" name="fnCoupon"
|
||||
th:value="${order.fnCoupon}"
|
||||
class="form-control"
|
||||
type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">红包抵扣:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="redPacket" name="redPacket"
|
||||
th:value="${order.redPacket}"
|
||||
class="form-control"
|
||||
type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">实收金额(元):</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="totalFee" name="totalFee"
|
||||
th:value="${order.totalFee}"
|
||||
class="form-control"
|
||||
type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">订单金额:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="orderPrice" name="orderPrice"
|
||||
th:value="${order.orderPrice}"
|
||||
class="form-control"
|
||||
type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">手续费(元):</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="fee" name="fee"
|
||||
th:value="${order.fee}"
|
||||
class="form-control"
|
||||
type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">对商品或交易的描述:</label>
|
||||
<div class="col-sm-8">
|
||||
<img title="点击选择图片" id="picImagebody"
|
||||
style="cursor:pointer;width: 100px;height: 100px"
|
||||
th:src="${order.body}==null?'/img/webuploader.png':${order.body}"/>
|
||||
<input id="body" name="body" th:value="${order.body}"
|
||||
class="form-control"
|
||||
type="hidden">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">附加数据:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="hidden" id="attach" name="attach" th:value="${order.attach}"/>
|
||||
<div id="contentEditorattach">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗系统的门店id:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="storeId" name="storeId"
|
||||
th:value="${order.storeId}"
|
||||
class="form-control"
|
||||
type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">付呗系统的收银员id:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="cashierId" name="cashierId"
|
||||
th:value="${order.cashierId}"
|
||||
class="form-control"
|
||||
type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">设备终端号:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="deviceNo" name="deviceNo"
|
||||
th:value="${order.deviceNo}"
|
||||
class="form-control"
|
||||
type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">微信顾客支付授权的“open_id”或者支付宝顾客的“buyer_user_id”:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="userId" name="userId"
|
||||
th:value="${order.userId}"
|
||||
class="form-control"
|
||||
type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">支付宝顾客的账号:</label>
|
||||
<div class="col-sm-8">
|
||||
<textarea id="userLogonId" name="userLogonId"
|
||||
class="form-control" th:text="${order.userLogonId}"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">交易成功的时间:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="laydate-icon layer-date form-control"
|
||||
id="payTime"
|
||||
name="payTime"
|
||||
th:value="${order.payTime}==null?null:${#dates.format(order.payTime,'yyyy-MM-dd HH:mm:ss')}"
|
||||
onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})"
|
||||
style="background-color: #fff;" readonly="readonly"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">支付通道:1微信、2支付宝、3银联:</label>
|
||||
<div class="col-sm-8">
|
||||
|
||||
<select data-placeholder="--选择--" id="payChannel"
|
||||
name="payChannel"
|
||||
class="form-control chosen-select" tabindex="2"
|
||||
dict-type="del_flag"
|
||||
th:attr="dict-value=${order.payChannel}" >
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">免充值代金券金额(元):</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="noCashCouponFee" name="noCashCouponFee"
|
||||
th:value="${order.noCashCouponFee}"
|
||||
class="form-control"
|
||||
type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">预充值代金券金额(元):</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="cashCouponFee" name="cashCouponFee"
|
||||
th:value="${order.cashCouponFee}"
|
||||
class="form-control"
|
||||
type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">顾客实际支付金额(元):</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="cashFee" name="cashFee"
|
||||
th:value="${order.cashFee}"
|
||||
class="form-control"
|
||||
type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">签名:</label>
|
||||
<div class="col-sm-8">
|
||||
|
||||
<select data-placeholder="--选择--" id="sign"
|
||||
name="sign"
|
||||
class="form-control chosen-select" tabindex="2"
|
||||
dict-type="theme"
|
||||
th:attr="dict-value=${order.sign}" >
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">其它选项:</label>
|
||||
<div class="col-sm-8">
|
||||
<img title="点击选择图片" id="picImageoptions"
|
||||
style="cursor:pointer;width: 100px;height: 100px"
|
||||
th:src="${order.options}==null?'/img/webuploader.png':${order.options}"/>
|
||||
<input id="options" name="options" th:value="${order.options}"
|
||||
class="form-control"
|
||||
type="hidden">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">创建时间:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="laydate-icon layer-date form-control"
|
||||
id="createTime"
|
||||
name="createTime"
|
||||
th:value="${order.createTime}==null?null:${#dates.format(order.createTime,'yyyy-MM-dd HH:mm:ss')}"
|
||||
onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})"
|
||||
style="background-color: #fff;" readonly="readonly"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">推送时间:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="laydate-icon layer-date form-control"
|
||||
id="pushTime"
|
||||
name="pushTime"
|
||||
th:value="${order.pushTime}==null?null:${#dates.format(order.pushTime,'yyyy-MM-dd HH:mm:ss')}"
|
||||
onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})"
|
||||
style="background-color: #fff;" readonly="readonly"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">推送IP:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="hidden" id="pushIp" name="pushIp" th:value="${order.pushIp}"/>
|
||||
<div id="contentEditorpushIp">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">商户id:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="mchtId" name="mchtId"
|
||||
th:value="${order.mchtId}"
|
||||
class="form-control"
|
||||
type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">QR编号:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="sn" name="sn"
|
||||
th:value="${order.sn}"
|
||||
class="form-control"
|
||||
type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-8 col-sm-offset-3">
|
||||
<button type="submit" class="btn btn-primary">提交</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="include::footer"></div>
|
||||
<script type="text/javascript" src="/wangEditor/release/wangEditor.js"></script>
|
||||
<script type="text/javascript" src="/js/appjs/test/order/edit.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,66 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<head th:include="include :: header"></head>
|
||||
<body class="gray-bg">
|
||||
<div class="wrapper wrapper-content ">
|
||||
<div class="col-sm-12">
|
||||
<div class="ibox">
|
||||
<div class="ibox-body">
|
||||
<div class="fixed-table-toolbar">
|
||||
<div class="columns pull-left">
|
||||
<button shiro:hasPermission="test:order:add" type="button"
|
||||
class="btn btn-primary" onclick="add()">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i>添加
|
||||
</button>
|
||||
<button shiro:hasPermission="test:order:batchRemove" type="button"
|
||||
class="btn btn-danger"
|
||||
onclick="batchRemove()">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>删除
|
||||
</button>
|
||||
</div>
|
||||
<div class="columns pull-right">
|
||||
<button class="btn btn-success" onclick="reLoad()">查询</button>
|
||||
</div>
|
||||
|
||||
<form id="searchForm">
|
||||
<div class="columns pull-right col-md-2">
|
||||
<input id="id" name="id" type="text" class="form-control"
|
||||
placeholder="主键">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<table id="exampleTable" data-mobile-responsive="true">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--shiro控制bootstraptable行内按钮看见性 -->
|
||||
<div>
|
||||
<script type="text/javascript">
|
||||
var s_detail_h = 'hidden';
|
||||
var s_edit_h = 'hidden';
|
||||
var s_remove_h = 'hidden';
|
||||
</script>
|
||||
</div>
|
||||
<div shiro:hasPermission="test:order:detail">
|
||||
<script type="text/javascript">
|
||||
s_detail_h = '';
|
||||
</script>
|
||||
</div>
|
||||
<div shiro:hasPermission="test:order:edit">
|
||||
<script type="text/javascript">
|
||||
s_edit_h = '';
|
||||
</script>
|
||||
</div>
|
||||
<div shiro:hasPermission="test:order:remove">
|
||||
<script type="text/javascript">
|
||||
var s_remove_h = '';
|
||||
</script>
|
||||
</div>
|
||||
<div th:include="include :: footer"></div>
|
||||
<script type="text/javascript" src="/js/appjs/test/order/order.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>novel</artifactId>
|
||||
<groupId>com.java2nb</groupId>
|
||||
<version>3.0.2</version>
|
||||
<version>3.5.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -123,6 +123,12 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
@ -1,21 +1,30 @@
|
||||
package com.java2nb.novel.core.advice;
|
||||
|
||||
import com.java2nb.novel.core.bean.ResultBean;
|
||||
import com.java2nb.novel.core.enums.ResponseStatus;
|
||||
import com.java2nb.novel.core.exception.BusinessException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
/**
|
||||
* 通用的异常处理器
|
||||
*
|
||||
* @author 11797*/
|
||||
@Slf4j
|
||||
@ControllerAdvice
|
||||
@ResponseBody
|
||||
@RestControllerAdvice(basePackages = "com.java2nb.novel.controller")
|
||||
public class CommonExceptionHandler {
|
||||
|
||||
/**
|
||||
* 处理后台数据校验异常
|
||||
* */
|
||||
@ExceptionHandler(BindException.class)
|
||||
public ResultBean handlerBindException(BindException e){
|
||||
log.error(e.getMessage(),e);
|
||||
return ResultBean.fail(ResponseStatus.PARAM_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理业务异常
|
||||
* */
|
||||
|
@ -0,0 +1,26 @@
|
||||
package com.java2nb.novel.core.advice;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
/**
|
||||
* 页面异常处理器
|
||||
*
|
||||
* @author 11797
|
||||
*/
|
||||
@Slf4j
|
||||
@ControllerAdvice(basePackages = "com.java2nb.novel.page")
|
||||
public class PageExceptionHandler {
|
||||
|
||||
|
||||
/**
|
||||
* 处理所有异常
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
public String handlerException(Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
//跳转页面过程中出现异常时统一跳转到404页面
|
||||
return "404";
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package com.java2nb.novel.core.bean;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 封装通用分页数据,接收PageHelper、SpringData等框架的分页数据,转换成通用的PageBean对象
|
||||
* @author xiongxiaoyang
|
||||
* @version 1.0
|
||||
* @since 2021/2/4
|
||||
* @param <T> 分页集合类型
|
||||
*/
|
||||
@Data
|
||||
public class PageBean<T> {
|
||||
|
||||
private Integer pageNum;
|
||||
private Integer pageSize;
|
||||
private Long total;
|
||||
private List<? extends T> list;
|
||||
|
||||
|
||||
/**
|
||||
* 该构造函数用于PageHelper工具进行分页查询的场景
|
||||
* 接收PageHelper分页后的list
|
||||
*/
|
||||
public PageBean(List<T> list){
|
||||
PageInfo<T> pageInfo = new PageInfo<>(list);
|
||||
this.pageNum = pageInfo.getPageNum();
|
||||
this.pageSize = pageInfo.getPageSize();
|
||||
this.total = pageInfo.getTotal();
|
||||
this.list = pageInfo.getList();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 该构造函数用于通用分页查询的场景
|
||||
* 接收普通分页数据和普通集合
|
||||
*/
|
||||
public PageBean(Integer pageNum, Integer pageSize, Long total, List<T> list) {
|
||||
this.pageNum = pageNum;
|
||||
this.pageSize = pageSize;
|
||||
this.total = total;
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
|
||||
//TODO 使用其他的分页工具或框架进行分页查询的场景
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
package com.java2nb.novel.core.utils;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
@ -28,4 +25,23 @@ public class HttpUtil {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getByHttpClientWithChrome(String url) {
|
||||
try {
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("user-agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36");
|
||||
HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
|
||||
ResponseEntity<String> forEntity = restTemplate.exchange(url.toString(), HttpMethod.GET, requestEntity, String.class);
|
||||
|
||||
if (forEntity.getStatusCode() == HttpStatus.OK) {
|
||||
return forEntity.getBody();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.java2nb.novel.core.valid;
|
||||
|
||||
/**
|
||||
* 新增数据的校验分组
|
||||
* @author xiongxiaoyang
|
||||
*/
|
||||
public interface AddGroup {
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.java2nb.novel.core.valid;
|
||||
|
||||
/**
|
||||
* 更新数据的校验分组
|
||||
* @author xiongxiaoyang
|
||||
*/
|
||||
public interface UpdateGroup {
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,36 +1,56 @@
|
||||
package com.java2nb.novel.entity;
|
||||
|
||||
import com.java2nb.novel.core.valid.AddGroup;
|
||||
import com.java2nb.novel.core.valid.UpdateGroup;
|
||||
|
||||
import java.util.Date;
|
||||
import javax.annotation.Generated;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
public class User {
|
||||
|
||||
@Null(groups = {AddGroup.class, UpdateGroup.class})
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private Long id;
|
||||
|
||||
|
||||
@NotBlank(groups = {AddGroup.class},message="手机号不能为空!")
|
||||
@Pattern(groups = {AddGroup.class},regexp="^1[3|4|5|6|7|8|9][0-9]{9}$",message="手机号格式不正确!")
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private String username;
|
||||
|
||||
@NotBlank(groups = {AddGroup.class},message="密码不能为空!")
|
||||
@Null(groups = {UpdateGroup.class})
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private String password;
|
||||
|
||||
@Null(groups = {AddGroup.class})
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private String nickName;
|
||||
|
||||
@Null(groups = {AddGroup.class})
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private String userPhoto;
|
||||
|
||||
@Null(groups = {AddGroup.class})
|
||||
@Min(value = 0,groups = {UpdateGroup.class})
|
||||
@Max(value = 1,groups = {UpdateGroup.class})
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private Byte userSex;
|
||||
|
||||
@Null(groups = {AddGroup.class,UpdateGroup.class})
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private Long accountBalance;
|
||||
|
||||
@Null(groups = {AddGroup.class,UpdateGroup.class})
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private Byte status;
|
||||
|
||||
@Null(groups = {AddGroup.class,UpdateGroup.class})
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private Date createTime;
|
||||
|
||||
@Null(groups = {AddGroup.class,UpdateGroup.class})
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private Date updateTime;
|
||||
|
||||
|
@ -71,8 +71,3 @@ sharding:
|
||||
|
||||
|
||||
|
||||
pic:
|
||||
save:
|
||||
type: 2 #图片保存方式, 1不保存,使用爬取的网络图片 ,2保存在自己的存储介质
|
||||
storage: local #存储介质,local:本地,OSS:阿里云对象存储,fastDfs:分布式文件系统
|
||||
path: /var/pic #图片保存路径
|
82
novel-common/src/main/resources/application-common-prod.yml
Normal file
82
novel-common/src/main/resources/application-common-prod.yml
Normal file
@ -0,0 +1,82 @@
|
||||
spring:
|
||||
profiles:
|
||||
include: [common]
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
#Redis服务器IP
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
#Redis服务器连接端口
|
||||
port: 6379
|
||||
#Redis服务器连接密码
|
||||
password: test
|
||||
jedis:
|
||||
pool:
|
||||
#连接池最大连接数(使用负值表示没有限制)
|
||||
max-active: 8
|
||||
#连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
max-wait: 1
|
||||
#连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
max-idle: 8
|
||||
#连接池中的最小空闲连接
|
||||
min-idle: 0
|
||||
#连接超时时间(毫秒)
|
||||
timeout: 30000
|
||||
datasource:
|
||||
url: jdbc:mysql://127.0.0.1:3306/novel_biz?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: test123456
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
|
||||
|
||||
####使用shardingJdbc时,
|
||||
####所有的jdbcType都不能是LONGVARCHAR,否则会导致java.io.NotSerializableException: java.io.StringReader错误
|
||||
##### 应该替换所有的 LONGVARCHAR 类型为VARCHAR
|
||||
|
||||
sharding:
|
||||
jdbc:
|
||||
datasource:
|
||||
names: ds0 #,ds1
|
||||
ds0:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
jdbc-url: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: test123456
|
||||
# ds1:
|
||||
# type: com.alibaba.druid.pool.DruidDataSource
|
||||
# driver-class-name: com.mysql.jdbc.Driver
|
||||
# url: jdbc:mysql://localhost:3306/novel_plus2
|
||||
# username: root
|
||||
# password: test123456
|
||||
config:
|
||||
sharding:
|
||||
props:
|
||||
sql.show: true
|
||||
tables:
|
||||
book_content: #book_content表
|
||||
key-generator-column-name: id #主键
|
||||
actual-data-nodes: ds${0}.book_content${0..9} #数据节点
|
||||
# database-strategy: #分库策略
|
||||
# inline:
|
||||
# sharding-column: book_id
|
||||
# algorithm-expression: ds${book_id % 10}
|
||||
table-strategy: #分表策略
|
||||
inline:
|
||||
shardingColumn: index_id
|
||||
algorithm-expression: book_content${index_id % 10}
|
||||
|
||||
|
||||
logging:
|
||||
level:
|
||||
root: error
|
||||
com.java2nb: error
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
spring:
|
||||
profiles:
|
||||
include: [common]
|
||||
datasource:
|
||||
url: jdbc:mysql://127.0.0.1:3306/novel_biz?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: root
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
|
||||
|
||||
pic:
|
||||
save:
|
||||
type: 2 #图片保存方式, 1不保存,使用网络图片 ,2本地保存
|
||||
path: /var/pic #图片保存路径
|
||||
|
||||
|
||||
|
15
novel-common/src/main/resources/banner.txt
Normal file
15
novel-common/src/main/resources/banner.txt
Normal file
@ -0,0 +1,15 @@
|
||||
${AnsiColor.CYAN}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
${AnsiColor.RED}
|
||||
|| / | / /
|
||||
|| / | / / ___ // ___ ___ _ __
|
||||
|| / /||/ / //___) ) // // ) ) // ) ) // ) ) ) )
|
||||
||/ / | / // // // // / / // / / / /
|
||||
| / | / ((____ // ((____ ((___/ / // / / / / 小说精品屋欢迎您!!!
|
||||
|
||||
-------Powered By XXY
|
||||
${AnsiColor.CYAN}
|
||||
--------------------------------------------------------------------------------
|
||||
${AnsiColor.BRIGHT_YELLOW}
|
||||
::: Spring-Boot ${spring-boot.formatted-version} :::
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>novel</artifactId>
|
||||
<groupId>com.java2nb</groupId>
|
||||
<version>3.0.2</version>
|
||||
<version>3.5.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -9,10 +9,7 @@ import com.java2nb.novel.service.CrawlService;
|
||||
import com.java2nb.novel.vo.CrawlSingleTaskVO;
|
||||
import com.java2nb.novel.vo.CrawlSourceVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @author Administrator
|
||||
@ -39,11 +36,10 @@ public class CrawlController {
|
||||
/**
|
||||
* 爬虫源分页列表查询
|
||||
* */
|
||||
@PostMapping("listCrawlByPage")
|
||||
@GetMapping("listCrawlByPage")
|
||||
public ResultBean listCrawlByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "10") int pageSize){
|
||||
|
||||
return ResultBean.ok(new PageInfo<>(BeanUtil.copyList(crawlService.listCrawlByPage(page,pageSize), CrawlSourceVO.class)
|
||||
));
|
||||
return ResultBean.ok(crawlService.listCrawlByPage(page,pageSize));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,18 +67,17 @@ public class CrawlController {
|
||||
/**
|
||||
* 单本采集任务分页列表查询
|
||||
* */
|
||||
@PostMapping("listCrawlSingleTaskByPage")
|
||||
@GetMapping("listCrawlSingleTaskByPage")
|
||||
public ResultBean listCrawlSingleTaskByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "10") int pageSize){
|
||||
|
||||
return ResultBean.ok(new PageInfo<>(BeanUtil.copyList(crawlService.listCrawlSingleTaskByPage(page,pageSize), CrawlSingleTaskVO.class)
|
||||
));
|
||||
return ResultBean.ok(crawlService.listCrawlSingleTaskByPage(page,pageSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除采集任务
|
||||
* */
|
||||
@PostMapping("delCrawlSingleTask")
|
||||
public ResultBean delCrawlSingleTask(Long id){
|
||||
@DeleteMapping("delCrawlSingleTask/{id}")
|
||||
public ResultBean delCrawlSingleTask(@PathVariable("id") Long id){
|
||||
|
||||
crawlService.delCrawlSingleTask(id);
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
package com.java2nb.novel.core.crawl;
|
||||
|
||||
import com.java2nb.novel.core.utils.HttpUtil;
|
||||
import com.java2nb.novel.core.utils.IdWorker;
|
||||
import com.java2nb.novel.core.utils.RandomBookInfoUtil;
|
||||
import com.java2nb.novel.core.utils.RestTemplateUtil;
|
||||
import com.java2nb.novel.core.utils.*;
|
||||
import com.java2nb.novel.entity.Book;
|
||||
import com.java2nb.novel.entity.BookContent;
|
||||
import com.java2nb.novel.entity.BookIndex;
|
||||
@ -11,8 +8,7 @@ import com.java2nb.novel.utils.Constants;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
@ -38,13 +34,13 @@ public class CrawlParser {
|
||||
|
||||
private static RestTemplate restTemplate = RestTemplateUtil.getInstance("utf-8");
|
||||
|
||||
private static ThreadLocal <Integer> retryCount = new ThreadLocal<>();
|
||||
private static ThreadLocal<Integer> retryCount = new ThreadLocal<>();
|
||||
|
||||
@SneakyThrows
|
||||
public static Book parseBook(RuleBean ruleBean, String bookId) {
|
||||
Book book = new Book();
|
||||
String bookDetailUrl = ruleBean.getBookDetailUrl().replace("{bookId}", bookId);
|
||||
String bookDetailHtml = getByHttpClient(bookDetailUrl);
|
||||
String bookDetailHtml = getByHttpClientWithChrome(bookDetailUrl);
|
||||
if (bookDetailHtml != null) {
|
||||
Pattern bookNamePatten = compile(ruleBean.getBookNamePatten());
|
||||
Matcher bookNameMatch = bookNamePatten.matcher(bookDetailHtml);
|
||||
@ -66,7 +62,7 @@ public class CrawlParser {
|
||||
boolean isFindPicUrl = picUrlMatch.find();
|
||||
if (isFindPicUrl) {
|
||||
String picUrl = picUrlMatch.group(1);
|
||||
if(StringUtils.isNotBlank(picUrl) && StringUtils.isNotBlank(ruleBean.getPicUrlPrefix())) {
|
||||
if (StringUtils.isNotBlank(picUrl) && StringUtils.isNotBlank(ruleBean.getPicUrlPrefix())) {
|
||||
picUrl = ruleBean.getPicUrlPrefix() + picUrl;
|
||||
}
|
||||
//设置封面图片路径
|
||||
@ -97,11 +93,11 @@ public class CrawlParser {
|
||||
String desc = bookDetailHtml.substring(bookDetailHtml.indexOf(ruleBean.getDescStart()) + ruleBean.getDescStart().length());
|
||||
desc = desc.substring(0, desc.indexOf(ruleBean.getDescEnd()));
|
||||
//过滤掉简介中的特殊标签
|
||||
desc = desc.replaceAll("<a[^<]+</a>","")
|
||||
.replaceAll("<font[^<]+</font>","")
|
||||
.replaceAll("<p>\\s*</p>","")
|
||||
.replaceAll("<p>","")
|
||||
.replaceAll("</p>","<br/>");
|
||||
desc = desc.replaceAll("<a[^<]+</a>", "")
|
||||
.replaceAll("<font[^<]+</font>", "")
|
||||
.replaceAll("<p>\\s*</p>", "")
|
||||
.replaceAll("<p>", "")
|
||||
.replaceAll("</p>", "<br/>");
|
||||
//设置书籍简介
|
||||
book.setBookDesc(desc);
|
||||
if (StringUtils.isNotBlank(ruleBean.getStatusPatten())) {
|
||||
@ -147,9 +143,9 @@ public class CrawlParser {
|
||||
}
|
||||
|
||||
public static Map<Integer, List> parseBookIndexAndContent(String sourceBookId, Book book, RuleBean ruleBean, Map<Integer, BookIndex> hasIndexs) {
|
||||
Map<Integer,List> result = new HashMap<>(2);
|
||||
result.put(BOOK_INDEX_LIST_KEY,new ArrayList(0));
|
||||
result.put(BOOK_CONTENT_LIST_KEY,new ArrayList(0));
|
||||
Map<Integer, List> result = new HashMap<>(2);
|
||||
result.put(BOOK_INDEX_LIST_KEY, new ArrayList(0));
|
||||
result.put(BOOK_CONTENT_LIST_KEY, new ArrayList(0));
|
||||
|
||||
Date currentDate = new Date();
|
||||
|
||||
@ -157,10 +153,10 @@ public class CrawlParser {
|
||||
List<BookContent> contentList = new ArrayList<>();
|
||||
//读取目录
|
||||
String indexListUrl = ruleBean.getBookIndexUrl().replace("{bookId}", sourceBookId);
|
||||
String indexListHtml = getByHttpClient(indexListUrl);
|
||||
String indexListHtml = getByHttpClientWithChrome(indexListUrl);
|
||||
|
||||
if (indexListHtml != null) {
|
||||
if(StringUtils.isNotBlank(ruleBean.getBookIndexStart())){
|
||||
if (StringUtils.isNotBlank(ruleBean.getBookIndexStart())) {
|
||||
indexListHtml = indexListHtml.substring(indexListHtml.indexOf(ruleBean.getBookIndexStart()) + ruleBean.getBookIndexStart().length());
|
||||
}
|
||||
|
||||
@ -175,10 +171,7 @@ public class CrawlParser {
|
||||
int indexNum = 0;
|
||||
|
||||
//总字数
|
||||
Integer totalWordCount = 0;
|
||||
//最新目录
|
||||
Long lastIndexId = null;
|
||||
String lastIndexName = null;
|
||||
Integer totalWordCount = book.getWordCount() == null ? 0 : book.getWordCount();
|
||||
|
||||
while (isFindIndex) {
|
||||
|
||||
@ -186,61 +179,81 @@ public class CrawlParser {
|
||||
String indexName = indexNameMatch.group(1);
|
||||
|
||||
if (hasIndex == null || !StringUtils.deleteWhitespace(hasIndex.getIndexName()).equals(StringUtils.deleteWhitespace(indexName))) {
|
||||
String contentUrl = ruleBean.getBookContentUrl().replace("{bookId}", sourceBookId).replace("{indexId}", indexIdMatch.group(1));
|
||||
|
||||
String sourceIndexId = indexIdMatch.group(1);
|
||||
String bookContentUrl = ruleBean.getBookContentUrl();
|
||||
int calStart = bookContentUrl.indexOf("{cal_");
|
||||
if (calStart != -1) {
|
||||
//内容页URL需要进行计算才能得到
|
||||
String calStr = bookContentUrl.substring(calStart, calStart + bookContentUrl.substring(calStart).indexOf("}"));
|
||||
String[] calArr = calStr.split("_");
|
||||
int calType = Integer.parseInt(calArr[1]);
|
||||
if (calType == 1) {
|
||||
///{cal_1_1_3}_{bookId}/{indexId}.html
|
||||
//第一种计算规则,去除第x个参数的最后y个字母
|
||||
int x = Integer.parseInt(calArr[2]);
|
||||
int y = Integer.parseInt(calArr[3]);
|
||||
String calResult;
|
||||
if (x == 1) {
|
||||
calResult = sourceBookId.substring(0, sourceBookId.length() - y);
|
||||
} else {
|
||||
calResult = sourceIndexId.substring(0, sourceBookId.length() - y);
|
||||
}
|
||||
|
||||
if (calResult.length() == 0) {
|
||||
calResult = "0";
|
||||
|
||||
}
|
||||
|
||||
bookContentUrl = bookContentUrl.replace(calStr + "}", calResult);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String contentUrl = bookContentUrl.replace("{bookId}", sourceBookId).replace("{indexId}", sourceIndexId);
|
||||
|
||||
//查询章节内容
|
||||
String contentHtml = getByHttpClient(contentUrl);
|
||||
String contentHtml = getByHttpClientWithChrome(contentUrl);
|
||||
if (contentHtml != null && !contentHtml.contains("正在手打中")) {
|
||||
String content = contentHtml.substring(contentHtml.indexOf(ruleBean.getContentStart()) + ruleBean.getContentStart().length());
|
||||
content = content.substring(0, content.indexOf(ruleBean.getContentEnd()));
|
||||
//TODO插入章节目录和章节内容
|
||||
//插入章节目录和章节内容
|
||||
BookIndex bookIndex = new BookIndex();
|
||||
|
||||
bookIndex.setIndexName(indexName);
|
||||
bookIndex.setIndexNum(indexNum);
|
||||
Integer wordCount = StringUtil.getStrValidWordCount(content);
|
||||
bookIndex.setWordCount(wordCount);
|
||||
indexList.add(bookIndex);
|
||||
BookContent bookContent = new BookContent();
|
||||
|
||||
BookContent bookContent = new BookContent();
|
||||
bookContent.setContent(content);
|
||||
contentList.add(bookContent);
|
||||
|
||||
//判断是新增还是更新
|
||||
if(hasIndexs.size() == 0){
|
||||
//新书入库
|
||||
if (hasIndex != null) {
|
||||
//章节更新
|
||||
bookIndex.setId(hasIndex.getId());
|
||||
bookContent.setIndexId(hasIndex.getId());
|
||||
|
||||
//计算总字数
|
||||
totalWordCount = (totalWordCount+wordCount-hasIndex.getWordCount());
|
||||
} else {
|
||||
//章节插入
|
||||
//设置目录和章节内容
|
||||
Long indexId = idWorker.nextId();
|
||||
lastIndexId = indexId;
|
||||
lastIndexName = indexName;
|
||||
bookIndex.setId(indexId);
|
||||
bookIndex.setBookId(book.getId());
|
||||
Integer wordCount = bookContent.getContent().length();
|
||||
totalWordCount += wordCount;
|
||||
bookIndex.setWordCount(wordCount);
|
||||
|
||||
bookIndex.setCreateTime(currentDate);
|
||||
bookIndex.setUpdateTime(currentDate);
|
||||
|
||||
bookContent.setIndexId(indexId);
|
||||
|
||||
//设置小说基础信息
|
||||
book.setWordCount(totalWordCount);
|
||||
book.setLastIndexId(lastIndexId);
|
||||
book.setLastIndexName(lastIndexName);
|
||||
book.setLastIndexUpdateTime(currentDate);
|
||||
book.setCreateTime(currentDate);
|
||||
book.setUpdateTime(currentDate);
|
||||
|
||||
}else{
|
||||
//老书更新
|
||||
//计算总字数
|
||||
totalWordCount += wordCount;
|
||||
}
|
||||
bookIndex.setUpdateTime(currentDate);
|
||||
|
||||
|
||||
|
||||
if(hasIndex != null){
|
||||
bookIndex.setId(hasIndex.getId());
|
||||
bookContent.setIndexId(hasIndex.getId());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -249,15 +262,29 @@ public class CrawlParser {
|
||||
isFindIndex = indexIdMatch.find() & indexNameMatch.find();
|
||||
}
|
||||
|
||||
|
||||
if (indexList.size() > 0) {
|
||||
//如果有爬到最新章节,则设置小说主表的最新章节信息
|
||||
//获取爬取到的最新章节
|
||||
BookIndex lastIndex = indexList.get(indexList.size()-1);
|
||||
book.setLastIndexId(lastIndex.getId());
|
||||
book.setLastIndexName(lastIndex.getIndexName());
|
||||
book.setLastIndexUpdateTime(currentDate);
|
||||
|
||||
}
|
||||
book.setWordCount(totalWordCount);
|
||||
book.setUpdateTime(currentDate);
|
||||
|
||||
if (indexList.size() == contentList.size() && indexList.size() > 0) {
|
||||
|
||||
result.put(BOOK_INDEX_LIST_KEY,indexList);
|
||||
result.put(BOOK_CONTENT_LIST_KEY,contentList);
|
||||
result.put(BOOK_INDEX_LIST_KEY, indexList);
|
||||
result.put(BOOK_CONTENT_LIST_KEY, contentList);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -267,7 +294,7 @@ public class CrawlParser {
|
||||
ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
|
||||
if (forEntity.getStatusCode() == HttpStatus.OK) {
|
||||
String body = forEntity.getBody();
|
||||
if(body.length() < Constants.INVALID_HTML_LENGTH){
|
||||
if (body.length() < Constants.INVALID_HTML_LENGTH) {
|
||||
return processErrorHttpResult(url);
|
||||
}
|
||||
//成功获得html内容
|
||||
@ -280,14 +307,30 @@ public class CrawlParser {
|
||||
|
||||
}
|
||||
|
||||
private static String getByHttpClientWithChrome(String url) {
|
||||
try {
|
||||
|
||||
String body = HttpUtil.getByHttpClientWithChrome(url);
|
||||
if (body != null && body.length() < Constants.INVALID_HTML_LENGTH) {
|
||||
return processErrorHttpResult(url);
|
||||
}
|
||||
//成功获得html内容
|
||||
return body;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return processErrorHttpResult(url);
|
||||
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private static String processErrorHttpResult(String url){
|
||||
private static String processErrorHttpResult(String url) {
|
||||
Integer count = retryCount.get();
|
||||
if(count == null){
|
||||
if (count == null) {
|
||||
count = 0;
|
||||
}
|
||||
if(count < Constants.HTTP_FAIL_RETRY_COUNT){
|
||||
Thread.sleep( new Random().nextInt(10*1000));
|
||||
if (count < Constants.HTTP_FAIL_RETRY_COUNT) {
|
||||
Thread.sleep(new Random().nextInt(10 * 1000));
|
||||
retryCount.set(++count);
|
||||
return getByHttpClient(url);
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ public class StarterListener implements ServletContextListener {
|
||||
Book book = CrawlParser.parseBook(ruleBean, needUpdateBook.getCrawlBookId());
|
||||
//这里只做老书更新
|
||||
book.setId(needUpdateBook.getId());
|
||||
book.setWordCount(needUpdateBook.getWordCount());
|
||||
if (needUpdateBook.getPicUrl() != null && needUpdateBook.getPicUrl().contains(Constants.LOCAL_PIC_PREFIX)) {
|
||||
//本地图片则不更新
|
||||
book.setPicUrl(null);
|
||||
|
@ -65,9 +65,8 @@ public interface BookService {
|
||||
* @param book 小说数据
|
||||
* @param bookIndexList 目录集合
|
||||
* @param bookContentList 内容集合
|
||||
* @param existBookIndexMap 已存在的章节Map
|
||||
* */
|
||||
void updateBookAndIndexAndContent(Book book, List<BookIndex> bookIndexList, List<BookContent> bookContentList, Map<Integer, BookIndex> existBookIndexMap);
|
||||
* @param existBookIndexMap 已存在的章节Map */
|
||||
void updateBookAndIndexAndContent(Book book, List<BookIndex> bookIndexList, List<BookContent> bookContentList, Map<Integer, BookIndex> existBookIndexMap);
|
||||
|
||||
/**
|
||||
* 更新一下最后一次的抓取时间
|
||||
|
@ -1,8 +1,11 @@
|
||||
package com.java2nb.novel.service;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.core.crawl.RuleBean;
|
||||
import com.java2nb.novel.entity.CrawlSingleTask;
|
||||
import com.java2nb.novel.entity.CrawlSource;
|
||||
import com.java2nb.novel.vo.CrawlSourceVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -22,9 +25,9 @@ public interface CrawlService {
|
||||
* 爬虫源分页列表
|
||||
* @param page 当前页码
|
||||
* @param pageSize 分页大小
|
||||
*@return 爬虫源集合
|
||||
*@return 爬虫源分页数据
|
||||
* */
|
||||
List<CrawlSource> listCrawlByPage(int page, int pageSize);
|
||||
PageBean<CrawlSource> listCrawlByPage(int page, int pageSize);
|
||||
|
||||
/**
|
||||
* 开启或停止爬虫
|
||||
@ -83,9 +86,9 @@ public interface CrawlService {
|
||||
* 单本采集任务分页列表查询
|
||||
* @param page 当前页码
|
||||
* @param pageSize 分页大小
|
||||
* @return 单本采集任务集合
|
||||
* @return 单本采集任务分页数据
|
||||
* */
|
||||
List<CrawlSingleTask> listCrawlSingleTaskByPage(int page, int pageSize);
|
||||
PageBean<CrawlSingleTask> listCrawlSingleTaskByPage(int page, int pageSize);
|
||||
|
||||
/**
|
||||
* 删除采集任务
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.java2nb.novel.service.impl;
|
||||
|
||||
import com.java2nb.novel.core.utils.IdWorker;
|
||||
import com.java2nb.novel.entity.Book;
|
||||
import com.java2nb.novel.entity.BookContent;
|
||||
import com.java2nb.novel.entity.BookIndex;
|
||||
@ -79,12 +78,9 @@ public class BookServiceImpl implements BookService {
|
||||
|
||||
if(bookIndexList.size()>0) {
|
||||
|
||||
if (book.getId() == null) {
|
||||
book.setId(new IdWorker().nextId());
|
||||
}
|
||||
|
||||
//保存小说主表
|
||||
|
||||
book.setCreateTime(new Date());
|
||||
bookMapper.insertSelective(book);
|
||||
|
||||
//批量保存目录和内容
|
||||
@ -109,7 +105,7 @@ public class BookServiceImpl implements BookService {
|
||||
|
||||
@Override
|
||||
public Map<Integer, BookIndex> queryExistBookIndexMap(Long bookId) {
|
||||
List<BookIndex> bookIndexs = bookIndexMapper.selectMany(select(BookIndexDynamicSqlSupport.id,BookIndexDynamicSqlSupport.indexNum,BookIndexDynamicSqlSupport.indexName)
|
||||
List<BookIndex> bookIndexs = bookIndexMapper.selectMany(select(BookIndexDynamicSqlSupport.id,BookIndexDynamicSqlSupport.indexNum,BookIndexDynamicSqlSupport.indexName,BookIndexDynamicSqlSupport.wordCount)
|
||||
.from(BookIndexDynamicSqlSupport.bookIndex)
|
||||
.where(BookIndexDynamicSqlSupport.bookId,isEqualTo(bookId))
|
||||
.build()
|
||||
@ -122,36 +118,19 @@ public class BookServiceImpl implements BookService {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void updateBookAndIndexAndContent(Book book, List<BookIndex> bookIndexList, List<BookContent> bookContentList, Map<Integer, BookIndex> existBookIndexMap) {
|
||||
Date currentDate = new Date();
|
||||
public void updateBookAndIndexAndContent(Book book, List<BookIndex> bookIndexList, List<BookContent> bookContentList, Map<Integer, BookIndex> existBookIndexMap) {
|
||||
for (int i = 0; i < bookIndexList.size(); i++) {
|
||||
BookIndex bookIndex = bookIndexList.get(i);
|
||||
BookContent bookContent = bookContentList.get(i);
|
||||
|
||||
//插入或更新目录
|
||||
Integer wordCount = bookContent.getContent().length();
|
||||
bookIndex.setWordCount(wordCount);
|
||||
bookIndex.setUpdateTime(currentDate);
|
||||
|
||||
if(bookIndex.getId() == null) {
|
||||
if(!existBookIndexMap.containsKey(bookIndex.getIndexNum())) {
|
||||
//插入
|
||||
bookIndex.setBookId(book.getId());
|
||||
Long indexId = new IdWorker().nextId();
|
||||
bookIndex.setId(indexId);
|
||||
bookIndex.setCreateTime(currentDate);
|
||||
bookIndexMapper.insertSelective(bookIndex);
|
||||
}else{
|
||||
//更新
|
||||
bookIndexMapper.updateByPrimaryKeySelective(bookIndex);
|
||||
}
|
||||
|
||||
if(bookContent.getIndexId() == null) {
|
||||
//插入
|
||||
bookContent.setIndexId(bookIndex.getId());
|
||||
bookContentMapper.insertSelective(bookContent);
|
||||
}else{
|
||||
//更新
|
||||
|
||||
bookIndexMapper.updateByPrimaryKeySelective(bookIndex);
|
||||
bookContentMapper.update(update(BookContentDynamicSqlSupport.bookContent)
|
||||
.set(BookContentDynamicSqlSupport.content)
|
||||
.equalTo(bookContent.getContent())
|
||||
@ -160,21 +139,10 @@ public class BookServiceImpl implements BookService {
|
||||
.render(RenderingStrategies.MYBATIS3));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//更新小说主表
|
||||
if(bookIndexList.size()>0) {
|
||||
//有更新章节,才需要更新以下字段
|
||||
book.setWordCount(queryTotalWordCount(book.getId()));
|
||||
BookIndex lastIndex = bookIndexList.get(bookIndexList.size()-1);
|
||||
if(!existBookIndexMap.containsKey(lastIndex.getIndexNum())) {
|
||||
//如果最新章节不在已存在章节中,那么更新小说表最新章节信息
|
||||
book.setLastIndexId(lastIndex.getId());
|
||||
book.setLastIndexName(lastIndex.getIndexName());
|
||||
book.setLastIndexUpdateTime(currentDate);
|
||||
}
|
||||
}
|
||||
book.setUpdateTime(currentDate);
|
||||
book.setBookName(null);
|
||||
book.setAuthorName(null);
|
||||
if(Constants.VISIT_COUNT_DEFAULT.equals(book.getVisitCount())) {
|
||||
|
@ -1,13 +1,17 @@
|
||||
package com.java2nb.novel.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.core.cache.CacheKey;
|
||||
import com.java2nb.novel.core.cache.CacheService;
|
||||
import com.java2nb.novel.core.crawl.CrawlParser;
|
||||
import com.java2nb.novel.core.crawl.RuleBean;
|
||||
import com.java2nb.novel.core.enums.ResponseStatus;
|
||||
import com.java2nb.novel.core.exception.BusinessException;
|
||||
import com.java2nb.novel.core.utils.BeanUtil;
|
||||
import com.java2nb.novel.core.utils.IdWorker;
|
||||
import com.java2nb.novel.core.utils.SpringUtil;
|
||||
import com.java2nb.novel.core.utils.ThreadUtil;
|
||||
@ -16,6 +20,8 @@ import com.java2nb.novel.entity.CrawlSource;
|
||||
import com.java2nb.novel.mapper.*;
|
||||
import com.java2nb.novel.service.BookService;
|
||||
import com.java2nb.novel.service.CrawlService;
|
||||
import com.java2nb.novel.vo.CrawlSingleTaskVO;
|
||||
import com.java2nb.novel.vo.CrawlSourceVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -30,6 +36,7 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.java2nb.novel.core.utils.HttpUtil.getByHttpClient;
|
||||
import static com.java2nb.novel.core.utils.HttpUtil.getByHttpClientWithChrome;
|
||||
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.crawlBookId;
|
||||
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.crawlSourceId;
|
||||
import static com.java2nb.novel.mapper.CrawlSourceDynamicSqlSupport.*;
|
||||
@ -65,14 +72,17 @@ public class CrawlServiceImpl implements CrawlService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrawlSource> listCrawlByPage(int page, int pageSize) {
|
||||
public PageBean<CrawlSource> listCrawlByPage(int page, int pageSize) {
|
||||
PageHelper.startPage(page, pageSize);
|
||||
SelectStatementProvider render = select(id, sourceName, sourceStatus, createTime, updateTime)
|
||||
.from(crawlSource)
|
||||
.orderBy(updateTime)
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3);
|
||||
return crawlSourceMapper.selectMany(render);
|
||||
List<CrawlSource> crawlSources = crawlSourceMapper.selectMany(render);
|
||||
PageBean<CrawlSource> pageBean = new PageBean<>(crawlSources);
|
||||
pageBean.setList(BeanUtil.copyList(crawlSources, CrawlSourceVO.class));
|
||||
return pageBean;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@ -155,14 +165,17 @@ public class CrawlServiceImpl implements CrawlService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrawlSingleTask> listCrawlSingleTaskByPage(int page, int pageSize) {
|
||||
public PageBean<CrawlSingleTask> listCrawlSingleTaskByPage(int page, int pageSize) {
|
||||
PageHelper.startPage(page, pageSize);
|
||||
SelectStatementProvider render = select(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask.allColumns())
|
||||
.from(CrawlSingleTaskDynamicSqlSupport.crawlSingleTask)
|
||||
.orderBy(CrawlSingleTaskDynamicSqlSupport.createTime.descending())
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3);
|
||||
return crawlSingleTaskMapper.selectMany(render);
|
||||
List<CrawlSingleTask> crawlSingleTasks = crawlSingleTaskMapper.selectMany(render);
|
||||
PageBean<CrawlSingleTask> pageBean = new PageBean<>(crawlSingleTasks);
|
||||
pageBean.setList(BeanUtil.copyList(crawlSingleTasks, CrawlSingleTaskVO.class));
|
||||
return pageBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -217,7 +230,7 @@ public class CrawlServiceImpl implements CrawlService {
|
||||
.replace("{catId}", ruleBean.getCatIdRule().get("catId" + catId))
|
||||
.replace("{page}", page + "");
|
||||
|
||||
String bookListHtml = getByHttpClient(catBookListUrl);
|
||||
String bookListHtml = getByHttpClientWithChrome(catBookListUrl);
|
||||
if (bookListHtml != null) {
|
||||
Pattern bookIdPatten = Pattern.compile(ruleBean.getBookIdPatten());
|
||||
Matcher bookIdMatcher = bookIdPatten.matcher(bookListHtml);
|
||||
|
3
novel-crawl/src/main/resources/application-prod.yml
Normal file
3
novel-crawl/src/main/resources/application-prod.yml
Normal file
@ -0,0 +1,3 @@
|
||||
spring:
|
||||
profiles:
|
||||
include: [common-prod]
|
@ -1,6 +1,9 @@
|
||||
#端口号
|
||||
server:
|
||||
port: 8081
|
||||
servlet:
|
||||
session:
|
||||
timeout: 1D
|
||||
|
||||
spring:
|
||||
profiles:
|
||||
@ -19,3 +22,6 @@ crawl:
|
||||
thread: 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
<select id="queryNeedUpdateBook" resultType="com.java2nb.novel.entity.Book">
|
||||
|
||||
select id,crawl_source_id,crawl_book_id,crawl_last_time,pic_url
|
||||
select id,crawl_source_id,crawl_book_id,crawl_last_time,pic_url,word_count
|
||||
from book where last_index_update_time > #{startDate} and crawl_source_id is not null
|
||||
order by crawl_last_time
|
||||
limit ${limit}
|
||||
@ -15,8 +15,7 @@
|
||||
|
||||
<select id="queryTotalWordCount" parameterType="long" resultType="int">
|
||||
|
||||
select sum(t2.word_count) from book t1 inner join book_index t2
|
||||
on t1.id = t2.book_id and t1.id = #{bookId}
|
||||
select sum(word_count) from book_index where book_id = #{bookId}
|
||||
</select>
|
||||
|
||||
<update id="updateCrawlLastTime">
|
||||
|
@ -96,7 +96,7 @@
|
||||
<script language="javascript" type="text/javascript">
|
||||
$(function () {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
type: "get",
|
||||
url: "/crawl/listCrawlByPage",
|
||||
data: {'curr':1,'limit':100},
|
||||
dataType: "json",
|
||||
|
@ -125,7 +125,7 @@
|
||||
function search(curr, limit) {
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
type: "get",
|
||||
url: "/crawl/listCrawlSingleTaskByPage",
|
||||
data: {'curr': curr, 'limit': limit},
|
||||
dataType: "json",
|
||||
@ -205,9 +205,9 @@
|
||||
function del(id) {
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/crawl/delCrawlSingleTask",
|
||||
data: {'id': id},
|
||||
type: "delete",
|
||||
url: "/crawl/delCrawlSingleTask/"+id,
|
||||
data: {},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
|
@ -117,7 +117,7 @@
|
||||
示例:<b></b>
|
||||
<li><input type="text" id="visitCountPatten" class="s_input icon_key"
|
||||
placeholder="小说点击量的正则表达式:"></li>
|
||||
示例:<b><p class=\"review\"></b>
|
||||
示例:<b><p class="review"></b>
|
||||
<li><input type="text" id="descStart" class="s_input icon_key"
|
||||
placeholder="小说简介开始截取字符串:"></li>
|
||||
示例:<b></p></b>
|
||||
|
@ -122,7 +122,7 @@
|
||||
function search(curr, limit) {
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
type: "get",
|
||||
url: "/crawl/listCrawlByPage",
|
||||
data: {'curr':curr,'limit':limit},
|
||||
dataType: "json",
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>novel</artifactId>
|
||||
<groupId>com.java2nb</groupId>
|
||||
<version>3.0.2</version>
|
||||
<version>3.5.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -39,6 +39,12 @@
|
||||
<version>${jest.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.elasticsearch.client</groupId>
|
||||
<artifactId>elasticsearch-rest-high-level-client</artifactId>
|
||||
<version>${elasticsearch.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--aliyunOSS-->
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
|
@ -5,6 +5,7 @@ import io.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@ -20,6 +21,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@EnableTransactionManagement
|
||||
@EnableScheduling
|
||||
@EnableCaching
|
||||
@ServletComponentScan
|
||||
@MapperScan(basePackages = {"com.java2nb.novel.mapper"})
|
||||
@Import(FdfsClientConfig.class)
|
||||
public class FrontNovelApplication {
|
||||
|
@ -13,10 +13,7 @@ import com.java2nb.novel.service.BookService;
|
||||
import com.java2nb.novel.service.FriendLinkService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@ -38,7 +35,7 @@ public class AuthorController extends BaseController{
|
||||
/**
|
||||
* 校验笔名是否存在
|
||||
* */
|
||||
@PostMapping("checkPenName")
|
||||
@GetMapping("checkPenName")
|
||||
public ResultBean checkPenName(String penName){
|
||||
|
||||
return ResultBean.ok(authorService.checkPenName(penName));
|
||||
@ -47,11 +44,10 @@ public class AuthorController extends BaseController{
|
||||
/**
|
||||
* 作家发布小说分页列表查询
|
||||
* */
|
||||
@PostMapping("listBookByPage")
|
||||
@GetMapping("listBookByPage")
|
||||
public ResultBean listBookByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "10") int pageSize ,HttpServletRequest request){
|
||||
|
||||
return ResultBean.ok(new PageInfo<>(bookService.listBookPageByUserId(getUserDetails(request).getId(),page,pageSize)
|
||||
));
|
||||
return ResultBean.ok(bookService.listBookPageByUserId(getUserDetails(request).getId(),page,pageSize));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,8 +86,8 @@ public class AuthorController extends BaseController{
|
||||
/**
|
||||
* 删除章节
|
||||
*/
|
||||
@PostMapping("deleteIndex")
|
||||
public ResultBean deleteIndex(Long indexId, HttpServletRequest request) {
|
||||
@DeleteMapping("deleteIndex/{indexId}")
|
||||
public ResultBean deleteIndex(@PathVariable("indexId") Long indexId, HttpServletRequest request) {
|
||||
|
||||
Author author = checkAuthor(request);
|
||||
|
||||
@ -136,8 +132,8 @@ public class AuthorController extends BaseController{
|
||||
/**
|
||||
* 查询章节内容
|
||||
*/
|
||||
@PostMapping("queryIndexContent")
|
||||
public ResultBean queryIndexContent(Long indexId, HttpServletRequest request) {
|
||||
@GetMapping("queryIndexContent/{indexId}")
|
||||
public ResultBean queryIndexContent(@PathVariable("indexId") Long indexId, HttpServletRequest request) {
|
||||
|
||||
Author author = checkAuthor(request);
|
||||
|
||||
@ -167,7 +163,7 @@ public class AuthorController extends BaseController{
|
||||
/**
|
||||
* 作家日收入统计数据分页列表查询
|
||||
* */
|
||||
@PostMapping("listIncomeDailyByPage")
|
||||
@GetMapping("listIncomeDailyByPage")
|
||||
public ResultBean listIncomeDailyByPage(@RequestParam(value = "curr", defaultValue = "1") int page,
|
||||
@RequestParam(value = "limit", defaultValue = "10") int pageSize ,
|
||||
@RequestParam(value = "bookId", defaultValue = "0") Long bookId,
|
||||
@ -175,22 +171,20 @@ public class AuthorController extends BaseController{
|
||||
@RequestParam(value = "endTime",defaultValue = "2030-01-01") Date endTime,
|
||||
HttpServletRequest request){
|
||||
|
||||
return ResultBean.ok(new PageInfo<>(authorService.listIncomeDailyByPage(page,pageSize,getUserDetails(request).getId(),bookId,startTime,endTime)
|
||||
));
|
||||
return ResultBean.ok(authorService.listIncomeDailyByPage(page,pageSize,getUserDetails(request).getId(),bookId,startTime,endTime));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 作家月收入统计数据分页列表查询
|
||||
* */
|
||||
@PostMapping("listIncomeMonthByPage")
|
||||
@GetMapping("listIncomeMonthByPage")
|
||||
public ResultBean listIncomeMonthByPage(@RequestParam(value = "curr", defaultValue = "1") int page,
|
||||
@RequestParam(value = "limit", defaultValue = "10") int pageSize ,
|
||||
@RequestParam(value = "bookId", defaultValue = "0") Long bookId,
|
||||
HttpServletRequest request){
|
||||
|
||||
return ResultBean.ok(new PageInfo<>(authorService.listIncomeMonthByPage(page,pageSize,getUserDetails(request).getId(),bookId)
|
||||
));
|
||||
return ResultBean.ok(authorService.listIncomeMonthByPage(page,pageSize,getUserDetails(request).getId(),bookId));
|
||||
}
|
||||
|
||||
private Author checkAuthor(HttpServletRequest request) {
|
||||
|
@ -1,21 +1,20 @@
|
||||
package com.java2nb.novel.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.core.bean.ResultBean;
|
||||
import com.java2nb.novel.core.bean.UserDetails;
|
||||
import com.java2nb.novel.core.enums.ResponseStatus;
|
||||
import com.java2nb.novel.entity.Book;
|
||||
import com.java2nb.novel.entity.BookComment;
|
||||
import com.java2nb.novel.search.BookSP;
|
||||
import com.java2nb.novel.vo.BookSpVO;
|
||||
import com.java2nb.novel.service.BookService;
|
||||
import com.java2nb.novel.vo.BookVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
@ -41,7 +40,7 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
* 查询首页小说设置列表数据
|
||||
* */
|
||||
@PostMapping("listBookSetting")
|
||||
@GetMapping("listBookSetting")
|
||||
public ResultBean listBookSetting(){
|
||||
return ResultBean.ok(bookService.listBookSettingVO());
|
||||
}
|
||||
@ -49,7 +48,7 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
* 查询首页点击榜单数据
|
||||
* */
|
||||
@PostMapping("listClickRank")
|
||||
@GetMapping("listClickRank")
|
||||
public ResultBean listClickRank(){
|
||||
return ResultBean.ok(bookService.listClickRank());
|
||||
}
|
||||
@ -57,7 +56,7 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
* 查询首页新书榜单数据
|
||||
* */
|
||||
@PostMapping("listNewRank")
|
||||
@GetMapping("listNewRank")
|
||||
public ResultBean listNewRank(){
|
||||
return ResultBean.ok(bookService.listNewRank());
|
||||
}
|
||||
@ -65,7 +64,7 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
* 查询首页更新榜单数据
|
||||
* */
|
||||
@PostMapping("listUpdateRank")
|
||||
@GetMapping("listUpdateRank")
|
||||
public ResultBean listUpdateRank(){
|
||||
return ResultBean.ok(bookService.listUpdateRank());
|
||||
}
|
||||
@ -73,7 +72,7 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
* 查询小说分类列表
|
||||
* */
|
||||
@PostMapping("listBookCategory")
|
||||
@GetMapping("listBookCategory")
|
||||
public ResultBean listBookCategory(){
|
||||
return ResultBean.ok(bookService.listBookCategory());
|
||||
}
|
||||
@ -81,17 +80,16 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
* 分页搜索
|
||||
* */
|
||||
@PostMapping("searchByPage")
|
||||
public ResultBean searchByPage(BookSP bookSP, @RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "20") int pageSize){
|
||||
PageInfo<BookVO> pageInfo = bookService.searchByPage(bookSP,page,pageSize);
|
||||
return ResultBean.ok(pageInfo);
|
||||
@GetMapping("searchByPage")
|
||||
public ResultBean searchByPage(BookSpVO bookSP, @RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "20") int pageSize){
|
||||
return ResultBean.ok(bookService.searchByPage(bookSP,page,pageSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询小说详情信息
|
||||
* */
|
||||
@PostMapping("queryBookDetail")
|
||||
public ResultBean queryBookDetail(Long id){
|
||||
@GetMapping("queryBookDetail/{id}")
|
||||
public ResultBean queryBookDetail(@PathVariable("id") Long id){
|
||||
return ResultBean.ok(bookService.queryBookDetail(id));
|
||||
}
|
||||
|
||||
@ -99,7 +97,7 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
* 查询小说排行信息
|
||||
* */
|
||||
@PostMapping("listRank")
|
||||
@GetMapping("listRank")
|
||||
public ResultBean listRank(@RequestParam(value = "type",defaultValue = "0") Byte type,@RequestParam(value = "limit",defaultValue = "30") Integer limit){
|
||||
return ResultBean.ok(bookService.listRank(type,limit));
|
||||
}
|
||||
@ -120,7 +118,7 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
* 查询章节相关信息
|
||||
* */
|
||||
@PostMapping("queryBookIndexAbout")
|
||||
@GetMapping("queryBookIndexAbout")
|
||||
public ResultBean queryBookIndexAbout(Long bookId,Long lastBookIndexId) {
|
||||
Map<String,Object> data = new HashMap<>(2);
|
||||
data.put("bookIndexCount",bookService.queryIndexCount(bookId));
|
||||
@ -135,7 +133,7 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
* 根据分类id查询同类推荐书籍
|
||||
* */
|
||||
@PostMapping("listRecBookByCatId")
|
||||
@GetMapping("listRecBookByCatId")
|
||||
public ResultBean listRecBookByCatId(Integer catId) {
|
||||
return ResultBean.ok(bookService.listRecBookByCatId(catId));
|
||||
}
|
||||
@ -144,9 +142,9 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
*分页查询书籍评论列表
|
||||
* */
|
||||
@PostMapping("listCommentByPage")
|
||||
@GetMapping("listCommentByPage")
|
||||
public ResultBean listCommentByPage(@RequestParam("bookId") Long bookId,@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize) {
|
||||
return ResultBean.ok(new PageInfo<>(bookService.listCommentByPage(null,bookId,page,pageSize)));
|
||||
return ResultBean.ok(bookService.listCommentByPage(null,bookId,page,pageSize));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,7 +163,7 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
* 根据小说ID查询小说前十条最新更新目录集合
|
||||
* */
|
||||
@PostMapping("queryNewIndexList")
|
||||
@GetMapping("queryNewIndexList")
|
||||
public ResultBean queryNewIndexList(Long bookId){
|
||||
return ResultBean.ok(bookService.queryIndexList(bookId,"index_num desc",1,10));
|
||||
}
|
||||
@ -173,9 +171,9 @@ public class BookController extends BaseController{
|
||||
/**
|
||||
* 目录页
|
||||
* */
|
||||
@PostMapping("/queryIndexList")
|
||||
public ResultBean indexList(Long bookId,@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize,@RequestParam(value = "orderBy") String orderBy) {
|
||||
return ResultBean.ok(new PageInfo<>(bookService.queryIndexList(bookId,orderBy,page,pageSize)));
|
||||
@GetMapping("/queryIndexList")
|
||||
public ResultBean indexList(Long bookId,@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize,@RequestParam(value = "orderBy",defaultValue = "index_num desc") String orderBy) {
|
||||
return ResultBean.ok(new PageBean<>(bookService.queryIndexList(bookId,orderBy,page,pageSize)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,6 +4,7 @@ import com.java2nb.novel.core.bean.ResultBean;
|
||||
import com.java2nb.novel.service.FriendLinkService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@ -22,7 +23,7 @@ public class FriendLinkController {
|
||||
/**
|
||||
* 查询首页友情链接
|
||||
* */
|
||||
@PostMapping("listIndexLink")
|
||||
@GetMapping("listIndexLink")
|
||||
public ResultBean listIndexLink(){
|
||||
return ResultBean.ok(friendLinkService.listIndexLink());
|
||||
}
|
||||
|
@ -5,10 +5,7 @@ import com.java2nb.novel.core.bean.ResultBean;
|
||||
import com.java2nb.novel.service.NewsService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
@ -24,7 +21,7 @@ public class NewsController {
|
||||
/**
|
||||
* 查询首页新闻
|
||||
* */
|
||||
@PostMapping("listIndexNews")
|
||||
@GetMapping("listIndexNews")
|
||||
public ResultBean listIndexNews(){
|
||||
return ResultBean.ok(newsService.listIndexNews());
|
||||
}
|
||||
@ -32,9 +29,9 @@ public class NewsController {
|
||||
/**
|
||||
* 分页查询新闻列表
|
||||
* */
|
||||
@PostMapping("listByPage")
|
||||
@GetMapping("listByPage")
|
||||
public ResultBean listByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize){
|
||||
return ResultBean.ok(new PageInfo<>(newsService.listByPage(page,pageSize)));
|
||||
return ResultBean.ok(newsService.listByPage(page,pageSize));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,214 +0,0 @@
|
||||
package com.java2nb.novel.controller;
|
||||
|
||||
import com.java2nb.novel.core.bean.ResultBean;
|
||||
import com.java2nb.novel.core.bean.UserDetails;
|
||||
import com.java2nb.novel.core.utils.ThreadLocalUtil;
|
||||
import com.java2nb.novel.entity.*;
|
||||
import com.java2nb.novel.service.AuthorService;
|
||||
import com.java2nb.novel.service.BookService;
|
||||
import com.java2nb.novel.service.NewsService;
|
||||
import com.java2nb.novel.service.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Controller
|
||||
public class PageController extends BaseController{
|
||||
|
||||
private final BookService bookService;
|
||||
|
||||
private final NewsService newsService;
|
||||
|
||||
private final AuthorService authorService;
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
|
||||
@RequestMapping("{url}.html")
|
||||
public String module(@PathVariable("url") String url) {
|
||||
return url;
|
||||
}
|
||||
|
||||
@RequestMapping("{module}/{url}.html")
|
||||
public String module2(@PathVariable("module") String module, @PathVariable("url") String url,HttpServletRequest request) {
|
||||
|
||||
if(request.getRequestURI().startsWith("/author")) {
|
||||
//访问作者专区
|
||||
UserDetails user = getUserDetails(request);
|
||||
if (user == null) {
|
||||
//未登录
|
||||
return "redirect:/user/login.html?originUrl=" + request.getRequestURI();
|
||||
}
|
||||
|
||||
boolean isAuthor = authorService.isAuthor(user.getId());
|
||||
if (!isAuthor) {
|
||||
return "redirect:/author/register.html" ;
|
||||
}
|
||||
}
|
||||
|
||||
return module + "/" + url;
|
||||
}
|
||||
|
||||
@RequestMapping("{module}/{classify}/{url}.html")
|
||||
public String module3(@PathVariable("module") String module, @PathVariable("classify") String classify, @PathVariable("url") String url) {
|
||||
return module + "/" + classify + "/" + url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页
|
||||
* */
|
||||
@RequestMapping(path = {"/", "/index", "/index.html"})
|
||||
public String index() {
|
||||
return ThreadLocalUtil.getTemplateDir()+"index";
|
||||
}
|
||||
|
||||
/**
|
||||
* 作品页
|
||||
* */
|
||||
@RequestMapping("book/bookclass.html")
|
||||
public String bookClass() {
|
||||
return "book/bookclass";
|
||||
}
|
||||
|
||||
/**
|
||||
* 排行页
|
||||
* */
|
||||
@RequestMapping("book/book_ranking.html")
|
||||
public String bookRank() {
|
||||
|
||||
return ThreadLocalUtil.getTemplateDir()+"book/book_ranking";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 详情页
|
||||
* */
|
||||
@RequestMapping("/book/{bookId}.html")
|
||||
public String bookDetail(@PathVariable("bookId") Long bookId, Model model) {
|
||||
Book book = bookService.queryBookDetail(bookId);
|
||||
model.addAttribute("book",book);
|
||||
if(book.getLastIndexId() != null) {
|
||||
//查询首章目录ID
|
||||
Long firstBookIndexId = bookService.queryFirstBookIndexId(bookId);
|
||||
model.addAttribute("firstBookIndexId", firstBookIndexId);
|
||||
}
|
||||
return ThreadLocalUtil.getTemplateDir()+"book/book_detail";
|
||||
}
|
||||
|
||||
/**
|
||||
* 目录页
|
||||
* */
|
||||
@RequestMapping("/book/indexList-{bookId}.html")
|
||||
public String indexList(@PathVariable("bookId") Long bookId, Model model) {
|
||||
Book book = bookService.queryBookDetail(bookId);
|
||||
model.addAttribute("book",book);
|
||||
List<BookIndex> bookIndexList = bookService.queryIndexList(bookId,null,1,null);
|
||||
model.addAttribute("bookIndexList",bookIndexList);
|
||||
model.addAttribute("bookIndexCount",bookIndexList.size());
|
||||
return ThreadLocalUtil.getTemplateDir()+"book/book_index";
|
||||
}
|
||||
|
||||
/**
|
||||
* 内容页
|
||||
* */
|
||||
@RequestMapping("/book/{bookId}/{bookIndexId}.html")
|
||||
public String indexList(@PathVariable("bookId") Long bookId,@PathVariable("bookIndexId") Long bookIndexId, HttpServletRequest request,Model model) {
|
||||
//查询书籍
|
||||
Book book = bookService.queryBookDetail(bookId);
|
||||
model.addAttribute("book",book);
|
||||
//查询目录
|
||||
BookIndex bookIndex = bookService.queryBookIndex(bookIndexId);
|
||||
model.addAttribute("bookIndex",bookIndex);
|
||||
//查询上一章节目录ID
|
||||
Long preBookIndexId = bookService.queryPreBookIndexId(bookId,bookIndex.getIndexNum());
|
||||
model.addAttribute("preBookIndexId",preBookIndexId);
|
||||
//查询下一章目录ID
|
||||
Long nextBookIndexId = bookService.queryNextBookIndexId(bookId,bookIndex.getIndexNum());
|
||||
model.addAttribute("nextBookIndexId",nextBookIndexId);
|
||||
//查询内容
|
||||
BookContent bookContent = bookService.queryBookContent(bookIndex.getId());
|
||||
model.addAttribute("bookContent",bookContent);
|
||||
|
||||
boolean needBuy = false;
|
||||
//判断该目录是否收费
|
||||
if(bookIndex.getIsVip()!=null && bookIndex.getIsVip() == 1 ){
|
||||
UserDetails user = getUserDetails(request);
|
||||
if(user == null){
|
||||
//未登录
|
||||
return "redirect:/user/login.html?originUrl="+request.getRequestURI();
|
||||
}
|
||||
//收费,判断用户是否购买过该目录
|
||||
boolean isBuy = userService.queryIsBuyBookIndex(user.getId(),bookIndexId);
|
||||
if(!isBuy){
|
||||
//没有购买过,需要购买
|
||||
bookContent.setContent(null);
|
||||
needBuy = true;
|
||||
}
|
||||
}
|
||||
model.addAttribute("needBuy",needBuy);
|
||||
return ThreadLocalUtil.getTemplateDir()+"book/book_content";
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论页面
|
||||
* */
|
||||
@RequestMapping("/book/comment-{bookId}.html")
|
||||
public String commentList(@PathVariable("bookId") Long bookId, Model model) {
|
||||
//查询书籍
|
||||
Book book = bookService.queryBookDetail(bookId);
|
||||
model.addAttribute("book",book);
|
||||
return "book/book_comment";
|
||||
}
|
||||
|
||||
/**
|
||||
* 新闻内容页面
|
||||
* */
|
||||
@RequestMapping("/about/newsInfo-{newsId}.html")
|
||||
public String newsInfo(@PathVariable("newsId") Long newsId, Model model) {
|
||||
//查询新闻
|
||||
News news = newsService.queryNewsInfo(newsId);
|
||||
model.addAttribute("news",news);
|
||||
return "about/news_info";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 作者注册页面
|
||||
* */
|
||||
@RequestMapping("author/register.html")
|
||||
public String authorRegister(Author author, HttpServletRequest request, Model model){
|
||||
UserDetails user = getUserDetails(request);
|
||||
if(user == null){
|
||||
//未登录
|
||||
return "redirect:/user/login.html?originUrl=/author/register.html";
|
||||
}
|
||||
|
||||
if(StringUtils.isNotBlank(author.getInviteCode())) {
|
||||
//提交作者注册信息
|
||||
String errorInfo = authorService.register(user.getId(), author);
|
||||
if(StringUtils.isBlank(errorInfo)){
|
||||
//注册成功
|
||||
return "redirect:/author/index.html";
|
||||
}
|
||||
model.addAttribute("LabErr",errorInfo);
|
||||
model.addAttribute("author",author);
|
||||
}
|
||||
return "author/register";
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -5,7 +5,7 @@ import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import com.alipay.api.request.AlipayTradePagePayRequest;
|
||||
import com.java2nb.novel.core.bean.UserDetails;
|
||||
import com.java2nb.novel.core.config.AlipayConfig;
|
||||
import com.java2nb.novel.core.config.AlipayProperties;
|
||||
import com.java2nb.novel.service.OrderService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
@ -31,7 +31,7 @@ import java.util.Map;
|
||||
public class PayController extends BaseController {
|
||||
|
||||
|
||||
private final AlipayConfig alipayConfig;
|
||||
private final AlipayProperties alipayConfig;
|
||||
|
||||
private final OrderService orderService;
|
||||
|
||||
|
@ -1,27 +1,23 @@
|
||||
package com.java2nb.novel.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.java2nb.novel.core.bean.ResultBean;
|
||||
import com.java2nb.novel.core.bean.UserDetails;
|
||||
import com.java2nb.novel.core.cache.CacheService;
|
||||
import com.java2nb.novel.core.enums.ResponseStatus;
|
||||
import com.java2nb.novel.core.utils.RandomValidateCodeUtil;
|
||||
import com.java2nb.novel.core.valid.AddGroup;
|
||||
import com.java2nb.novel.core.valid.UpdateGroup;
|
||||
import com.java2nb.novel.entity.User;
|
||||
import com.java2nb.novel.entity.UserBuyRecord;
|
||||
import com.java2nb.novel.form.UserForm;
|
||||
import com.java2nb.novel.service.BookService;
|
||||
import com.java2nb.novel.service.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -45,12 +41,7 @@ public class UserController extends BaseController {
|
||||
* 登陆
|
||||
*/
|
||||
@PostMapping("login")
|
||||
public ResultBean login(@Valid UserForm user, BindingResult result) {
|
||||
//判断参数是否合法
|
||||
if (result.hasErrors()) {
|
||||
log.info(result.getAllErrors().toString());
|
||||
return ResultBean.fail(ResponseStatus.PARAM_ERROR);
|
||||
}
|
||||
public ResultBean login(User user) {
|
||||
|
||||
//登陆
|
||||
UserDetails userDetails = userService.login(user);
|
||||
@ -67,13 +58,8 @@ public class UserController extends BaseController {
|
||||
* 注册
|
||||
*/
|
||||
@PostMapping("register")
|
||||
public ResultBean register(@Valid UserForm user, @RequestParam(value = "velCode", defaultValue = "") String velCode, BindingResult result) {
|
||||
public ResultBean register(@Validated({AddGroup.class}) User user, @RequestParam(value = "velCode", defaultValue = "") String velCode) {
|
||||
|
||||
//判断参数是否合法
|
||||
if (result.hasErrors()) {
|
||||
log.info(result.getAllErrors().toString());
|
||||
return ResultBean.fail(ResponseStatus.PARAM_ERROR);
|
||||
}
|
||||
|
||||
//判断验证码是否正确
|
||||
if (!velCode.equals(cacheService.get(RandomValidateCodeUtil.RANDOM_CODE_KEY))) {
|
||||
@ -115,7 +101,7 @@ public class UserController extends BaseController {
|
||||
/**
|
||||
* 查询小说是否已加入书架
|
||||
*/
|
||||
@PostMapping("queryIsInShelf")
|
||||
@GetMapping("queryIsInShelf")
|
||||
public ResultBean queryIsInShelf(Long bookId, HttpServletRequest request) {
|
||||
UserDetails userDetails = getUserDetails(request);
|
||||
if (userDetails == null) {
|
||||
@ -140,8 +126,8 @@ public class UserController extends BaseController {
|
||||
/**
|
||||
* 移出书架
|
||||
* */
|
||||
@PostMapping("removeFromBookShelf")
|
||||
public ResultBean removeFromBookShelf(Long bookId, HttpServletRequest request) {
|
||||
@DeleteMapping("removeFromBookShelf/{bookId}")
|
||||
public ResultBean removeFromBookShelf(@PathVariable("bookId") Long bookId, HttpServletRequest request) {
|
||||
UserDetails userDetails = getUserDetails(request);
|
||||
if (userDetails == null) {
|
||||
return ResultBean.fail(ResponseStatus.NO_LOGIN);
|
||||
@ -153,25 +139,25 @@ public class UserController extends BaseController {
|
||||
/**
|
||||
* 分页查询书架
|
||||
* */
|
||||
@PostMapping("listBookShelfByPage")
|
||||
@GetMapping("listBookShelfByPage")
|
||||
public ResultBean listBookShelfByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "10") int pageSize,HttpServletRequest request) {
|
||||
UserDetails userDetails = getUserDetails(request);
|
||||
if (userDetails == null) {
|
||||
return ResultBean.fail(ResponseStatus.NO_LOGIN);
|
||||
}
|
||||
return ResultBean.ok(new PageInfo<>(userService.listBookShelfByPage(userDetails.getId(),page,pageSize)));
|
||||
return ResultBean.ok(userService.listBookShelfByPage(userDetails.getId(),page,pageSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询阅读记录
|
||||
* */
|
||||
@PostMapping("listReadHistoryByPage")
|
||||
@GetMapping("listReadHistoryByPage")
|
||||
public ResultBean listReadHistoryByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "10") int pageSize,HttpServletRequest request) {
|
||||
UserDetails userDetails = getUserDetails(request);
|
||||
if (userDetails == null) {
|
||||
return ResultBean.fail(ResponseStatus.NO_LOGIN);
|
||||
}
|
||||
return ResultBean.ok(new PageInfo<>(userService.listReadHistoryByPage(userDetails.getId(),page,pageSize)));
|
||||
return ResultBean.ok(userService.listReadHistoryByPage(userDetails.getId(),page,pageSize));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -203,19 +189,19 @@ public class UserController extends BaseController {
|
||||
/**
|
||||
* 分页查询我的反馈列表
|
||||
* */
|
||||
@PostMapping("listUserFeedBackByPage")
|
||||
@GetMapping("listUserFeedBackByPage")
|
||||
public ResultBean listUserFeedBackByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize, HttpServletRequest request){
|
||||
UserDetails userDetails = getUserDetails(request);
|
||||
if (userDetails == null) {
|
||||
return ResultBean.fail(ResponseStatus.NO_LOGIN);
|
||||
}
|
||||
return ResultBean.ok(new PageInfo<>(userService.listUserFeedBackByPage(userDetails.getId(),page,pageSize)));
|
||||
return ResultBean.ok(userService.listUserFeedBackByPage(userDetails.getId(),page,pageSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询个人信息
|
||||
* */
|
||||
@PostMapping("userInfo")
|
||||
@GetMapping("userInfo")
|
||||
public ResultBean userInfo(HttpServletRequest request) {
|
||||
UserDetails userDetails = getUserDetails(request);
|
||||
if (userDetails == null) {
|
||||
@ -228,7 +214,7 @@ public class UserController extends BaseController {
|
||||
* 更新个人信息
|
||||
* */
|
||||
@PostMapping("updateUserInfo")
|
||||
public ResultBean updateUserInfo(User user,HttpServletRequest request) {
|
||||
public ResultBean updateUserInfo(@Validated({UpdateGroup.class}) User user, HttpServletRequest request) {
|
||||
UserDetails userDetails = getUserDetails(request);
|
||||
if (userDetails == null) {
|
||||
return ResultBean.fail(ResponseStatus.NO_LOGIN);
|
||||
@ -263,13 +249,13 @@ public class UserController extends BaseController {
|
||||
/**
|
||||
* 分页查询用户书评
|
||||
* */
|
||||
@PostMapping("listCommentByPage")
|
||||
@GetMapping("listCommentByPage")
|
||||
public ResultBean listCommentByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "5") int pageSize,HttpServletRequest request) {
|
||||
UserDetails userDetails = getUserDetails(request);
|
||||
if (userDetails == null) {
|
||||
return ResultBean.fail(ResponseStatus.NO_LOGIN);
|
||||
}
|
||||
return ResultBean.ok(new PageInfo<>(bookService.listCommentByPage(userDetails.getId(),null,page,pageSize)));
|
||||
return ResultBean.ok(bookService.listCommentByPage(userDetails.getId(),null,page,pageSize));
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,7 +10,7 @@ import org.springframework.stereotype.Component;
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix="alipay")
|
||||
public class AlipayConfig {
|
||||
public class AlipayProperties {
|
||||
|
||||
private String appId;
|
||||
private String merchantPrivateKey;
|
@ -7,13 +7,13 @@ import org.springframework.stereotype.Component;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 作家收入配置
|
||||
* 作家收入配置属性
|
||||
* @author cd
|
||||
*/
|
||||
@Component
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "author.income")
|
||||
public class AuthorIncomeConfig {
|
||||
public class AuthorIncomeProperties {
|
||||
|
||||
private BigDecimal taxRate;
|
||||
|
@ -7,13 +7,13 @@ import org.springframework.stereotype.Component;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 章节费用配置
|
||||
* 章节费用配置属性
|
||||
* @author cd
|
||||
*/
|
||||
@Component
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "book.price")
|
||||
public class BookPriceConfig {
|
||||
public class BookPriceProperties {
|
||||
|
||||
private BigDecimal wordCount;
|
||||
|
@ -0,0 +1,25 @@
|
||||
package com.java2nb.novel.core.config;
|
||||
|
||||
import org.springframework.boot.web.server.ErrorPage;
|
||||
import org.springframework.boot.web.server.ErrorPageRegistrar;
|
||||
import org.springframework.boot.web.server.ErrorPageRegistry;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/**
|
||||
* 错误页面配置
|
||||
* @author xiongxiaoyang
|
||||
*/
|
||||
@Configuration
|
||||
public class ErrorPageConfig implements ErrorPageRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerErrorPages(ErrorPageRegistry registry) {
|
||||
/*1.错误类型为404,默认显示404.html网页*/
|
||||
ErrorPage e404 = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
|
||||
/**
|
||||
TODO 2.错误类型为500,表示服务器响应错误,默认显示/500.html网页
|
||||
*/
|
||||
registry.addErrorPages(e404);
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.java2nb.novel.core.config;
|
||||
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* elasticsearch搜索引擎配置
|
||||
* @author xiongxiaoyang
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enable", havingValue = "1")
|
||||
public class EsConfig {
|
||||
|
||||
@Value("${spring.elasticsearch.jest.uris}")
|
||||
private String esUris;
|
||||
|
||||
@Bean
|
||||
public RestHighLevelClient esClient(){
|
||||
|
||||
|
||||
String[] uris = esUris.split(",");
|
||||
HttpHost[] hosts = new HttpHost[uris.length];
|
||||
for(int i = 0 ; i < uris.length ; i++){
|
||||
String uri = uris[i];
|
||||
String scheme = uri.substring(0,uri.indexOf(":")).trim();
|
||||
String hostname = uri.substring(uri.indexOf("://")+3,uri.lastIndexOf(":")).trim();
|
||||
Integer port = Integer.parseInt(uri.substring(uri.lastIndexOf(":")+1).trim());
|
||||
hosts[i] = new HttpHost(hostname,port,scheme);
|
||||
}
|
||||
|
||||
return new RestHighLevelClient(
|
||||
RestClient.builder(hosts));
|
||||
|
||||
}
|
||||
}
|
@ -9,5 +9,5 @@ import org.springframework.jmx.support.RegistrationPolicy;
|
||||
*/
|
||||
@Configuration
|
||||
@EnableMBeanExport(registration= RegistrationPolicy.IGNORE_EXISTING)
|
||||
public class FdfsConfiguration {
|
||||
public class FdfsConfig {
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.java2nb.novel.core.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 线程池配置
|
||||
* @author xiongxiaoyang
|
||||
*/
|
||||
@Configuration
|
||||
public class ThreadPoolConfig {
|
||||
|
||||
@Bean
|
||||
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolProperties properties){
|
||||
return new ThreadPoolExecutor(properties.getCorePoolSize(),properties.getMaximumPoolSize(),properties.getKeepAliveTime()
|
||||
, TimeUnit.SECONDS, new LinkedBlockingDeque<>(properties.getQueueSize()),new ThreadPoolExecutor.AbortPolicy());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.java2nb.novel.core.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 线程池配置属性
|
||||
* @author xiongxiaoyang
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "thread.pool")
|
||||
public class ThreadPoolProperties {
|
||||
|
||||
private Integer corePoolSize;
|
||||
private Integer maximumPoolSize;
|
||||
private Long keepAliveTime;
|
||||
private Integer queueSize;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.java2nb.novel.core.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix="website")
|
||||
public class WebsiteProperties {
|
||||
|
||||
private String name;
|
||||
private String domain;
|
||||
private String keyword;
|
||||
private String description;
|
||||
private String qq;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.java2nb.novel.core.listener;
|
||||
|
||||
import com.java2nb.novel.core.config.WebsiteProperties;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.servlet.annotation.WebListener;
|
||||
|
||||
/**
|
||||
* 启动监听器
|
||||
* @author xiongxiaoyang
|
||||
*/
|
||||
@WebListener
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class StarterListener implements ServletContextListener {
|
||||
|
||||
private final WebsiteProperties websiteConfig;
|
||||
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
sce.getServletContext().setAttribute("website",websiteConfig);
|
||||
|
||||
}
|
||||
}
|
@ -2,19 +2,11 @@ package com.java2nb.novel.core.schedule;
|
||||
|
||||
import com.java2nb.novel.core.cache.CacheKey;
|
||||
import com.java2nb.novel.core.cache.CacheService;
|
||||
import com.java2nb.novel.core.utils.BeanUtil;
|
||||
import com.java2nb.novel.entity.Book;
|
||||
import com.java2nb.novel.service.BookService;
|
||||
import com.java2nb.novel.service.SearchService;
|
||||
import com.java2nb.novel.vo.EsBookVO;
|
||||
import io.searchbox.client.JestClient;
|
||||
import io.searchbox.core.DocumentResult;
|
||||
import io.searchbox.core.Index;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -68,8 +60,6 @@ public class BookToEsSchedule {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
cacheService.setObject(CacheKey.ES_LAST_UPDATE_TIME, lastDate);
|
||||
|
||||
} catch (Exception e) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.java2nb.novel.core.schedule;
|
||||
|
||||
|
||||
import com.java2nb.novel.core.config.AuthorIncomeConfig;
|
||||
import com.java2nb.novel.core.utils.DateUtil;
|
||||
import com.java2nb.novel.entity.Author;
|
||||
import com.java2nb.novel.entity.AuthorIncomeDetail;
|
||||
|
@ -1,19 +1,17 @@
|
||||
package com.java2nb.novel.core.schedule;
|
||||
|
||||
|
||||
import com.java2nb.novel.core.config.AuthorIncomeConfig;
|
||||
import com.java2nb.novel.core.config.AuthorIncomeProperties;
|
||||
import com.java2nb.novel.core.utils.DateUtil;
|
||||
import com.java2nb.novel.entity.*;
|
||||
import com.java2nb.novel.service.AuthorService;
|
||||
import com.java2nb.novel.service.BookService;
|
||||
import com.java2nb.novel.service.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@ -31,7 +29,7 @@ public class MonthIncomeStaSchedule {
|
||||
|
||||
private final BookService bookService;
|
||||
|
||||
private final AuthorIncomeConfig authorIncomeConfig;
|
||||
private final AuthorIncomeProperties authorIncomeConfig;
|
||||
|
||||
/**
|
||||
* 每个月1号凌晨2点统计上个月数据
|
||||
|
@ -86,7 +86,11 @@ public class JwtTokenUtil {
|
||||
*/
|
||||
private boolean isTokenExpired(String token) {
|
||||
Date expiredDate = getExpiredDateFromToken(token);
|
||||
return expiredDate.before(new Date());
|
||||
if(expiredDate == null){
|
||||
return true;
|
||||
}else {
|
||||
return expiredDate.before(new Date());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,7 +98,7 @@ public class JwtTokenUtil {
|
||||
*/
|
||||
private Date getExpiredDateFromToken(String token) {
|
||||
Claims claims = getClaimsFromToken(token);
|
||||
return claims.getExpiration();
|
||||
return claims != null ? claims.getExpiration() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,20 +0,0 @@
|
||||
package com.java2nb.novel.form;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
@Data
|
||||
public class UserForm {
|
||||
@NotBlank(message="手机号不能为空!")
|
||||
@Pattern(regexp="^1[3|4|5|6|7|8|9][0-9]{9}$",message="手机号格式不正确!")
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private String username;
|
||||
|
||||
@NotBlank(message="密码不能为空!")
|
||||
@Generated("org.mybatis.generator.api.MyBatisGenerator")
|
||||
private String password;
|
||||
|
||||
}
|
@ -1,11 +1,10 @@
|
||||
package com.java2nb.novel.mapper;
|
||||
|
||||
import com.java2nb.novel.entity.Book;
|
||||
import com.java2nb.novel.search.BookSP;
|
||||
import com.java2nb.novel.vo.BookSpVO;
|
||||
import com.java2nb.novel.vo.BookVO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -14,7 +13,7 @@ import java.util.List;
|
||||
public interface FrontBookMapper extends BookMapper {
|
||||
|
||||
|
||||
List<BookVO> searchByPage(BookSP params);
|
||||
List<BookVO> searchByPage(BookSpVO params);
|
||||
|
||||
void addVisitCount(@Param("bookId") Long bookId, @Param("visitCount") Integer visitCount);
|
||||
|
||||
|
@ -0,0 +1,263 @@
|
||||
package com.java2nb.novel.page;
|
||||
|
||||
import com.java2nb.novel.controller.BaseController;
|
||||
import com.java2nb.novel.core.bean.UserDetails;
|
||||
import com.java2nb.novel.core.utils.ThreadLocalUtil;
|
||||
import com.java2nb.novel.entity.*;
|
||||
import com.java2nb.novel.service.AuthorService;
|
||||
import com.java2nb.novel.service.BookService;
|
||||
import com.java2nb.novel.service.NewsService;
|
||||
import com.java2nb.novel.service.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Controller
|
||||
public class PageController extends BaseController {
|
||||
|
||||
private final BookService bookService;
|
||||
|
||||
private final NewsService newsService;
|
||||
|
||||
private final AuthorService authorService;
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
private final ThreadPoolExecutor threadPoolExecutor;
|
||||
|
||||
|
||||
@RequestMapping("{url}.html")
|
||||
public String module(@PathVariable("url") String url) {
|
||||
return url;
|
||||
}
|
||||
|
||||
@RequestMapping("{module}/{url}.html")
|
||||
public String module2(@PathVariable("module") String module, @PathVariable("url") String url, HttpServletRequest request) {
|
||||
|
||||
if (request.getRequestURI().startsWith("/author")) {
|
||||
//访问作者专区
|
||||
UserDetails user = getUserDetails(request);
|
||||
if (user == null) {
|
||||
//未登录
|
||||
return "redirect:/user/login.html?originUrl=" + request.getRequestURI();
|
||||
}
|
||||
|
||||
boolean isAuthor = authorService.isAuthor(user.getId());
|
||||
if (!isAuthor) {
|
||||
return "redirect:/author/register.html";
|
||||
}
|
||||
}
|
||||
|
||||
return module + "/" + url;
|
||||
}
|
||||
|
||||
@RequestMapping("{module}/{classify}/{url}.html")
|
||||
public String module3(@PathVariable("module") String module, @PathVariable("classify") String classify, @PathVariable("url") String url) {
|
||||
return module + "/" + classify + "/" + url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页
|
||||
*/
|
||||
@RequestMapping(path = {"/", "/index", "/index.html"})
|
||||
public String index() {
|
||||
return ThreadLocalUtil.getTemplateDir() + "index";
|
||||
}
|
||||
|
||||
/**
|
||||
* 作品页
|
||||
*/
|
||||
@RequestMapping("book/bookclass.html")
|
||||
public String bookClass() {
|
||||
return "book/bookclass";
|
||||
}
|
||||
|
||||
/**
|
||||
* 排行页
|
||||
*/
|
||||
@RequestMapping("book/book_ranking.html")
|
||||
public String bookRank() {
|
||||
|
||||
return ThreadLocalUtil.getTemplateDir() + "book/book_ranking";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 详情页
|
||||
*/
|
||||
@SneakyThrows
|
||||
@RequestMapping("/book/{bookId}.html")
|
||||
public String bookDetail(@PathVariable("bookId") Long bookId, Model model) {
|
||||
Book book = bookService.queryBookDetail(bookId);
|
||||
model.addAttribute("book", book);
|
||||
if (book.getLastIndexId() != null) {
|
||||
//查询首章目录ID
|
||||
Long firstBookIndexId = bookService.queryFirstBookIndexId(bookId);
|
||||
model.addAttribute("firstBookIndexId", firstBookIndexId);
|
||||
}
|
||||
return ThreadLocalUtil.getTemplateDir() + "book/book_detail";
|
||||
}
|
||||
|
||||
/**
|
||||
* 目录页
|
||||
*/
|
||||
@SneakyThrows
|
||||
@RequestMapping("/book/indexList-{bookId}.html")
|
||||
public String indexList(@PathVariable("bookId") Long bookId, Model model) {
|
||||
Book book = bookService.queryBookDetail(bookId);
|
||||
model.addAttribute("book", book);
|
||||
List<BookIndex> bookIndexList = bookService.queryIndexList(bookId, null, 1, null);
|
||||
model.addAttribute("bookIndexList", bookIndexList);
|
||||
model.addAttribute("bookIndexCount", bookIndexList.size());
|
||||
return ThreadLocalUtil.getTemplateDir() + "book/book_index";
|
||||
}
|
||||
|
||||
/**
|
||||
* 内容页
|
||||
*/
|
||||
@SneakyThrows
|
||||
@RequestMapping("/book/{bookId}/{bookIndexId}.html")
|
||||
public String indexList(@PathVariable("bookId") Long bookId, @PathVariable("bookIndexId") Long bookIndexId, HttpServletRequest request, Model model) {
|
||||
|
||||
|
||||
//加载小说基本信息线程
|
||||
CompletableFuture<Book> bookCompletableFuture = CompletableFuture.supplyAsync(() -> {
|
||||
//查询书籍
|
||||
Book book = bookService.queryBookDetail(bookId);
|
||||
log.debug("加载小说基本信息线程结束");
|
||||
return book;
|
||||
}, threadPoolExecutor);
|
||||
|
||||
//加载小说章节信息线程
|
||||
CompletableFuture<BookIndex> bookIndexCompletableFuture = CompletableFuture.supplyAsync(() -> {
|
||||
//查询目录
|
||||
BookIndex bookIndex = bookService.queryBookIndex(bookIndexId);
|
||||
log.debug("加载小说章节信息线程结束");
|
||||
return bookIndex;
|
||||
}, threadPoolExecutor);
|
||||
|
||||
//加载小说上一章节信息线程,该线程在加载小说章节信息线程执行完毕后才执行
|
||||
CompletableFuture<Long> preBookIndexIdCompletableFuture = bookIndexCompletableFuture.thenApplyAsync((bookIndex) -> {
|
||||
//查询上一章节目录ID
|
||||
Long preBookIndexId = bookService.queryPreBookIndexId(bookId, bookIndex.getIndexNum());
|
||||
log.debug("加载小说上一章节信息线程结束");
|
||||
return preBookIndexId;
|
||||
}, threadPoolExecutor);
|
||||
|
||||
//加载小说下一章节信息线程,该线程在加载小说章节信息线程执行完毕后才执行
|
||||
CompletableFuture<Long> nextBookIndexIdCompletableFuture = bookIndexCompletableFuture.thenApplyAsync((bookIndex) -> {
|
||||
//查询下一章目录ID
|
||||
Long nextBookIndexId = bookService.queryNextBookIndexId(bookId, bookIndex.getIndexNum());
|
||||
log.debug("加载小说下一章节信息线程结束");
|
||||
return nextBookIndexId;
|
||||
}, threadPoolExecutor);
|
||||
|
||||
//加载小说内容信息线程
|
||||
CompletableFuture<BookContent> bookContentCompletableFuture = CompletableFuture.supplyAsync(() -> {
|
||||
//查询内容
|
||||
BookContent bookContent = bookService.queryBookContent(bookIndexId);
|
||||
log.debug("加载小说内容信息线程结束");
|
||||
return bookContent;
|
||||
}, threadPoolExecutor);
|
||||
|
||||
|
||||
//判断用户是否需要购买线程,该线程在加载小说章节信息线程执行完毕后才执行
|
||||
CompletableFuture<Boolean> needBuyCompletableFuture = bookIndexCompletableFuture.thenApplyAsync((bookIndex) -> {
|
||||
//判断该目录是否收费
|
||||
if (bookIndex.getIsVip() != null && bookIndex.getIsVip() == 1) {
|
||||
//收费
|
||||
UserDetails user = getUserDetails(request);
|
||||
if (user == null) {
|
||||
//未登录,需要购买
|
||||
return true;
|
||||
}
|
||||
//判断用户是否购买过该目录
|
||||
boolean isBuy = userService.queryIsBuyBookIndex(user.getId(), bookIndexId);
|
||||
if (!isBuy) {
|
||||
//没有购买过,需要购买
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("判断用户是否需要购买线程结束");
|
||||
return false;
|
||||
|
||||
}, threadPoolExecutor);
|
||||
|
||||
|
||||
model.addAttribute("book", bookCompletableFuture.get());
|
||||
model.addAttribute("bookIndex", bookIndexCompletableFuture.get());
|
||||
model.addAttribute("preBookIndexId", preBookIndexIdCompletableFuture.get());
|
||||
model.addAttribute("nextBookIndexId", nextBookIndexIdCompletableFuture.get());
|
||||
model.addAttribute("bookContent", bookContentCompletableFuture.get());
|
||||
model.addAttribute("needBuy", needBuyCompletableFuture.get());
|
||||
|
||||
return ThreadLocalUtil.getTemplateDir() + "book/book_content";
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论页面
|
||||
*/
|
||||
@RequestMapping("/book/comment-{bookId}.html")
|
||||
public String commentList(@PathVariable("bookId") Long bookId, Model model) {
|
||||
//查询书籍
|
||||
Book book = bookService.queryBookDetail(bookId);
|
||||
model.addAttribute("book", book);
|
||||
return "book/book_comment";
|
||||
}
|
||||
|
||||
/**
|
||||
* 新闻内容页面
|
||||
*/
|
||||
@RequestMapping("/about/newsInfo-{newsId}.html")
|
||||
public String newsInfo(@PathVariable("newsId") Long newsId, Model model) {
|
||||
//查询新闻
|
||||
News news = newsService.queryNewsInfo(newsId);
|
||||
model.addAttribute("news", news);
|
||||
return "about/news_info";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 作者注册页面
|
||||
*/
|
||||
@RequestMapping("author/register.html")
|
||||
public String authorRegister(Author author, HttpServletRequest request, Model model) {
|
||||
UserDetails user = getUserDetails(request);
|
||||
if (user == null) {
|
||||
//未登录
|
||||
return "redirect:/user/login.html?originUrl=/author/register.html";
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(author.getInviteCode())) {
|
||||
//提交作者注册信息
|
||||
String errorInfo = authorService.register(user.getId(), author);
|
||||
if (StringUtils.isBlank(errorInfo)) {
|
||||
//注册成功
|
||||
return "redirect:/author/index.html";
|
||||
}
|
||||
model.addAttribute("LabErr", errorInfo);
|
||||
model.addAttribute("author", author);
|
||||
}
|
||||
return "author/register";
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.java2nb.novel.service;
|
||||
|
||||
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.entity.Author;
|
||||
import com.java2nb.novel.entity.AuthorIncome;
|
||||
import com.java2nb.novel.entity.AuthorIncomeDetail;
|
||||
@ -111,9 +112,9 @@ public interface AuthorService {
|
||||
* @param bookId 小说ID
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return 日收入统计数据列表
|
||||
* @return 日收入统计数据分页数据
|
||||
*/
|
||||
List<AuthorIncomeDetail> listIncomeDailyByPage(int page, int pageSize, Long userId, Long bookId, Date startTime, Date endTime);
|
||||
PageBean<AuthorIncomeDetail> listIncomeDailyByPage(int page, int pageSize, Long userId, Long bookId, Date startTime, Date endTime);
|
||||
|
||||
|
||||
/**
|
||||
@ -122,7 +123,7 @@ public interface AuthorService {
|
||||
* @param pageSize 分页大小
|
||||
* @param userId 用户ID
|
||||
* @param bookId 小说ID
|
||||
* @return
|
||||
* @return 分页数据
|
||||
* */
|
||||
List<AuthorIncome> listIncomeMonthByPage(int page, int pageSize, Long userId, Long bookId);
|
||||
PageBean<AuthorIncome> listIncomeMonthByPage(int page, int pageSize, Long userId, Long bookId);
|
||||
}
|
||||
|
@ -2,7 +2,8 @@ package com.java2nb.novel.service;
|
||||
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.java2nb.novel.search.BookSP;
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.vo.BookSpVO;
|
||||
import com.java2nb.novel.vo.BookCommentVO;
|
||||
import com.java2nb.novel.vo.BookSettingVO;
|
||||
import com.java2nb.novel.entity.*;
|
||||
@ -48,7 +49,7 @@ public interface BookService {
|
||||
* @param pageSize 分页大小
|
||||
* @return 小说集合分页信息
|
||||
* */
|
||||
PageInfo searchByPage(BookSP params, int page, int pageSize);
|
||||
PageBean searchByPage(BookSpVO params, int page, int pageSize);
|
||||
|
||||
/**
|
||||
* 查询小说分类列表
|
||||
@ -144,9 +145,9 @@ public interface BookService {
|
||||
* @param bookId 书籍ID
|
||||
* @param page 页码
|
||||
* @param pageSize 分页大小
|
||||
* @return 评论集合
|
||||
* @return 评论分页数据
|
||||
* */
|
||||
List<BookCommentVO> listCommentByPage(Long userId, Long bookId, int page, int pageSize);
|
||||
PageBean<BookCommentVO> listCommentByPage(Long userId, Long bookId, int page, int pageSize);
|
||||
|
||||
/**
|
||||
* 新增评价
|
||||
@ -202,9 +203,9 @@ public interface BookService {
|
||||
* @param userId 用户ID
|
||||
* @param page 页码
|
||||
* @param pageSize 分页大小
|
||||
* @return 小说集合
|
||||
* @return 小说分页数据
|
||||
* */
|
||||
List<Book> listBookPageByUserId(Long userId, int page, int pageSize);
|
||||
PageBean<Book> listBookPageByUserId(Long userId, int page, int pageSize);
|
||||
|
||||
/**
|
||||
* 发布小说
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.java2nb.novel.service;
|
||||
|
||||
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.entity.News;
|
||||
import com.java2nb.novel.vo.NewsVO;
|
||||
|
||||
@ -28,7 +29,7 @@ public interface NewsService {
|
||||
* 分页查询新闻列表
|
||||
* @param page 页码
|
||||
* @param pageSize 分页大小
|
||||
* @return 新闻集合
|
||||
* @return 新闻分页数据
|
||||
* */
|
||||
List<NewsVO> listByPage(int page, int pageSize);
|
||||
PageBean<News> listByPage(int page, int pageSize);
|
||||
}
|
||||
|
@ -2,8 +2,11 @@ package com.java2nb.novel.service;
|
||||
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.entity.Book;
|
||||
import com.java2nb.novel.search.BookSP;
|
||||
import com.java2nb.novel.vo.BookSpVO;
|
||||
import com.java2nb.novel.vo.BookVO;
|
||||
import com.java2nb.novel.vo.EsBookVO;
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
@ -23,5 +26,5 @@ public interface SearchService {
|
||||
* @param pageSize 每页大小
|
||||
* @return 分页信息
|
||||
*/
|
||||
PageInfo searchBook(BookSP params, int page, int pageSize);
|
||||
PageBean<EsBookVO> searchBook(BookSpVO params, int page, int pageSize);
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
package com.java2nb.novel.service;
|
||||
|
||||
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.core.bean.UserDetails;
|
||||
import com.java2nb.novel.entity.UserBuyRecord;
|
||||
import com.java2nb.novel.form.UserForm;
|
||||
import com.java2nb.novel.entity.UserFeedback;
|
||||
import com.java2nb.novel.vo.BookReadHistoryVO;
|
||||
import com.java2nb.novel.vo.BookShelfVO;
|
||||
import com.java2nb.novel.entity.User;
|
||||
@ -19,17 +20,17 @@ public interface UserService {
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
* @param form 用户注册提交信息类
|
||||
* @param user 用户注册信息类
|
||||
* @return jwt载体信息类
|
||||
* */
|
||||
UserDetails register(UserForm form);
|
||||
UserDetails register(User user);
|
||||
|
||||
/**
|
||||
* 用户登陆
|
||||
* @param form 用户登陆提交信息类
|
||||
* @param user 用户登陆信息类
|
||||
* @return jwt载体信息类
|
||||
* */
|
||||
UserDetails login(UserForm form);
|
||||
UserDetails login(User user);
|
||||
|
||||
/**
|
||||
* 查询小说是否已加入书架
|
||||
@ -59,9 +60,9 @@ public interface UserService {
|
||||
* @param userId 用户ID
|
||||
* @param page
|
||||
* @param pageSize
|
||||
* @return 书架集合
|
||||
* @return 书架分页信息
|
||||
* */
|
||||
List<BookShelfVO> listBookShelfByPage(Long userId, int page, int pageSize);
|
||||
PageBean<BookShelfVO> listBookShelfByPage(Long userId, int page, int pageSize);
|
||||
|
||||
/**
|
||||
* 添加阅读记录
|
||||
@ -83,9 +84,9 @@ public interface UserService {
|
||||
* @param userId 用户ID
|
||||
* @param page 页码
|
||||
* @param pageSize 分页大小
|
||||
* @return 反馈集合
|
||||
* @return 反馈分页数据
|
||||
* */
|
||||
List<UserFeedbackVO> listUserFeedBackByPage(Long userId, int page, int pageSize);
|
||||
PageBean<UserFeedback> listUserFeedBackByPage(Long userId, int page, int pageSize);
|
||||
|
||||
/**
|
||||
* 查询个人信息
|
||||
@ -99,9 +100,9 @@ public interface UserService {
|
||||
* @param userId 用户id
|
||||
* @param page 页码
|
||||
* @param pageSize 分页大小
|
||||
* @return
|
||||
* @return 分页数据
|
||||
* */
|
||||
List<BookReadHistoryVO> listReadHistoryByPage(Long userId, int page, int pageSize);
|
||||
PageBean<BookReadHistoryVO> listReadHistoryByPage(Long userId, int page, int pageSize);
|
||||
|
||||
/**
|
||||
* 更新个人信息
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.java2nb.novel.service.impl;
|
||||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.core.cache.CacheKey;
|
||||
import com.java2nb.novel.core.cache.CacheService;
|
||||
import com.java2nb.novel.core.enums.ResponseStatus;
|
||||
@ -170,9 +171,9 @@ public class AuthorServiceImpl implements AuthorService {
|
||||
|
||||
|
||||
@Override
|
||||
public List<AuthorIncomeDetail> listIncomeDailyByPage(int page, int pageSize, Long userId, Long bookId, Date startTime, Date endTime) {
|
||||
public PageBean<AuthorIncomeDetail> listIncomeDailyByPage(int page, int pageSize, Long userId, Long bookId, Date startTime, Date endTime) {
|
||||
PageHelper.startPage(page, pageSize);
|
||||
return authorIncomeDetailMapper.selectMany(
|
||||
return new PageBean<>(authorIncomeDetailMapper.selectMany(
|
||||
select(AuthorIncomeDetailDynamicSqlSupport.incomeDate, AuthorIncomeDetailDynamicSqlSupport.incomeAccount
|
||||
, AuthorIncomeDetailDynamicSqlSupport.incomeCount, AuthorIncomeDetailDynamicSqlSupport.incomeNumber)
|
||||
.from(AuthorIncomeDetailDynamicSqlSupport.authorIncomeDetail)
|
||||
@ -182,14 +183,14 @@ public class AuthorServiceImpl implements AuthorService {
|
||||
.and(AuthorIncomeDetailDynamicSqlSupport.incomeDate, isLessThanOrEqualTo(endTime))
|
||||
.orderBy(AuthorIncomeDetailDynamicSqlSupport.incomeDate.descending())
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3));
|
||||
.render(RenderingStrategies.MYBATIS3)));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<AuthorIncome> listIncomeMonthByPage(int page, int pageSize, Long userId, Long bookId) {
|
||||
public PageBean<AuthorIncome> listIncomeMonthByPage(int page, int pageSize, Long userId, Long bookId) {
|
||||
PageHelper.startPage(page, pageSize);
|
||||
return authorIncomeMapper.selectMany(select(AuthorIncomeDynamicSqlSupport.incomeMonth
|
||||
return new PageBean<>(authorIncomeMapper.selectMany(select(AuthorIncomeDynamicSqlSupport.incomeMonth
|
||||
, AuthorIncomeDynamicSqlSupport.preTaxIncome
|
||||
, AuthorIncomeDynamicSqlSupport.afterTaxIncome
|
||||
, AuthorIncomeDynamicSqlSupport.payStatus
|
||||
@ -199,6 +200,6 @@ public class AuthorServiceImpl implements AuthorService {
|
||||
.and(AuthorIncomeDynamicSqlSupport.bookId, isEqualTo(bookId))
|
||||
.orderBy(AuthorIncomeDynamicSqlSupport.incomeMonth.descending())
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3));
|
||||
.render(RenderingStrategies.MYBATIS3)));
|
||||
}
|
||||
}
|
||||
|
@ -3,16 +3,17 @@ package com.java2nb.novel.service.impl;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.core.cache.CacheKey;
|
||||
import com.java2nb.novel.core.cache.CacheService;
|
||||
import com.java2nb.novel.core.config.BookPriceConfig;
|
||||
import com.java2nb.novel.core.config.BookPriceProperties;
|
||||
import com.java2nb.novel.core.enums.ResponseStatus;
|
||||
import com.java2nb.novel.core.exception.BusinessException;
|
||||
import com.java2nb.novel.core.utils.*;
|
||||
import com.java2nb.novel.entity.*;
|
||||
import com.java2nb.novel.entity.Book;
|
||||
import com.java2nb.novel.mapper.*;
|
||||
import com.java2nb.novel.search.BookSP;
|
||||
import com.java2nb.novel.vo.BookSpVO;
|
||||
import com.java2nb.novel.service.AuthorService;
|
||||
import com.java2nb.novel.service.BookService;
|
||||
import com.java2nb.novel.service.FileService;
|
||||
@ -89,7 +90,7 @@ public class BookServiceImpl implements BookService {
|
||||
|
||||
private final FileService fileService;
|
||||
|
||||
private final BookPriceConfig bookPriceConfig;
|
||||
private final BookPriceProperties bookPriceConfig;
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
@ -186,7 +187,7 @@ public class BookServiceImpl implements BookService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo searchByPage(BookSP params, int page, int pageSize) {
|
||||
public PageBean searchByPage(BookSpVO params, int page, int pageSize) {
|
||||
|
||||
|
||||
if (params.getUpdatePeriod() != null) {
|
||||
@ -213,7 +214,7 @@ public class BookServiceImpl implements BookService {
|
||||
if (StringUtils.isNotBlank(params.getSort())) {
|
||||
OrderByHelper.orderBy(params.getSort() + " desc");
|
||||
}
|
||||
return new PageInfo<>(bookMapper.searchByPage(params));
|
||||
return new PageBean(bookMapper.searchByPage(params));
|
||||
|
||||
|
||||
}
|
||||
@ -382,10 +383,10 @@ public class BookServiceImpl implements BookService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BookCommentVO> listCommentByPage(Long userId, Long bookId, int page, int pageSize) {
|
||||
public PageBean<BookCommentVO> listCommentByPage(Long userId, Long bookId, int page, int pageSize) {
|
||||
PageHelper.startPage(page, pageSize);
|
||||
OrderByHelper.orderBy("t1.create_time desc");
|
||||
return bookCommentMapper.listCommentByPage(userId, bookId);
|
||||
return new PageBean<>(bookCommentMapper.listCommentByPage(userId, bookId));
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ -491,7 +492,7 @@ public class BookServiceImpl implements BookService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Book> listBookPageByUserId(Long userId, int page, int pageSize) {
|
||||
public PageBean<Book> listBookPageByUserId(Long userId, int page, int pageSize) {
|
||||
|
||||
PageHelper.startPage(page, pageSize);
|
||||
|
||||
@ -501,7 +502,7 @@ public class BookServiceImpl implements BookService {
|
||||
.orderBy(BookDynamicSqlSupport.createTime.descending())
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3);
|
||||
return bookMapper.selectMany(selectStatement);
|
||||
return new PageBean<>(bookMapper.selectMany(selectStatement));
|
||||
|
||||
}
|
||||
|
||||
@ -600,6 +601,7 @@ public class BookServiceImpl implements BookService {
|
||||
return bookMapper.selectMany(select(book.allColumns())
|
||||
.from(book)
|
||||
.where(updateTime, isGreaterThan(startDate))
|
||||
.and(lastIndexId,isNotNull())
|
||||
.orderBy(updateTime)
|
||||
.limit(limit)
|
||||
.build()
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.java2nb.novel.service.impl;
|
||||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.core.utils.BeanUtil;
|
||||
import com.java2nb.novel.service.NewsService;
|
||||
import com.java2nb.novel.core.cache.CacheKey;
|
||||
@ -35,7 +36,7 @@ public class NewsServiceImpl implements NewsService {
|
||||
public List<News> listIndexNews() {
|
||||
List<News> result = (List<News>) cacheService.getObject(CacheKey.INDEX_NEWS_KEY);
|
||||
if(result == null || result.size() == 0) {
|
||||
SelectStatementProvider selectStatement = select(id, catName, catId, title)
|
||||
SelectStatementProvider selectStatement = select(id, catName, catId, title,createTime)
|
||||
.from(news)
|
||||
.orderBy(createTime.descending())
|
||||
.limit(2)
|
||||
@ -59,14 +60,16 @@ public class NewsServiceImpl implements NewsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NewsVO> listByPage(int page, int pageSize) {
|
||||
public PageBean<News> listByPage(int page, int pageSize) {
|
||||
PageHelper.startPage(page,pageSize);
|
||||
SelectStatementProvider selectStatement = select(id, catName, catId, title,createTime)
|
||||
.from(news)
|
||||
.orderBy(createTime.descending())
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3);
|
||||
|
||||
return BeanUtil.copyList(newsMapper.selectMany(selectStatement),NewsVO.class);
|
||||
List<News> news = newsMapper.selectMany(selectStatement);
|
||||
PageBean<News> pageBean = new PageBean<>(news);
|
||||
pageBean.setList(BeanUtil.copyList(news,NewsVO.class));
|
||||
return pageBean;
|
||||
}
|
||||
}
|
||||
|
@ -3,19 +3,29 @@ package com.java2nb.novel.service.impl;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.core.enums.ResponseStatus;
|
||||
import com.java2nb.novel.core.exception.BusinessException;
|
||||
import com.java2nb.novel.core.utils.StringUtil;
|
||||
import com.java2nb.novel.entity.Book;
|
||||
import com.java2nb.novel.search.BookSP;
|
||||
import com.java2nb.novel.vo.BookSpVO;
|
||||
import com.java2nb.novel.service.SearchService;
|
||||
import com.java2nb.novel.vo.BookVO;
|
||||
import com.java2nb.novel.vo.EsBookVO;
|
||||
import io.searchbox.client.JestClient;
|
||||
import io.searchbox.core.*;
|
||||
import io.searchbox.core.Count;
|
||||
import io.searchbox.core.CountResult;
|
||||
import io.searchbox.core.Search;
|
||||
import io.searchbox.core.SearchResult;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
@ -37,12 +47,12 @@ import java.util.Map;
|
||||
@Slf4j
|
||||
public class SearchServiceImpl implements SearchService {
|
||||
|
||||
private final String INDEX = "novel";
|
||||
|
||||
private final String TYPE = "book";
|
||||
|
||||
private final JestClient jestClient;
|
||||
|
||||
private final RestHighLevelClient restHighLevelClient;
|
||||
|
||||
private final String INDEX = "novel";
|
||||
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@ -51,16 +61,19 @@ public class SearchServiceImpl implements SearchService {
|
||||
EsBookVO esBookVO = new EsBookVO();
|
||||
BeanUtils.copyProperties(book, esBookVO, "lastIndexUpdateTime");
|
||||
esBookVO.setLastIndexUpdateTime(new SimpleDateFormat("yyyy/MM/dd HH:mm").format(book.getLastIndexUpdateTime()));
|
||||
Index action = new Index.Builder(esBookVO).index(INDEX).type(TYPE).id(book.getId().toString()).build();
|
||||
|
||||
jestClient.execute(action);
|
||||
IndexRequest request = new IndexRequest(INDEX);
|
||||
request.id(book.getId()+"");
|
||||
request.source(new ObjectMapper().writeValueAsString(esBookVO), XContentType.JSON);
|
||||
IndexResponse index = restHighLevelClient.index(request, RequestOptions.DEFAULT);
|
||||
|
||||
log.debug(index.getResult().toString());
|
||||
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public PageInfo searchBook(BookSP params, int page, int pageSize) {
|
||||
public PageBean<EsBookVO> searchBook(BookSpVO params, int page, int pageSize) {
|
||||
List<EsBookVO> bookList = new ArrayList<>(0);
|
||||
|
||||
//使用搜索引擎搜索
|
||||
@ -102,7 +115,7 @@ public class SearchServiceImpl implements SearchService {
|
||||
searchSourceBuilder.query(boolQueryBuilder);
|
||||
|
||||
|
||||
Count count = new Count.Builder().addIndex(INDEX).addType(TYPE)
|
||||
Count count = new Count.Builder().addIndex(INDEX)
|
||||
.query(searchSourceBuilder.toString()).build();
|
||||
CountResult results = jestClient.execute(count);
|
||||
Double total = results.getCount();
|
||||
@ -130,7 +143,7 @@ public class SearchServiceImpl implements SearchService {
|
||||
searchSourceBuilder.size(pageSize);
|
||||
|
||||
// 构建Search对象
|
||||
Search search = new Search.Builder(searchSourceBuilder.toString()).addIndex(INDEX).addType(TYPE).build();
|
||||
Search search = new Search.Builder(searchSourceBuilder.toString()).addIndex(INDEX).build();
|
||||
log.debug(search.toString());
|
||||
SearchResult result;
|
||||
result = jestClient.execute(search);
|
||||
@ -188,11 +201,7 @@ public class SearchServiceImpl implements SearchService {
|
||||
}
|
||||
}
|
||||
|
||||
PageInfo<EsBookVO> pageInfo = new PageInfo<>(bookList);
|
||||
pageInfo.setTotal(total.longValue());
|
||||
pageInfo.setPageNum(page);
|
||||
pageInfo.setPageSize(pageSize);
|
||||
return pageInfo;
|
||||
return new PageBean<>(page,pageSize,total.longValue(),bookList);
|
||||
}
|
||||
throw new BusinessException(ResponseStatus.ES_SEARCH_FAIL);
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package com.java2nb.novel.service.impl;
|
||||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.java2nb.novel.core.bean.PageBean;
|
||||
import com.java2nb.novel.core.bean.UserDetails;
|
||||
import com.java2nb.novel.core.utils.BeanUtil;
|
||||
import com.java2nb.novel.entity.*;
|
||||
import com.java2nb.novel.entity.User;
|
||||
import com.java2nb.novel.form.UserForm;
|
||||
import com.java2nb.novel.service.UserService;
|
||||
import com.java2nb.novel.core.enums.ResponseStatus;
|
||||
import com.java2nb.novel.core.exception.BusinessException;
|
||||
@ -29,7 +29,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.book;
|
||||
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.id;
|
||||
import static com.java2nb.novel.mapper.UserBookshelfDynamicSqlSupport.userBookshelf;
|
||||
import static com.java2nb.novel.mapper.UserDynamicSqlSupport.*;
|
||||
@ -59,11 +58,11 @@ public class UserServiceImpl implements UserService {
|
||||
|
||||
|
||||
@Override
|
||||
public UserDetails register(UserForm form) {
|
||||
public UserDetails register(User user) {
|
||||
//查询用户名是否已注册
|
||||
SelectStatementProvider selectStatement = select(count(id))
|
||||
.from(user)
|
||||
.where(username, isEqualTo(form.getUsername()))
|
||||
.from(UserDynamicSqlSupport.user)
|
||||
.where(username, isEqualTo(user.getUsername()))
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3);
|
||||
long count = userMapper.count(selectStatement);
|
||||
@ -72,7 +71,7 @@ public class UserServiceImpl implements UserService {
|
||||
throw new BusinessException(ResponseStatus.USERNAME_EXIST);
|
||||
}
|
||||
User entity = new User();
|
||||
BeanUtils.copyProperties(form,entity);
|
||||
BeanUtils.copyProperties(user,entity);
|
||||
//数据库生成注册记录
|
||||
Long id = new IdWorker().nextId();
|
||||
entity.setId(id);
|
||||
@ -91,12 +90,12 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails login(UserForm form) {
|
||||
public UserDetails login(User user) {
|
||||
//根据用户名密码查询记录
|
||||
SelectStatementProvider selectStatement = select(id, username,nickName)
|
||||
.from(user)
|
||||
.where(username, isEqualTo(form.getUsername()))
|
||||
.and(password, isEqualTo(MD5Util.MD5Encode(form.getPassword(), Charsets.UTF_8.name())))
|
||||
.from(UserDynamicSqlSupport.user)
|
||||
.where(username, isEqualTo(user.getUsername()))
|
||||
.and(password, isEqualTo(MD5Util.MD5Encode(user.getPassword(), Charsets.UTF_8.name())))
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3);
|
||||
List<User> users = userMapper.selectMany(selectStatement);
|
||||
@ -105,10 +104,10 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
//生成UserDetail对象并返回
|
||||
UserDetails userDetails = new UserDetails();
|
||||
User user = users.get(0);
|
||||
user = users.get(0);
|
||||
userDetails.setId(user.getId());
|
||||
userDetails.setNickName(user.getNickName());
|
||||
userDetails.setUsername(form.getUsername());
|
||||
userDetails.setUsername(user.getUsername());
|
||||
return userDetails;
|
||||
}
|
||||
|
||||
@ -149,9 +148,9 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BookShelfVO> listBookShelfByPage(Long userId, int page, int pageSize) {
|
||||
public PageBean<BookShelfVO> listBookShelfByPage(Long userId, int page, int pageSize) {
|
||||
PageHelper.startPage(page, pageSize);
|
||||
return userBookshelfMapper.listBookShelf(userId);
|
||||
return new PageBean<>(userBookshelfMapper.listBookShelf(userId));
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ -203,7 +202,7 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserFeedbackVO> listUserFeedBackByPage(Long userId, int page, int pageSize) {
|
||||
public PageBean<UserFeedback> listUserFeedBackByPage(Long userId, int page, int pageSize) {
|
||||
PageHelper.startPage(page, pageSize);
|
||||
SelectStatementProvider selectStatement = select(UserFeedbackDynamicSqlSupport.content, UserFeedbackDynamicSqlSupport.createTime)
|
||||
.from(userFeedback)
|
||||
@ -211,7 +210,10 @@ public class UserServiceImpl implements UserService {
|
||||
.orderBy(UserFeedbackDynamicSqlSupport.id.descending())
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3);
|
||||
return BeanUtil.copyList(userFeedbackMapper.selectMany(selectStatement),UserFeedbackVO.class);
|
||||
List<UserFeedback> userFeedbacks = userFeedbackMapper.selectMany(selectStatement);
|
||||
PageBean<UserFeedback> pageBean = new PageBean<>(userFeedbacks);
|
||||
pageBean.setList(BeanUtil.copyList(userFeedbacks,UserFeedbackVO.class));
|
||||
return pageBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -225,19 +227,16 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BookReadHistoryVO> listReadHistoryByPage(Long userId, int page, int pageSize) {
|
||||
public PageBean<BookReadHistoryVO> listReadHistoryByPage(Long userId, int page, int pageSize) {
|
||||
PageHelper.startPage(page, pageSize);
|
||||
return userReadHistoryMapper.listReadHistory(userId);
|
||||
return new PageBean<>(userReadHistoryMapper.listReadHistory(userId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUserInfo(Long userId, User user) {
|
||||
User updateUser = new User();
|
||||
updateUser.setId(userId);
|
||||
updateUser.setNickName(user.getNickName());
|
||||
updateUser.setUserSex(user.getUserSex());
|
||||
updateUser.setUpdateTime(new Date());
|
||||
userMapper.updateByPrimaryKeySelective(updateUser);
|
||||
user.setId(userId);
|
||||
user.setUpdateTime(new Date());
|
||||
userMapper.updateByPrimaryKeySelective(user);
|
||||
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,12 @@ public class BookSettingVO extends BookSetting implements Serializable {
|
||||
|
||||
private Float score;
|
||||
|
||||
private Integer catId;
|
||||
|
||||
private String catName;
|
||||
|
||||
private Byte bookStatus;
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.java2nb.novel.search;
|
||||
package com.java2nb.novel.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@ -9,7 +9,7 @@ import java.util.Date;
|
||||
* @author 11797
|
||||
*/
|
||||
@Data
|
||||
public class BookSP {
|
||||
public class BookSpVO {
|
||||
|
||||
private String keyword;
|
||||
|
@ -1,13 +1,7 @@
|
||||
package com.java2nb.novel.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.java2nb.novel.entity.Book;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Administrator
|
||||
*/
|
||||
|
@ -1,3 +1,24 @@
|
||||
spring:
|
||||
profiles:
|
||||
include: [common-dev]
|
||||
profiles:
|
||||
include: [common-dev]
|
||||
|
||||
|
||||
pic:
|
||||
save:
|
||||
type: 1 #图片保存方式, 1不保存,使用爬取的网络图片 ,2保存在自己的存储介质
|
||||
storage: local #存储介质,local:本地,OSS:阿里云对象存储,fastDfs:分布式文件系统
|
||||
path: /Users/xiongxiaoyang/java #图片保存路径
|
||||
|
||||
|
||||
|
||||
#线程池配置
|
||||
thread:
|
||||
pool:
|
||||
#核心线程池数量
|
||||
core-pool-size: 10
|
||||
#最大线程池数量
|
||||
maximum-pool-size: 20
|
||||
#线程超时时间(秒)
|
||||
keep-alive-time: 10
|
||||
#队列大小
|
||||
queue-size: 100
|
37
novel-front/src/main/resources/application-prod.yml
Normal file
37
novel-front/src/main/resources/application-prod.yml
Normal file
@ -0,0 +1,37 @@
|
||||
spring:
|
||||
profiles:
|
||||
include: [common-prod]
|
||||
|
||||
#静态文件路径配置
|
||||
resources:
|
||||
static-locations: file:${user.dir}/templates/${templates.name}/static/
|
||||
#thymeleaf模版路径配置
|
||||
thymeleaf:
|
||||
prefix: file:${user.dir}/templates/${templates.name}/html/
|
||||
suffix: .html
|
||||
|
||||
#模版配置
|
||||
templates:
|
||||
name: orange
|
||||
|
||||
|
||||
pic:
|
||||
save:
|
||||
type: 2 #图片保存方式, 1不保存,使用爬取的网络图片 ,2保存在自己的存储介质
|
||||
storage: local #存储介质,local:本地,OSS:阿里云对象存储,fastDfs:分布式文件系统
|
||||
path: /var/pic #图片保存路径
|
||||
|
||||
|
||||
#线程池配置
|
||||
thread:
|
||||
pool:
|
||||
#核心线程池数量
|
||||
core-pool-size: 10
|
||||
#最大线程池数量
|
||||
maximum-pool-size: 20
|
||||
#线程超时时间(秒)
|
||||
keep-alive-time: 10
|
||||
#队列大小
|
||||
queue-size: 1000
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
spring:
|
||||
profiles:
|
||||
include: [common-test]
|
12
novel-front/src/main/resources/application-website.yml
Normal file
12
novel-front/src/main/resources/application-website.yml
Normal file
@ -0,0 +1,12 @@
|
||||
#网站配置
|
||||
website:
|
||||
#网站名
|
||||
name: 小说精品屋
|
||||
#域名
|
||||
domain: xiongxyang.gitee.io
|
||||
#SEO关键词
|
||||
keyword: ${website.name},小说,小说CMS,原创文学系统,开源小说系统,免费小说建站程序
|
||||
#SEO描述
|
||||
description: ${website.name}是一个多端(PC、WAP)阅读、功能完善的原创文学CMS系统,由前台门户系统、作家后台管理系统、平台后台管理系统、爬虫管理系统等多个子系统构成,支持会员充值、订阅模式、新闻发布和实时统计报表等功能,新书自动入库,老书自动更新。
|
||||
#联系QQ
|
||||
qq: 1179705413
|
@ -4,7 +4,7 @@ server:
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
include: alipay,oss,fastdfs
|
||||
include: website,alipay,oss,fastdfs
|
||||
|
||||
|
||||
rabbitmq:
|
||||
@ -23,7 +23,9 @@ spring:
|
||||
#是否开启搜索引擎,1:开启,0:不开启
|
||||
enable: 0
|
||||
jest:
|
||||
uris: http://127.0.0.1:9200
|
||||
uris: http://192.168.0.105:9200
|
||||
|
||||
|
||||
|
||||
redisson:
|
||||
singleServerConfig:
|
||||
@ -64,4 +66,12 @@ book:
|
||||
#字数
|
||||
word-count: 1000
|
||||
#价值(屋币)
|
||||
value: 5
|
||||
value: 5
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,5 +0,0 @@
|
||||
#网站配置
|
||||
#网站名
|
||||
website.name=小说精品屋
|
||||
#PC站网站域名
|
||||
website.domain=www.java2nb.com
|
@ -3,7 +3,7 @@
|
||||
|
||||
<mapper namespace="com.java2nb.novel.mapper.FrontBookMapper">
|
||||
|
||||
<select id="searchByPage" parameterType="com.java2nb.novel.search.BookSP" resultType="com.java2nb.novel.vo.BookVO">
|
||||
<select id="searchByPage" parameterType="com.java2nb.novel.vo.BookSpVO" resultType="com.java2nb.novel.vo.BookVO">
|
||||
select
|
||||
id,cat_id,cat_name,book_name,author_id,author_name,word_count,last_index_id,last_index_name,score,pic_url,book_status,last_index_update_time,book_desc
|
||||
from book where word_count > 0
|
||||
|
@ -4,7 +4,7 @@
|
||||
<mapper namespace="com.java2nb.novel.mapper.FrontBookSettingMapper">
|
||||
|
||||
<select id="listVO" resultType="com.java2nb.novel.vo.BookSettingVO">
|
||||
select t1.book_id,t1.type,t1.sort,t2.book_name,t2.author_name,t2.pic_url,t2.book_desc,t2.score
|
||||
select t1.book_id,t1.type,t1.sort,t2.book_name,t2.author_name,t2.pic_url,t2.book_desc,t2.score,t2.cat_id,t2.cat_name,t2.book_status
|
||||
from book_setting t1 inner join book t2
|
||||
on t1.book_id = t2.id
|
||||
order by t1.sort
|
||||
|
BIN
novel-front/src/main/resources/static/images/404.jpeg
Normal file
BIN
novel-front/src/main/resources/static/images/404.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 150 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user