Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
7e650a0a04 | |||
45c59ecc37 | |||
5e3962fef4 | |||
7f5035e369 | |||
44aad39847 | |||
6ad51908d5 | |||
f03ab953d0 | |||
5cc9dfa1bc | |||
2fbda60617 | |||
39c19ac004 | |||
7494fe431a | |||
c9f1500976 | |||
f61c252e71 | |||
6fd183c2ae | |||
c3daaecaaa | |||
1b6cc8ccd5 | |||
0a10504461 | |||
1046a7ffc1 | |||
612555dbe6 | |||
d5768e4011 | |||
5982eb623f | |||
85ad5fa3b2 |
69
README.md
@ -2,6 +2,10 @@
|
||||
|
||||
# 小说精品屋-plus
|
||||
|
||||
#### 官网
|
||||
|
||||
https://xiongxyang.gitee.io/home/
|
||||
|
||||
#### 新项目:小说精品屋-微服务版
|
||||
|
||||
基于小说精品屋-plus构建的Spring Cloud 微服务小说门户平台。
|
||||
@ -15,13 +19,9 @@ Gitee仓库地址: https://gitee.com/novel_dev_team/novel-cloud
|
||||
[点击前往](http://47.106.243.172:8888/)
|
||||
|
||||
|
||||
#### 前言
|
||||
|
||||
小说精品屋-plus致力于打造一个完整的商用小说门户平台,使用前建议先阅读此文档。
|
||||
|
||||
#### 项目介绍
|
||||
|
||||
小说精品屋-plus是在[小说精品屋](https://github.com/201206030/fiction_house)的基础上,去除了漫画和弹幕模块,专注于小说,是一个多端(PC、移动)阅读、功能完善的小说原创/爬虫网站项目,既包含了作家专区供原创作者上传小说,又提供了爬虫工具通过规则多线程全自动采集任意小说网站数据(已兼容99%的小说网站),新书自动入库,老书自动更新。
|
||||
小说精品屋-plus是在[小说精品屋](https://github.com/201206030/fiction_house)的基础上,去除了漫画和弹幕模块,专注于小说,是一个多端(PC、WAP)阅读、功能完善的原创文学CMS系统,由前台门户系统、作家后台管理系统、平台后台管理系统、爬虫管理系统等多个子系统构成,支持会员充值、订阅模式、新闻发布和实时统计报表等功能。
|
||||
|
||||
小说精品屋-plus重新进行了数据库设计、代码重构和功能增强,提升了程序整体的可读性和性能,增加了很多商用特性。主要升级如下:
|
||||
|
||||
@ -29,6 +29,7 @@ Gitee仓库地址: https://gitee.com/novel_dev_team/novel-cloud
|
||||
- [x] 服务端代码重构,MyBatis3升级为MyBatis3DynamicSql。
|
||||
- [x] 移动站与PC站站点分离,浏览器自动识别跳转。
|
||||
- [x] PC站UI更新。
|
||||
- [x] 支持前端模版自定义,内置多套模版。
|
||||
- [x] 新闻模块。
|
||||
- [x] 排行榜。
|
||||
- [x] 小说评论模块。
|
||||
@ -44,9 +45,10 @@ Gitee仓库地址: https://gitee.com/novel_dev_team/novel-cloud
|
||||
```
|
||||
novel-plus -- 父工程
|
||||
├── novel-common -- 通用模块
|
||||
├── novel-front -- 前台门户系统
|
||||
├── novel-crawl -- 爬虫管理系统
|
||||
└── novel-admin -- 后台管理系统
|
||||
├── novel-front -- 前台门户&作家后台管理子系统(可拆分)
|
||||
├── novel-crawl -- 爬虫管理子系统
|
||||
├── novel-admin -- 平台后台管理子系统
|
||||
└── templates -- 前端模版
|
||||
```
|
||||
|
||||
#### 技术选型
|
||||
@ -78,9 +80,10 @@ novel-plus -- 父工程
|
||||
|
||||
#### 接口文档
|
||||
|
||||
[点击查看接口文档示例](./doc/api.md)
|
||||
[点击查看接口文档示例](doc/api/api.md)
|
||||
|
||||
#### PC站截图
|
||||
#### 橙色主题模版截图
|
||||
##### PC站截图
|
||||
|
||||
1. 首页
|
||||
|
||||
@ -134,7 +137,7 @@ novel-plus -- 父工程
|
||||
|
||||

|
||||
|
||||
#### 手机站截图
|
||||
##### 手机站截图
|
||||
|
||||
1. 首页
|
||||
|
||||
@ -152,13 +155,13 @@ novel-plus -- 父工程
|
||||
|
||||
<img src="https://s3.ax1x.com/2020/12/04/Dbsew4.jpg" alt="QQ图片20191018161901" style="zoom:33%;" />
|
||||
|
||||
#### 爬虫管理系统截图
|
||||
##### 爬虫管理系统截图
|
||||
|
||||

|
||||
|
||||

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

|
||||
|
||||
@ -168,6 +171,30 @@ novel-plus -- 父工程
|
||||
|
||||

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

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

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

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

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

|
||||
|
||||
#### 安装步骤
|
||||
|
||||
##### 数据库安装:
|
||||
@ -175,19 +202,21 @@ novel-plus -- 父工程
|
||||
1. 安装MySQL软件。
|
||||
2. 修改MySQL`max_allowed_packet `配置(建议100M)。
|
||||
3. 新建数据库,设置编码为utf8mb4。
|
||||
4. 执行sql/novel_plus.sql脚本文件。
|
||||
4. 执行doc/sql/novel_plus.sql脚本文件。
|
||||
|
||||
##### 爬虫管理系统安装:
|
||||
|
||||
1. 修改novel-common模块下application-dev.yml文件中的数据库的配置。
|
||||
1. 修改novel-common模块下application-common-dev.yml配置文件中的数据库配置。
|
||||
2. 修改novel-crawl模块下application.yml文件中的管理员账号密码。
|
||||
3. 启动程序,打开浏览器,默认8081端口访问。
|
||||
4. 选择已有或新增爬虫源(支持自定义爬虫规则),点击`开启`按钮,开始爬取小说数据。
|
||||
|
||||
##### 前台小说门户安装:
|
||||
##### 前台小说门户安装(jar包形式部署时,需要复制templates文件夹到jar文件的相同目录下):
|
||||
|
||||
1. 修改novel-common模块下application-dev.yml文件中的数据库的配置。
|
||||
2. 启动程序,打开浏览器,默认8080端口访问。
|
||||
1. 修改novel-common模块下application-common-dev.yml配置文件中的数据库配置。
|
||||
2. 修改novel-front模块下application.yml配置文件中的模版名为你需要使用的模版名(templates文件夹下的模版文件夹名)(内置orange和dark两套模版)。
|
||||

|
||||
3. 启动程序,打开浏览器,默认8080端口访问。
|
||||
|
||||
**喜欢此项目的可以给我的GitHub和Gitee加个Star支持一下 。**
|
||||
|
||||
@ -207,9 +236,9 @@ docker安装教程:[点击前往](https://my.oschina.net/java2nb/blog/4271989)
|
||||
|
||||
#### QQ交流群
|
||||
|
||||

|
||||
[点击前往官网查看](https://xiongxyang.gitee.io/home/service.htm)
|
||||
|
||||
#### 微信公众号(发布最新更新资讯)
|
||||
#### 微信公众号(发布最新更新资讯、最新前端模版、最新爬虫规则、技术文档等)
|
||||
|
||||

|
||||
|
||||
|
@ -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>3.1.0</version>
|
||||
<version>3.3.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>novel-admin</name>
|
||||
|
@ -1,5 +1,5 @@
|
||||
java2nb:
|
||||
uploadPath: c:/var/java2nb/uploaded_files/
|
||||
uploadPath: /var/pic/
|
||||
username: admin
|
||||
password: 111111
|
||||
logging:
|
||||
@ -10,7 +10,7 @@ spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
|
||||
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: test123456
|
||||
#password:
|
||||
|
@ -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>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>novel</artifactId>
|
||||
<groupId>com.java2nb</groupId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -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,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;
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>novel</artifactId>
|
||||
<groupId>com.java2nb</groupId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -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;
|
||||
@ -37,7 +34,7 @@ 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) {
|
||||
@ -65,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;
|
||||
}
|
||||
//设置封面图片路径
|
||||
@ -96,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())) {
|
||||
@ -146,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();
|
||||
|
||||
@ -159,7 +156,7 @@ public class CrawlParser {
|
||||
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());
|
||||
}
|
||||
|
||||
@ -174,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) {
|
||||
|
||||
@ -189,12 +183,12 @@ public class CrawlParser {
|
||||
String sourceIndexId = indexIdMatch.group(1);
|
||||
String bookContentUrl = ruleBean.getBookContentUrl();
|
||||
int calStart = bookContentUrl.indexOf("{cal_");
|
||||
if(calStart != -1){
|
||||
if (calStart != -1) {
|
||||
//内容页URL需要进行计算才能得到
|
||||
String calStr = bookContentUrl.substring(calStart,calStart+bookContentUrl.substring(calStart).indexOf("}"));
|
||||
String calStr = bookContentUrl.substring(calStart, calStart + bookContentUrl.substring(calStart).indexOf("}"));
|
||||
String[] calArr = calStr.split("_");
|
||||
int calType = Integer.parseInt(calArr[1]);
|
||||
if(calType == 1) {
|
||||
if (calType == 1) {
|
||||
///{cal_1_1_3}_{bookId}/{indexId}.html
|
||||
//第一种计算规则,去除第x个参数的最后y个字母
|
||||
int x = Integer.parseInt(calArr[2]);
|
||||
@ -206,12 +200,12 @@ public class CrawlParser {
|
||||
calResult = sourceIndexId.substring(0, sourceBookId.length() - y);
|
||||
}
|
||||
|
||||
if(calResult.length() == 0){
|
||||
if (calResult.length() == 0) {
|
||||
calResult = "0";
|
||||
|
||||
}
|
||||
|
||||
bookContentUrl = bookContentUrl.replace(calStr+"}", calResult);
|
||||
bookContentUrl = bookContentUrl.replace(calStr + "}", calResult);
|
||||
}
|
||||
|
||||
}
|
||||
@ -223,54 +217,43 @@ public class CrawlParser {
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -279,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;
|
||||
}
|
||||
|
||||
@ -297,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内容
|
||||
@ -314,11 +311,11 @@ public class CrawlParser {
|
||||
try {
|
||||
|
||||
String body = HttpUtil.getByHttpClientWithChrome(url);
|
||||
if(body != null && body.length() < Constants.INVALID_HTML_LENGTH){
|
||||
return processErrorHttpResult(url);
|
||||
}
|
||||
//成功获得html内容
|
||||
return body;
|
||||
if (body != null && body.length() < Constants.INVALID_HTML_LENGTH) {
|
||||
return processErrorHttpResult(url);
|
||||
}
|
||||
//成功获得html内容
|
||||
return body;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -327,13 +324,13 @@ public class CrawlParser {
|
||||
}
|
||||
|
||||
@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,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())) {
|
||||
|
@ -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">
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>novel</artifactId>
|
||||
<groupId>com.java2nb</groupId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -6,15 +6,16 @@ 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.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -42,12 +43,7 @@ public class UserController extends BaseController {
|
||||
* 登陆
|
||||
*/
|
||||
@PostMapping("login")
|
||||
public ResultBean login(@Valid UserForm user, BindingResult result) {
|
||||
//判断参数是否合法
|
||||
if (result.hasErrors()) {
|
||||
log.info(result.getAllErrors().toString());
|
||||
return ResultBean.fail(ResponseStatus.PARAM_ERROR);
|
||||
}
|
||||
public ResultBean login(User user) {
|
||||
|
||||
//登陆
|
||||
UserDetails userDetails = userService.login(user);
|
||||
@ -64,13 +60,8 @@ public class UserController extends BaseController {
|
||||
* 注册
|
||||
*/
|
||||
@PostMapping("register")
|
||||
public ResultBean register(@Valid UserForm user, @RequestParam(value = "velCode", defaultValue = "") String velCode, BindingResult result) {
|
||||
public ResultBean register(@Validated({AddGroup.class}) User user, @RequestParam(value = "velCode", defaultValue = "") String velCode) {
|
||||
|
||||
//判断参数是否合法
|
||||
if (result.hasErrors()) {
|
||||
log.info(result.getAllErrors().toString());
|
||||
return ResultBean.fail(ResponseStatus.PARAM_ERROR);
|
||||
}
|
||||
|
||||
//判断验证码是否正确
|
||||
if (!velCode.equals(cacheService.get(RandomValidateCodeUtil.RANDOM_CODE_KEY))) {
|
||||
@ -225,7 +216,7 @@ public class UserController extends BaseController {
|
||||
* 更新个人信息
|
||||
* */
|
||||
@PostMapping("updateUserInfo")
|
||||
public ResultBean updateUserInfo(User user,HttpServletRequest request) {
|
||||
public ResultBean updateUserInfo(@Validated({UpdateGroup.class}) User user, HttpServletRequest request) {
|
||||
UserDetails userDetails = getUserDetails(request);
|
||||
if (userDetails == null) {
|
||||
return ResultBean.fail(ResponseStatus.NO_LOGIN);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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,6 +1,6 @@
|
||||
package com.java2nb.novel.controller;
|
||||
package com.java2nb.novel.page;
|
||||
|
||||
import com.java2nb.novel.core.bean.ResultBean;
|
||||
import com.java2nb.novel.controller.BaseController;
|
||||
import com.java2nb.novel.core.bean.UserDetails;
|
||||
import com.java2nb.novel.core.utils.ThreadLocalUtil;
|
||||
import com.java2nb.novel.entity.*;
|
||||
@ -9,16 +9,16 @@ import com.java2nb.novel.service.BookService;
|
||||
import com.java2nb.novel.service.NewsService;
|
||||
import com.java2nb.novel.service.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.URLEncoder;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -27,7 +27,7 @@ import java.util.List;
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Controller
|
||||
public class PageController extends BaseController{
|
||||
public class PageController extends BaseController {
|
||||
|
||||
private final BookService bookService;
|
||||
|
||||
@ -97,6 +97,7 @@ public class PageController extends BaseController{
|
||||
/**
|
||||
* 详情页
|
||||
* */
|
||||
@SneakyThrows
|
||||
@RequestMapping("/book/{bookId}.html")
|
||||
public String bookDetail(@PathVariable("bookId") Long bookId, Model model) {
|
||||
Book book = bookService.queryBookDetail(bookId);
|
||||
@ -112,6 +113,7 @@ public class PageController extends BaseController{
|
||||
/**
|
||||
* 目录页
|
||||
* */
|
||||
@SneakyThrows
|
||||
@RequestMapping("/book/indexList-{bookId}.html")
|
||||
public String indexList(@PathVariable("bookId") Long bookId, Model model) {
|
||||
Book book = bookService.queryBookDetail(bookId);
|
||||
@ -125,13 +127,14 @@ public class PageController extends BaseController{
|
||||
/**
|
||||
* 内容页
|
||||
* */
|
||||
@SneakyThrows
|
||||
@RequestMapping("/book/{bookId}/{bookIndexId}.html")
|
||||
public String indexList(@PathVariable("bookId") Long bookId,@PathVariable("bookIndexId") Long bookIndexId, HttpServletRequest request,Model model) {
|
||||
public String indexList(@PathVariable("bookId") Long bookId,@PathVariable("bookIndexId") Long bookIndexId, HttpServletRequest request, Model model) {
|
||||
//查询书籍
|
||||
Book book = bookService.queryBookDetail(bookId);
|
||||
model.addAttribute("book",book);
|
||||
//查询目录
|
||||
BookIndex bookIndex = bookService.queryBookIndex(bookIndexId);
|
||||
model.addAttribute("book",book);
|
||||
model.addAttribute("bookIndex",bookIndex);
|
||||
//查询上一章节目录ID
|
||||
Long preBookIndexId = bookService.queryPreBookIndexId(bookId,bookIndex.getIndexNum());
|
@ -3,7 +3,6 @@ package com.java2nb.novel.service;
|
||||
|
||||
import com.java2nb.novel.core.bean.UserDetails;
|
||||
import com.java2nb.novel.entity.UserBuyRecord;
|
||||
import com.java2nb.novel.form.UserForm;
|
||||
import com.java2nb.novel.vo.BookReadHistoryVO;
|
||||
import com.java2nb.novel.vo.BookShelfVO;
|
||||
import com.java2nb.novel.entity.User;
|
||||
@ -19,17 +18,17 @@ public interface UserService {
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
* @param form 用户注册提交信息类
|
||||
* @param user 用户注册信息类
|
||||
* @return jwt载体信息类
|
||||
* */
|
||||
UserDetails register(UserForm form);
|
||||
UserDetails register(User user);
|
||||
|
||||
/**
|
||||
* 用户登陆
|
||||
* @param form 用户登陆提交信息类
|
||||
* @param user 用户登陆信息类
|
||||
* @return jwt载体信息类
|
||||
* */
|
||||
UserDetails login(UserForm form);
|
||||
UserDetails login(User user);
|
||||
|
||||
/**
|
||||
* 查询小说是否已加入书架
|
||||
|
@ -5,7 +5,6 @@ import com.java2nb.novel.core.bean.UserDetails;
|
||||
import com.java2nb.novel.core.utils.BeanUtil;
|
||||
import com.java2nb.novel.entity.*;
|
||||
import com.java2nb.novel.entity.User;
|
||||
import com.java2nb.novel.form.UserForm;
|
||||
import com.java2nb.novel.service.UserService;
|
||||
import com.java2nb.novel.core.enums.ResponseStatus;
|
||||
import com.java2nb.novel.core.exception.BusinessException;
|
||||
@ -29,7 +28,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.book;
|
||||
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.id;
|
||||
import static com.java2nb.novel.mapper.UserBookshelfDynamicSqlSupport.userBookshelf;
|
||||
import static com.java2nb.novel.mapper.UserDynamicSqlSupport.*;
|
||||
@ -59,11 +57,11 @@ public class UserServiceImpl implements UserService {
|
||||
|
||||
|
||||
@Override
|
||||
public UserDetails register(UserForm form) {
|
||||
public UserDetails register(User user) {
|
||||
//查询用户名是否已注册
|
||||
SelectStatementProvider selectStatement = select(count(id))
|
||||
.from(user)
|
||||
.where(username, isEqualTo(form.getUsername()))
|
||||
.from(UserDynamicSqlSupport.user)
|
||||
.where(username, isEqualTo(user.getUsername()))
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3);
|
||||
long count = userMapper.count(selectStatement);
|
||||
@ -72,7 +70,7 @@ public class UserServiceImpl implements UserService {
|
||||
throw new BusinessException(ResponseStatus.USERNAME_EXIST);
|
||||
}
|
||||
User entity = new User();
|
||||
BeanUtils.copyProperties(form,entity);
|
||||
BeanUtils.copyProperties(user,entity);
|
||||
//数据库生成注册记录
|
||||
Long id = new IdWorker().nextId();
|
||||
entity.setId(id);
|
||||
@ -91,12 +89,12 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails login(UserForm form) {
|
||||
public UserDetails login(User user) {
|
||||
//根据用户名密码查询记录
|
||||
SelectStatementProvider selectStatement = select(id, username,nickName)
|
||||
.from(user)
|
||||
.where(username, isEqualTo(form.getUsername()))
|
||||
.and(password, isEqualTo(MD5Util.MD5Encode(form.getPassword(), Charsets.UTF_8.name())))
|
||||
.from(UserDynamicSqlSupport.user)
|
||||
.where(username, isEqualTo(user.getUsername()))
|
||||
.and(password, isEqualTo(MD5Util.MD5Encode(user.getPassword(), Charsets.UTF_8.name())))
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3);
|
||||
List<User> users = userMapper.selectMany(selectStatement);
|
||||
@ -105,10 +103,10 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
//生成UserDetail对象并返回
|
||||
UserDetails userDetails = new UserDetails();
|
||||
User user = users.get(0);
|
||||
user = users.get(0);
|
||||
userDetails.setId(user.getId());
|
||||
userDetails.setNickName(user.getNickName());
|
||||
userDetails.setUsername(form.getUsername());
|
||||
userDetails.setUsername(user.getUsername());
|
||||
return userDetails;
|
||||
}
|
||||
|
||||
@ -232,12 +230,9 @@ public class UserServiceImpl implements UserService {
|
||||
|
||||
@Override
|
||||
public void updateUserInfo(Long userId, User user) {
|
||||
User updateUser = new User();
|
||||
updateUser.setId(userId);
|
||||
updateUser.setNickName(user.getNickName());
|
||||
updateUser.setUserSex(user.getUserSex());
|
||||
updateUser.setUpdateTime(new Date());
|
||||
userMapper.updateByPrimaryKeySelective(updateUser);
|
||||
user.setId(userId);
|
||||
user.setUpdateTime(new Date());
|
||||
userMapper.updateByPrimaryKeySelective(user);
|
||||
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,14 @@ spring:
|
||||
jest:
|
||||
uris: http://127.0.0.1:9200
|
||||
|
||||
#thymeleaf模版路径配置
|
||||
thymeleaf:
|
||||
prefix: file:${user.dir}/templates/${templates.name}/html/
|
||||
suffix: .html
|
||||
#静态文件路径配置
|
||||
resources:
|
||||
static-locations: file:${user.dir}/templates/${templates.name}/static/
|
||||
|
||||
redisson:
|
||||
singleServerConfig:
|
||||
address: 127.0.0.1:6379
|
||||
@ -65,3 +73,13 @@ book:
|
||||
word-count: 1000
|
||||
#价值(屋币)
|
||||
value: 5
|
||||
|
||||
|
||||
|
||||
#模版配置
|
||||
templates:
|
||||
name: orange
|
||||
|
||||
|
||||
|
||||
|
||||
|
BIN
novel-front/src/main/resources/static/images/404.jpeg
Normal file
After Width: | Height: | Size: 9.5 KiB |
17
novel-front/src/main/resources/templates/404.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Page Not Found</title>
|
||||
<script>
|
||||
setTimeout(function () {
|
||||
location.href = '/';
|
||||
},3000)
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body style="background: url(/images/404.jpeg) no-repeat;" >
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
2
pom.xml
@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.java2nb</groupId>
|
||||
<artifactId>novel</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.3.0</version>
|
||||
<modules>
|
||||
<module>novel-common</module>
|
||||
<module>novel-front</module>
|
||||
|
17
templates/dark/html/404.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Page Not Found</title>
|
||||
<script>
|
||||
setTimeout(function () {
|
||||
location.href = '/';
|
||||
},3000)
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body style="background: url(/images/404.jpeg) no-repeat;" >
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
364
templates/dark/html/book/book_content.html
Normal file
@ -0,0 +1,364 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta th:if="${catId == 9}" name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=1">
|
||||
<meta th:if="${catId != 9}" name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title th:utext="${book.bookName}+${bookIndex.indexName}"></title>
|
||||
|
||||
<meta name="keywords" th:content="${book.bookName}+','+${bookIndex.indexName}">
|
||||
|
||||
<meta name="description"
|
||||
th:content="${book.bookName}+'最新更新章节免费在线阅读TXT下载'">
|
||||
|
||||
|
||||
|
||||
<div th:include="common/css :: css"></div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
function reinitIframe(){
|
||||
|
||||
var iframe = document.getElementById("frame_content");
|
||||
try{
|
||||
iframe.height = iframe.contentWindow.document.documentElement.scrollHeight;
|
||||
}catch (ex){}
|
||||
}
|
||||
window.setInterval("reinitIframe()", 200);
|
||||
</script>
|
||||
<script th:fragment="js" src="/js/jquery-1.9.1.js"></script>
|
||||
<script th:fragment="js" src="/layui/layui.all.js"></script>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
.indexP p a {
|
||||
color: #4c6978;
|
||||
}
|
||||
|
||||
.Readarea {
|
||||
font-size: 18px;
|
||||
line-height: 35px;
|
||||
padding: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
div, p {
|
||||
wrap-work: break-word;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
word-break: normal;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.indexDiv a {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.Readpage {
|
||||
font-size: 14px;
|
||||
padding: 0;
|
||||
background: #d4eaf2;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div, p {
|
||||
wrap-work: break-word;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
word-break: normal;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
/* background-attachment: fixed; */
|
||||
}
|
||||
|
||||
user agent stylesheet
|
||||
p {
|
||||
display: block;
|
||||
-webkit-margin-before: 1em;
|
||||
-webkit-margin-after: 1em;
|
||||
-webkit-margin-start: 0px;
|
||||
-webkit-margin-end: 0px;
|
||||
}
|
||||
|
||||
.huyanon {
|
||||
border: 1px solid #64c878;
|
||||
box-shadow: 0 1px 2px #b9ecc4 inset, 0 -1px 0 #6c9f76 inset, 0 -2px 3px #b9ecc4 inset;
|
||||
background: -webkit-linear-gradient(top, #90dfa2, #84d494);
|
||||
background: -moz-linear-gradient(top, #90dfa2, #84d494);
|
||||
background: linear-gradient(top, #90dfa2, #84d494);
|
||||
}
|
||||
|
||||
.Readpage a {
|
||||
font-size: 16px;
|
||||
padding: 2px 2px;
|
||||
line-height: 35px;
|
||||
}
|
||||
|
||||
.lightoff, .huyanoff, .sizebgon {
|
||||
border: 1px solid #333;
|
||||
box-shadow: 0 1px 2px #8b8b8b inset, 0 -1px 0 #3d3d3d inset, 0 -2px 3px #8b8b8b inset;
|
||||
background: -webkit-linear-gradient(top, #656565, #4c4c4c);
|
||||
background: -moz-linear-gradient(top, #656565, #4a4a4a);
|
||||
background: linear-gradient(top, #656565, #4a4a4a);
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 40px;
|
||||
line-height: 38px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px 1px #333;
|
||||
border-radius: 5px;
|
||||
margin: 3px 0px 0px 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4c6978;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.lighton {
|
||||
border: 1px solid #d2a000;
|
||||
box-shadow: 0 1px 2px #fedd71 inset, 0 -1px 0 #a38b39 inset, 0 -2px 3px #fedd71 inset;
|
||||
background: -webkit-linear-gradient(top, #fece34, #d8a605);
|
||||
background: -moz-linear-gradient(top, #fece34, #d8a605);
|
||||
background: linear-gradient(top, #fece34, #d8a605);
|
||||
}
|
||||
|
||||
.screen_toolbar {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0px;
|
||||
bottom: 100px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body id="read">
|
||||
<div id="content">
|
||||
|
||||
|
||||
<input type="hidden" id="bookIdHidden" th:value="${book.id}"/>
|
||||
|
||||
<input type="hidden" id="bookNameHidden" th:value="${book.bookName}"/>
|
||||
|
||||
<input type="hidden" id="contentIdHidden" th:value="${bookIndex.id}"/>
|
||||
|
||||
<input type="hidden" id="indexNameHidden" th:value="${bookIndex.indexName}"/>
|
||||
|
||||
<input type="hidden" id="indexNumHidden" th:value="${bookIndex.indexNum}"/>
|
||||
|
||||
<script>
|
||||
var token = localStorage.getItem("token");
|
||||
</script>
|
||||
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="width:10%;float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<a style="color: #ffffff;" th:href="'/book/'+ ${book.id} + '.html'"><b style="padding-left: 5%;float: left;width: 69%" class="line-limit-length" th:utext="${bookIndex.indexName}+' '+${book.bookName}"></b></a>
|
||||
<div style="width:10%;float: right;margin-right: 10px"><a href="/">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p class="Readpage" style="background:#FFFFFF;padding:2px;">
|
||||
<a id="lightdiv" class="button lighton" onclick="nr_setbg('light')">开灯</a>
|
||||
<a id="huyandiv" class="button huyanon" onclick="nr_setbg('huyan')">护眼</a>
|
||||
字体:<a id="fontbig" class="sizebg" onclick="nr_setbg('big')">大</a> <a id="fontmiddle" class="button sizebgon"
|
||||
onclick="nr_setbg('middle')">中</a> <a
|
||||
id="fontsmall" class="sizebg" onclick="nr_setbg('small')">小</a>
|
||||
</p>
|
||||
<div class="indexDiv" style="height: 42px;line-height: 42px;text-align:center;background: #f2f2f2">
|
||||
|
||||
<a th:href="${preBookIndexId!=0?'/book/'+book.id+'/'+preBookIndexId+'.html':'#'}">上一章</a>
|
||||
<a th:href="'/book/indexList-'+${book.id}+'.html'">目录</a>
|
||||
<a th:href="${nextBookIndexId!=0?'/book/'+book.id+'/'+nextBookIndexId+'.html':'#'}">下一章</a>
|
||||
</div>
|
||||
<!--<div id="screenInput" class="screen_toolbar" style="display: none">
|
||||
<div style="height: 5px" class="layui-col-xs2 layui-col-sm3 layui-col-md3 layui-col-lg3"></div>
|
||||
<div class="layui-col-xs6 layui-col-sm4 layui-col-md4 layui-col-lg4">
|
||||
<input type="text" id="screenBulletText" required lay-verify="required" placeholder="请输入弹幕内容,右下角开关可控制弹幕是否开启" autocomplete="off"
|
||||
class="layui-input">
|
||||
|
||||
</div>
|
||||
<div class="layui-col-xs2 layui-col-sm1 layui-col-md1 layui-col-lg1">
|
||||
<button class="layui-btn send">发送</button>
|
||||
</div>
|
||||
</div>
|
||||
<form id="screenSwitch" class="layui-form">
|
||||
<div class="layui-form-item" style="position: fixed;right: 0px;bottom: 100px" title="弹幕开关">
|
||||
<!– <label class="layui-form-label" style="opacity:0.5;font-weight: bold;color: red;">弹幕</label>–>
|
||||
<div class="layui-input-block">
|
||||
<input class="clear" type="checkbox" name="switch" lay-skin="switch">
|
||||
</div>
|
||||
</div>
|
||||
</form>-->
|
||||
<div th:replace="common/js :: js">
|
||||
</div>
|
||||
<div id="chaptercontent" class="Readarea ReadAjax_content screen_container"
|
||||
style="color: rgb(0, 0, 0); font-size: 25px;" th:if="${!needBuy}">
|
||||
<p style="width:100%;text-alight:center; overflow: auto;-webkit-overflow-scrolling:touch;" >
|
||||
<span
|
||||
th:utext="${bookContent.content}"></span></p>
|
||||
</div>
|
||||
<div class="Readarea ReadAjax_content screen_container"
|
||||
style="color: rgb(0, 0, 0); font-size: 10px;background-color: #fff" th:if="${needBuy}">
|
||||
<h5>此章为VIP章节,需要订阅后才能继续阅读</h5>
|
||||
价格:<span style="color: red" th:text="${bookIndex.bookPrice}+'屋币(1元=100屋币)'"></span><br/>
|
||||
<a href="javascript:buyBookIndex()" type="button" class="layui-btn layui-btn-sm layui-btn-radius">购买</a>
|
||||
|
||||
</div>
|
||||
<div class="indexDiv" style="height: 42px;line-height: 42px;text-align:center;background: #f2f2f2">
|
||||
|
||||
<a th:href="${preBookIndexId!=0?'/book/'+book.id+'/'+preBookIndexId+'.html':'#'}">上一章</a>
|
||||
<a th:href="'/book/indexList-'+${book.id}+'.html'">目录</a>
|
||||
<a th:href="${nextBookIndexId!=0?'/book/'+book.id+'/'+nextBookIndexId+'.html':'#'}">下一章</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div th:replace="common/footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
var ua = navigator.userAgent;
|
||||
|
||||
var ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
|
||||
|
||||
isIphone =!ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
|
||||
|
||||
isAndroid = ua.match(/(Android)\s+([\d.]+)/),
|
||||
|
||||
isMobile = isIphone || isAndroid;
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
<script>
|
||||
(function () {
|
||||
|
||||
//添加阅读记录
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/user/addReadHistory",
|
||||
data: {'bookId': $("#bookIdHidden").val(), 'preContentId': $("#contentIdHidden").val()},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
|
||||
},
|
||||
error: function () {
|
||||
}
|
||||
})
|
||||
|
||||
$("#content").css("min-height",($(window).height()-60)+"px");
|
||||
|
||||
|
||||
})();
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script src="/js/read.js"></script>
|
||||
<script language="javascript">getset()</script>
|
||||
<script language="javascript">getset1()</script>
|
||||
<script language="javascript">
|
||||
var books = localStorage.getItem("historyBooks");
|
||||
var item = parseInt($("#bookIdHidden").val());
|
||||
if (books) {
|
||||
var booksArr = JSON.parse(books);
|
||||
if (booksArr.length >= 50) {
|
||||
booksArr.splice(0, 1);
|
||||
}
|
||||
booksArr.remove(item);
|
||||
booksArr[booksArr.length] = item;
|
||||
} else {
|
||||
var booksArr = [item];
|
||||
}
|
||||
|
||||
localStorage.setItem("historyBooks", JSON.stringify(booksArr));//
|
||||
|
||||
function toMyCollect() {
|
||||
var token = localStorage.getItem("token");
|
||||
if (token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
} else {
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
|
||||
function buyBookIndex(){
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/user/buyBookIndex",
|
||||
data: {'bookId':$("#bookIdHidden").val(),"bookName":$("#bookNameHidden").val(),
|
||||
"bookIndexId":$("#contentIdHidden").val(),"bookIndexName":$("#indexNameHidden").val()},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
location.reload();
|
||||
|
||||
|
||||
} else if(data.code == 1001){
|
||||
//未登录
|
||||
|
||||
}else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
$.post("/book/addVisitCount", {"bookId": $("#bookIdHidden").val()}, function () {
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</html>
|
354
templates/dark/html/book/book_detail.html
Normal file
@ -0,0 +1,354 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title th:utext="${book.bookName}+'小说最新章节免费阅读和下载'"></title>
|
||||
|
||||
<meta name="keywords" th:content="${book.bookName}+','+${book.bookName}+'最新章节,'+${book.bookName}+'免费阅读,'+${book.bookName}+'TXT下载'">
|
||||
|
||||
<meta name="description"
|
||||
th:content="${book.bookName}+'最新章节列表,'+${book.bookName}+'最新更新章节免费无广告无弹窗在线阅读,'+${book.bookName}+'小说TXT免费下载。'">
|
||||
|
||||
|
||||
|
||||
|
||||
<div th:include="/common/css :: css"></div>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
.indexP p a{
|
||||
color:#4c6978;
|
||||
}
|
||||
|
||||
.tag-list {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 20px;
|
||||
position: fixed;
|
||||
top:50px;
|
||||
right: 0px;
|
||||
width: 120px;
|
||||
z-index:100000;
|
||||
}
|
||||
|
||||
.tag-list .tag {
|
||||
float: right;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.tag-list .tag a {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.tag-list .highlight {
|
||||
padding: 5px 9px;
|
||||
border: 1px solid #f90;
|
||||
color: #f90;
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
.tag-list .highlight .text {
|
||||
color: #f90;
|
||||
}
|
||||
.tag-list .tag .text {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
color: #f90;
|
||||
}
|
||||
|
||||
ul, li {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.tag-list .tag a {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tag-list .highlight .icn {
|
||||
color: #f90;
|
||||
}
|
||||
.tag-list .tag .icn {
|
||||
margin-right: 5px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.tag-list .highlight .text {
|
||||
padding-left: 3px;
|
||||
color: #f90;
|
||||
}
|
||||
.tag-list .tag .text {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
color: #f90;
|
||||
}
|
||||
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
|
||||
<ul class="tag-list clearfix" id="tagLi">
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<input type="hidden" id="bookIdHidden" th:value="${bookId}"/>
|
||||
<input type="hidden" id="bookNamedHidden" th:value="${book.bookName}"/>
|
||||
<input type="hidden" id="preContentId" th:value="${firstBookIndexId}"/>
|
||||
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<b class="layui-icon" th:utext="${book.bookName}"></b>
|
||||
<div style="float: right;margin-right: 10px">
|
||||
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-row" style="background: #f2f2f2">
|
||||
<div style="padding: 10px" class="layui-col-xs4 layui-col-sm2 layui-col-md2 layui-col-lg2">
|
||||
<img style=" width:auto; height:auto; max-width:100%; max-height:100%;" th:src="${book.picUrl}"/>
|
||||
|
||||
</div>
|
||||
<div style="position:relative;padding: 10px 20px" class="layui-col-xs8 layui-col-sm8 layui-col-md8 layui-col-lg8">
|
||||
<a th:href="'javascript:searchBooks(\''+ ${book.authorName}+'\')'"><div style=";color: #4c6978;" th:utext="'作者:'+ ${book.authorName}"></div></a>
|
||||
<a th:href="'/book/book_ranking.html?catId='+${book.catId}"><div style="margin-top: 5px;color: #4c6978;" th:text="'类别:'+ ${book.catName}"></div></a>
|
||||
<div style="margin-top: 5px;color: #4c6978;" th:text="'状态:'+ ${book.bookStatus==0?'连载':'完结'}"></div>
|
||||
<div style="margin-top: 5px;color: #4c6978;">更新:<i th:text="${#dates.format(book.lastIndexUpdateTime, 'yy-MM-dd')}"></i></div>
|
||||
<div style="margin-top: 5px;color: #4c6978;">评分:<i style="font-weight:bold;color: red" th:text="${book.score} + '分'"></i></div>
|
||||
<div style="margin-top: 5px;color: #4c6978;">点击:<i style="font-weight:bold;color: red" th:text="${book.visitCount}"></i></div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div style="text-align: center;height: 45px;line-height: 45px">
|
||||
<a th:href="'/book/'+${book.id}+'/'+${firstBookIndexId}+'.html'" type="button" class="layui-btn layui-btn-sm layui-btn-radius">开始阅读</a>
|
||||
<!--
|
||||
<button type="button" onclick="downloadFile()" class="layui-btn layui-btn-sm layui-btn-radius layui-bg-normal">下载TXT</button>
|
||||
-->
|
||||
</div>
|
||||
<p style="line-height: 23px;padding: 10px;font-size: 14px;color: #4c6978;" th:utext="${book.bookDesc}">
|
||||
|
||||
</p>
|
||||
|
||||
<div class="layui-collapse">
|
||||
<div class="layui-colla-item" >
|
||||
<h2 class="layui-colla-title">
|
||||
<span>最新章节</span>
|
||||
<span style="margin-left: 30px">
|
||||
更新: <i th:text="${#dates.format(book.lastIndexUpdateTime, 'yy-MM-dd HH:mm:ss')}"></i>
|
||||
</span>
|
||||
</h2>
|
||||
<div class="layui-colla-content layui-show indexP layui-row" id="indexList">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 42px;color:#4c6978;line-height: 42px;padding-left: 30px;background: #f2f2f2" >
|
||||
|
||||
<a th:href="'/book/indexList-'+${book.id}+'.html'">查看完整目录</a>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div style="position: fixed;top:0px;left:0px;z-index:-100;opacity: 0" th:utext="${attacDivForSearch}"></div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div th:replace="/common/footer :: footer">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
<div th:replace="/common/js :: js">
|
||||
</div>
|
||||
<script>
|
||||
//查询是否在书架
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/user/queryIsInShelf",
|
||||
data: {'bookId': $("#bookIdHidden").val()},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
if (data.data) {
|
||||
$("#cFavs").html("<button type=\"button\" id=\"cFavs\" class=\"layui-btn layui-btn-sm layui-btn-radius layui-btn-warm\">已在书架</button>");
|
||||
}
|
||||
|
||||
|
||||
} else if (data.code == 1001) {
|
||||
//未登录
|
||||
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
//查询最新目录集合
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/book/queryNewIndexList",
|
||||
data: {'bookId': $("#bookIdHidden").val()},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
var indexListHtml = "";
|
||||
for(var i = 0 ; i < data.data.length ; i++){
|
||||
var bookIndex = data.data[i];
|
||||
indexListHtml+=("<p class=\"line-limit-length layui-col-xs12 layui-col-sm4 layui-col-md3 layui-col-lg2\" style=\"padding-left:10px;height: 50px;line-height: 50px;\"><a href=\"/book/"+$("#bookIdHidden").val()+"/"+bookIndex.id+".html\">"+bookIndex.indexName+"</a></p>");
|
||||
}
|
||||
|
||||
$("#indexList").html(indexListHtml);
|
||||
|
||||
|
||||
|
||||
} else if (data.code == 1001) {
|
||||
//未登录
|
||||
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
function addInShell() {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/user/addToBookShelf",
|
||||
data: {'bookId': $("#bookIdHidden").val(), 'preContentId': $("#preContentId").val()},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
$("#cFavs").html("<button type=\"button\" id=\"cFavs\" class=\"layui-btn layui-btn-sm layui-btn-radius layui-btn-warm\">已在书架</button>");
|
||||
|
||||
|
||||
} else if (data.code == 1001) {
|
||||
//未登录
|
||||
location.href = '/user/login.html?originUrl=' + decodeURIComponent(location.href);
|
||||
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$("#content").css("min-height",($(window).height()-60)+"px");
|
||||
|
||||
function downloadFile() {
|
||||
var fileUrl = '/book/download?bookId='+$("#bookIdHidden").val()+'&bookName='+$("#bookNamedHidden").val();
|
||||
window.location.href=fileUrl;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function toMyCollect(){
|
||||
var token = localStorage.getItem("token");
|
||||
if(token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
}else{
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
|
||||
function addToCollect(){
|
||||
var token = localStorage.getItem("token");
|
||||
|
||||
if(token) {
|
||||
$.get("/user/addToCollect",{"bookId":$("#bookIdHidden").val(),"token":token},function(data){
|
||||
layer.alert(data.desc);
|
||||
if(data.code == 1) {
|
||||
$('#collectButton').unbind("click");
|
||||
$("#collectButton").text("撤下书架");
|
||||
$("#collectButton").click(function () {
|
||||
cancelToCollect();
|
||||
});
|
||||
}
|
||||
});
|
||||
}else{
|
||||
window.location.href = "/user/login.html?bookId="+$("#bookIdHidden").val();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function cancelToCollect(){
|
||||
var token = localStorage.getItem("token");
|
||||
|
||||
if(token) {
|
||||
$.get("/user/cancelToCollect",{"bookId":$("#bookIdHidden").val(),"token":token},function(data){
|
||||
layer.alert(data.desc);
|
||||
if(data.code == 1) {
|
||||
$('#collectButton').unbind("click");
|
||||
$("#collectButton").text("加入书架");
|
||||
$("#collectButton").click(function () {
|
||||
addToCollect();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}else{
|
||||
window.location.href = "/user/login.html?bookId="+$("#bookIdHidden").val();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function searchBooks(keyword) {
|
||||
window.location.href = "/book/book_ranking.html?keyword=" + encodeURI(keyword);
|
||||
}
|
||||
|
||||
$.post("/book/addVisitCount", {"bookId": $("#bookIdHidden").val()}, function () {
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
96
templates/dark/html/book/book_index.html
Normal file
@ -0,0 +1,96 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title th:utext="${book.bookName}+'最新免费章节目录列表'"></title>
|
||||
|
||||
<meta name="keywords" th:content="${book.bookName}+','+${book.bookName}+'最新章节'">
|
||||
|
||||
<meta name="description"
|
||||
th:content="${book.bookName}+'最新章节列表,'+${book.bookName}+'最新更新章节免费无广告无弹窗在线阅读TXT下载。'">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div th:include="/common/css :: css"></div>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
.indexP p a {
|
||||
color: #4c6978;
|
||||
}
|
||||
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="content">
|
||||
<input type="hidden" id="bookIdHidden" th:value="${book.id}"/>
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<a style="color: #ffffff;" th:href="'/book/'+ ${book.id} + '.html'"><b class="layui-icon" th:utext="${book.bookName}"></b></a>
|
||||
<div style="float: right;margin-right: 10px">
|
||||
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p style="height: 30px;line-height: 30px;padding: 10px">
|
||||
|
||||
<a href="#buttom" style="color: red"> ↓直达页面底部</a>
|
||||
</p>
|
||||
|
||||
|
||||
<div class="layui-colla-content layui-show indexP layui-row">
|
||||
<p class="line-limit-length layui-col-xs12 layui-col-sm4 layui-col-md3 layui-col-lg2" style="padding-left:10px;height: 50px;line-height: 50px;" th:each="index : ${bookIndexList}">
|
||||
<a th:href="'/book/'+${index.bookId}+'/'+${index.id}+'.html'" th:utext="${index.indexName}">
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div th:replace="/common/footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
<div th:replace="/common/js :: js">
|
||||
</div>
|
||||
<script>
|
||||
$("#content").css("min-height",($(window).height()-60)+"px");
|
||||
$.get("/book/addVisit",{"bookId":$("#bookIdHidden").val()},function(){});
|
||||
function toMyCollect(){
|
||||
var token = localStorage.getItem("token");
|
||||
if(token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
}else{
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
320
templates/dark/html/book/book_ranking.html
Normal file
@ -0,0 +1,320 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title th:text="#{website.name}+'列表'"></title>
|
||||
|
||||
<meta name="keywords"
|
||||
th:content="#{website.name}+',精品小说,弹幕网站,弹幕,弹幕小说网站,免费小说,小说阅读,小说排行,轻小说,txt小说下载,电子书下载,动漫轻小说,日本轻小说'">
|
||||
|
||||
<meta name="description"
|
||||
th:content="#{website.name}+'是国内优秀的小说弹幕网站,'+#{website.name}+'提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。'">
|
||||
|
||||
|
||||
<div th:include="/common/css :: css"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
.indexP p a {
|
||||
color: #4c6978;
|
||||
}
|
||||
|
||||
.Readarea {
|
||||
font-size: 18px;
|
||||
line-height: 35px;
|
||||
padding: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
div, p {
|
||||
wrap-work: break-word;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
word-break: normal;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.indexDiv a {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 130px;
|
||||
height: 180px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<input type="hidden" id="limit" th:value="${limit}"/>
|
||||
<input type="hidden" id="curr" th:value="${curr}"/>
|
||||
<input type="hidden" id="total" th:value="${total}"/>
|
||||
<input type="hidden" id="ids" th:value="${ids}"/>
|
||||
<input type="hidden" id="bookStatus" th:value="${bookStatus}"/>
|
||||
<input type="hidden" id="token" th:value="${token}"/>
|
||||
<input type="hidden" id="keyword" th:value="${keyword}"/>
|
||||
<input type="hidden" id="catId" th:value="${catId}"/>
|
||||
<input type="hidden" id="sortBy" th:value="${sortBy}"/>
|
||||
<input type="hidden" id="sort" th:value="${sort}"/>
|
||||
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<b class="layui-icon">小说列表</b>
|
||||
<div style="float: right;margin-right: 10px">
|
||||
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-container">
|
||||
<div class="layui-row">
|
||||
|
||||
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
|
||||
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
|
||||
autocomplete="off"
|
||||
class="layui-input" th:value="${keyword}">
|
||||
</div>
|
||||
<div class="layui-col-xs1" style="padding: 1%">
|
||||
<button onclick="search(1,20)" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="bookList">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="books" style="text-align: center"></div>
|
||||
|
||||
|
||||
<div th:replace="/common/footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
|
||||
<div th:replace="/common/js :: js"></div>
|
||||
|
||||
<script>
|
||||
|
||||
var catId = getQueryVariable("catId");
|
||||
var bookStatus = getQueryVariable("bookStatus");
|
||||
var sortBy = getQueryVariable("sortBy");
|
||||
var keyword = getQueryVariable("keyword");
|
||||
|
||||
if(keyword != false){
|
||||
$("#title").val(decodeURI(keyword));
|
||||
}else{
|
||||
keyword = "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
search(1,20);
|
||||
|
||||
function search(curr,limit) {
|
||||
|
||||
|
||||
|
||||
var searchData = {};
|
||||
|
||||
searchData.curr = curr;
|
||||
searchData.limit = limit;
|
||||
|
||||
keyword = $("#title").val();
|
||||
|
||||
if(catId != false){
|
||||
searchData.catId = catId;
|
||||
}
|
||||
|
||||
if(bookStatus != false){
|
||||
searchData.bookStatus = bookStatus;
|
||||
}
|
||||
|
||||
if(sortBy != false){
|
||||
searchData.sort = sortBy;
|
||||
}else if(!keyword){
|
||||
sortBy = "last_index_update_time";
|
||||
}
|
||||
|
||||
if(keyword){
|
||||
searchData.keyword = keyword;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/book/searchByPage",
|
||||
data: searchData,
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
var bookList = data.data.list;
|
||||
var bookListHtml = "";
|
||||
for (var i = 0; i < bookList.length; i++) {
|
||||
var book = bookList[i];
|
||||
|
||||
/*var end = book.bookDesc.indexOf("<");
|
||||
if(end != -1) {
|
||||
book.bookDesc = book.bookDesc.substring(0,end);
|
||||
}*/
|
||||
|
||||
if(book.bookDesc){
|
||||
book.bookDesc = book.bookDesc.replace(/<[^>]+>/g,"").replace(/\s+/g,"").replace(/ /g,"");
|
||||
}
|
||||
|
||||
bookListHtml += ("<div class=\"layui-row\" style=\"margin-bottom:10px;padding:10px;background: #f2f2f2\">\n" +
|
||||
" <a href=\"/book/"+book.id+".html\">\n" +
|
||||
" <div class=\"layui-col-xs6 layui-col-sm3 layui-col-md2 layui-col-lg2\" style=\"text-align: center\">\n" +
|
||||
" <img width='150' height='180' align=\"center\"\n" +
|
||||
" src=\""+book.picUrl+"\"/>\n" +
|
||||
"\n" +
|
||||
" </div>\n" +
|
||||
" </a>\n" +
|
||||
" <div style=\"padding: 10px\" class=\"layui-col-xs6 layui-col-sm8 layui-col-md8 layui-col-lg8\">\n" +
|
||||
" <a href=\"/book/"+book.id+".html\">\n" +
|
||||
" <div class=\"line-limit-length\" style=\";color: #4c6978;font-weight: bold;font-size: 15px\">"+book.bookName+"</div>\n" +
|
||||
" </a>\n" +
|
||||
" <div style=\";color: #4c6978;float: right;\"><i style=\"color: red\"></i></div>\n" +
|
||||
" <a href=\"/book/book_ranking.html?keyword="+encodeURI(book.authorName)+"\">\n" +
|
||||
" <div style=\";color: #4c6978;\" class=\"line-limit-length\">作者:"+book.authorName+"</div>\n" +
|
||||
" </a>\n" +
|
||||
" <div style=\"margin-top: 5px;color: #4c6978;\">类别:"+book.catName+"</div>\n" +
|
||||
" <div style=\"margin-top: 5px;color: #4c6978;\">状态:"+(book.bookStatus==0?'连载':'完结')+"</div>\n" +
|
||||
" <div style=\"margin-top: 5px;color: #4c6978;\">更新:<i>"+book.lastIndexUpdateTime.substr(0,11)+"</i>\n" +
|
||||
" </div>\n" +
|
||||
" <div style=\"margin-top: 5px;color: #4c6978;\">简介:"+(book.bookDesc?(book.bookDesc.length>20?(book.bookDesc.substr(0,20)+"..."):book.bookDesc):book.bookDesc)+"</div>\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
" </div>\n" +
|
||||
"\n" +
|
||||
" </div>");
|
||||
}
|
||||
$("#bookList").html(bookListHtml);
|
||||
|
||||
layui.use('laypage', function () {
|
||||
var laypage = layui.laypage;
|
||||
|
||||
//执行一个laypage实例
|
||||
laypage.render({
|
||||
elem: 'books' //注意,这里的 test1 是 ID,不用加 # 号
|
||||
, count: data.data.total //数据总数,从服务端得到,
|
||||
, curr: data.data.pageNum
|
||||
, limit: data.data.pageSize
|
||||
, jump: function (obj, first) {
|
||||
|
||||
|
||||
//obj包含了当前分页的所有参数,比如:
|
||||
console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。
|
||||
console.log(obj.limit); //得到每页显示的条数
|
||||
|
||||
|
||||
//首次不执行
|
||||
if (!first) {
|
||||
search(obj.curr, obj.limit);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function searchByAllCondition(curr, limit, newKeyword) {
|
||||
var toUrl = "/book/search?curr=" + curr + "&limit=" + limit;
|
||||
var ids = $("#ids").val();
|
||||
if (ids) {
|
||||
toUrl += ("&historyBookIds=" + ids);
|
||||
}
|
||||
var token = $("#token").val();
|
||||
if (token) {
|
||||
toUrl += ("&token=" + token);
|
||||
}
|
||||
var keyword = $("#keyword").val();
|
||||
if (newKeyword) {
|
||||
toUrl += encodeURI("&keyword=" + newKeyword);
|
||||
} else if (keyword) {
|
||||
toUrl += encodeURI("&keyword=" + keyword);
|
||||
}
|
||||
var bookStatus = $("#bookStatus").val();
|
||||
if (bookStatus) {
|
||||
toUrl += ("&bookStatus=" + bookStatus);
|
||||
}
|
||||
var catId = $("#catId").val();
|
||||
if (catId) {
|
||||
toUrl += ("&catId=" + catId);
|
||||
}
|
||||
|
||||
var sortBy = $("#sortBy").val();
|
||||
if (sortBy) {
|
||||
toUrl += ("&sortBy=" + sortBy);
|
||||
}
|
||||
|
||||
var sort = $("#sort").val();
|
||||
if (sort) {
|
||||
toUrl += ("&sort=" + sort);
|
||||
}
|
||||
|
||||
window.location.href = toUrl;
|
||||
}
|
||||
|
||||
function searchBooks() {
|
||||
var keywords = $("#title").val();
|
||||
$("#keyword").val("");
|
||||
searchByAllCondition(1, 20, keywords);
|
||||
}
|
||||
|
||||
</script>
|
||||
<script>
|
||||
|
||||
|
||||
|
||||
|
||||
function toMyCollect() {
|
||||
var token = localStorage.getItem("token");
|
||||
if (token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
} else {
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
88
templates/dark/html/book/book_submit.html
Normal file
@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>小说提交</title>
|
||||
|
||||
<div th:include="common/css :: css"></div>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body id="read" >
|
||||
|
||||
</div>
|
||||
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<b class="layui-icon">单本小说提交</b>
|
||||
<div style="float: right;margin-right: 10px"><a href="/">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 800px;padding: 20px;border: 1px solid #eee;">
|
||||
<form class="layui-form" action="">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">详情页Url:</label>
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1" >
|
||||
<input type="text" id="bookUrl" name="bookUrl" required lay-verify="required" placeholder="请输入源站小说详情页Url" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小说名:</label>
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1" >
|
||||
<input type="text" id="bookName" name="bookName" required lay-verify="required" placeholder="请输入小说名" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小说评分:</label>
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1">
|
||||
<input type="number" id="score" name="score" required lay-verify="required" placeholder="请输入小说评分" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit lay-filter="formDemo">提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div th:replace="common/footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
<div th:replace="common/js :: js"></div>
|
||||
|
||||
|
||||
<script>
|
||||
//Demo
|
||||
layui.use('form', function(){
|
||||
var form = layui.form;
|
||||
|
||||
//监听提交
|
||||
form.on('submit(formDemo)', function(){
|
||||
$.post("/book/submit",{"bookUrl":$("#bookUrl").val(),"bookName":$("#bookName").val(),"score":$("#score").val()},function (data) {
|
||||
if(data.code == 1 ){
|
||||
layer.alert("提交成功,任务排队中,请过一段时间后再搜索查看");
|
||||
}else{
|
||||
layer.alert("提交失败");
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
24
templates/dark/html/common/css.html
Normal file
@ -0,0 +1,24 @@
|
||||
<div th:fragment="css">
|
||||
<link rel="stylesheet" href="/layui/css/layui.css">
|
||||
<style type="text/css">
|
||||
.app {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.app {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.pc {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.pc {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</div>
|
11
templates/dark/html/common/footer.html
Normal file
@ -0,0 +1,11 @@
|
||||
<div th:fragment="footer" style="height: 60px;line-height: 60px;text-align: center" class="layui-footer footer footer-demo layui-bg-cyan">
|
||||
<!--<a href="/mobile/book/searchSoftBook.html" style="font-size: 14px;color: #92B8B1;">轻小说</a>
|
||||
<a href="/mobile/book/searchSoftBook.html?catId=9" style="font-size: 14px;color: #92B8B1;margin-left: 8px">漫画</a>-->
|
||||
<a href="/?to=mobile" style="font-size: 14px;color: #92B8B1;margin-left: 8px">手机站</a>
|
||||
<!--<a href="https://www.zinglizingli.xyz/me/index.html" style="font-size: 14px;color: #92B8B1;margin-left: 8px">开发者</a>-->
|
||||
|
||||
|
||||
<div style="float: right"><a href="#top"><i class="layui-icon"
|
||||
style="margin-right:15px;font-size: 30px;color:#92B8B1 "></i></a>
|
||||
</div>
|
||||
</div>
|
3
templates/dark/html/common/js.html
Normal file
@ -0,0 +1,3 @@
|
||||
<script th:fragment="js" src="/js/jquery-1.9.1.js"></script>
|
||||
<script th:fragment="js" src="/js/common.js"></script>
|
||||
<script th:fragment="js" src="/layui/layui.all.js"></script>
|
388
templates/dark/html/index.html
Normal file
@ -0,0 +1,388 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
|
||||
|
||||
<title th:text="#{website.name}"></title>
|
||||
|
||||
<meta name="keywords" th:content="#{website.name}+',精品小说,弹幕网站,弹幕,弹幕小说网站,免费小说,小说阅读,小说排行,轻小说,txt小说下载,电子书下载,动漫轻小说,日本轻小说'">
|
||||
|
||||
<meta name="description"
|
||||
th:content="#{website.name}+'是国内优秀的小说弹幕网站,'+#{website.name}+'提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。'">
|
||||
|
||||
<meta property="og:type" content="novel_index"/>
|
||||
<meta property="og:title" th:content="#{website.name}"/>
|
||||
<meta property="og:description"
|
||||
th:content="#{website.name}+'是国内优秀的小说弹幕网站,'+#{website.name}+'提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。'"/>
|
||||
|
||||
|
||||
<div th:include="/common/css :: css"></div>
|
||||
|
||||
<style>
|
||||
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
.layui-nav .layui-nav-item {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
body ul.layui-nav li.layui-nav-item a {
|
||||
display: block;
|
||||
transition: all .3s;
|
||||
-webkit-transition: all .3s;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<!-- 你的HTML代码 -->
|
||||
<a name="top"></a>
|
||||
<ul class="layui-nav app" lay-filter="" style="display:none;padding:0 10px;text-align: center">
|
||||
<li class="layui-nav-item"><a>分类</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a href="/book/book_ranking.html?catId=1&sort=last_index_update_time">玄幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=2&sort=last_index_update_time">修真小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=3&sort=last_index_update_time">都市小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=4&sort=last_index_update_time">历史小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=6&sort=last_index_update_time">网游小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=5&sort=last_index_update_time">科幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=7&sort=last_index_update_time">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="layui-nav-item"><a>全本</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1">全部小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=1">玄幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=2">修真小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=3">都市小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=4">历史小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=6">网游小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=5">科幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=7">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="layui-nav-item"><a>排行</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count">全部小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=1">玄幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=2">修真小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=3">都市小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=4">历史小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=6">网游小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=5">科幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=7">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<ul class="layui-nav pc" lay-filter="" style="padding:0 36px;text-align: center">
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=1&sort=last_index_update_time">玄幻小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=2&sort=last_index_update_time">修真小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=3&sort=last_index_update_time">都市小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=4&sort=last_index_update_time">历史小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=6&sort=last_index_update_time">网游小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=5&sort=last_index_update_time">科幻小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=7&sort=last_index_update_time">女频小说</a></li>
|
||||
<li class="layui-nav-item"><a>完本小说</a>
|
||||
<dl class="layui-nav-child"> <!-- 二级菜单 -->
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1">全部小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=1">玄幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=2">修真小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=3">都市小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=4">历史小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=6">网游小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=5">科幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=7">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="layui-nav-item"><a>小说排行</a>
|
||||
<dl class="layui-nav-child"> <!-- 二级菜单 -->
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count">全部小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=1">玄幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=2">修真小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=3">都市小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=4">历史小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=6">网游小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=5">科幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=7">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="layui-container">
|
||||
<div class="layui-row">
|
||||
|
||||
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
|
||||
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
|
||||
autocomplete="off"
|
||||
class="layui-input">
|
||||
</div>
|
||||
<div class="layui-col-xs1" style="padding: 1%">
|
||||
<button onclick="searchBooks()" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="height: 1px" class="layui-col-lg1"></div>
|
||||
<div class="layui-collapse layui-col-lg10">
|
||||
<div class="layui-colla-item">
|
||||
<h2 class="layui-colla-title">本站推荐</h2>
|
||||
<div class="layui-colla-content layui-show">
|
||||
|
||||
|
||||
<div class="layui-container" style="padding: 0px">
|
||||
|
||||
<div class="layui-row" style="text-align: center" id="currentWeek">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-colla-item">
|
||||
<h2 class="layui-colla-title">热门小说推荐</h2>
|
||||
<div class="layui-colla-content layui-show">
|
||||
|
||||
<div class="layui-container">
|
||||
<div class="layui-row" id="hotRecBooks">
|
||||
|
||||
|
||||
<!--<div th:each="hotBook : ${hotBooks}" style="margin-top: 1%"
|
||||
class="layui-col-xs12 layui-col-sm6 layui-col-md6 layui-col-lg6">
|
||||
<a th:href="'/book/'+${hotBook.id}+'.html'">
|
||||
<div class="layui-col-xs5 layui-col-sm3 layui-col-md3 layui-col-lg3">
|
||||
<img style=" width:100px; height:125px;"
|
||||
th:src="${hotBook.picUrl}"/>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md7 layui-col-lg7"
|
||||
style="float: left;padding-right: 10px">
|
||||
<div><b th:text="${hotBook.bookName}"></b></div>
|
||||
<div class="layui-col-xs8 layui-col-sm9 layui-col-md10 layui-col-lg10"
|
||||
th:text="'作者:'+ ${hotBook.author}"></div>
|
||||
<div class="layui-col-xs3 layui-col-sm2 layui-col-md1 layui-col-lg1" style="text-align: right;">
|
||||
<b><i style="color: red"
|
||||
th:text="${hotBook.score} + '分'"></i></b></div>
|
||||
</div>
|
||||
<div class="layui-elip layui-col-xs12 layui-col-sm9 layui-col-md10 layui-col-lg10 layui-col-sm9 layui-col-md10 layui-col-lg10"
|
||||
th:text="${hotBook.bookDesc}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
<div style="height: 1px" class="layui-col-lg1"></div>
|
||||
<div class="layui-colla-item layui-col-lg10"
|
||||
style="border-width: 1px;border-style: solid;border-radius: 2px;border-top-width: 0px"><a
|
||||
href="javascript:moreNewBooks()">
|
||||
<h2 class="layui-colla-title">最近更新小说
|
||||
<div style="float: right; margin-right: 20px"><i style="font-size: 14px;"
|
||||
class="layui-icon">更多</i>
|
||||
</div>
|
||||
</h2>
|
||||
</a>
|
||||
<div class="layui-colla-content layui-show">
|
||||
|
||||
<div class="layui-container" style="padding-left: 2px;padding-right: 5px">
|
||||
<div class="layui-row" id="updateRankBooks">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
<div th:replace="/common/footer :: footer">
|
||||
</div>
|
||||
<div th:replace="/common/js :: js">
|
||||
</div>
|
||||
|
||||
<script src="/js/wap_collect.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
//加载首页书籍设置数据
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/book/listBookSetting",
|
||||
data: {},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
|
||||
//本周强推
|
||||
var rightListBooks = data.data[2];
|
||||
var rightListBooksHtml = "";
|
||||
for (var i = 0; i < 3; i++) {
|
||||
var rightListBook = rightListBooks[i];
|
||||
var classHtml = "";
|
||||
if (i == 0) {
|
||||
classHtml = "on";
|
||||
}
|
||||
if (i < 3) {
|
||||
classHtml += (" num" + (i + 1));
|
||||
}
|
||||
|
||||
rightListBooksHtml += (" <span>\n" +
|
||||
" <a href=\"/book/"+rightListBook.bookId+".html\">\n" +
|
||||
" <div style=\"padding: 1%\" class=\"layui-col-xs4 layui-col-sm4 layui-col-md4 layui-col-lg4\">\n" +
|
||||
" <img style=\" width:80%; height:auto; max-width:100%; max-height:100%;\"\n" +
|
||||
" src=\""+rightListBook.picUrl+"\"/>\n" +
|
||||
"\n" +
|
||||
" <br/>\n" +
|
||||
" <span>"+rightListBook.bookName+"</span>\n" +
|
||||
"\n" +
|
||||
" </div>\n" +
|
||||
" </a>\n" +
|
||||
" </span>");
|
||||
}
|
||||
$("#currentWeek").html(rightListBooksHtml);
|
||||
|
||||
//热门推荐
|
||||
var hotRecBooks = data.data[3];
|
||||
var hotRecBooksHtml = "";
|
||||
for (var i = 0; i < 6; i++) {
|
||||
var hotRecBook = hotRecBooks[i];
|
||||
|
||||
if(hotRecBook.bookDesc){
|
||||
hotRecBook.bookDesc = hotRecBook.bookDesc.replace(/<[^>]+>/g,"").replace(/\s+/g,"");
|
||||
}
|
||||
|
||||
hotRecBooksHtml += ("<div style=\"margin-bottom: 5px\" class=\"layui-col-xs12 layui-col-sm6 layui-col-md4 layui-col-lg4\">\n" +
|
||||
" <a href=\"/book/"+hotRecBook.bookId+".html\">\n" +
|
||||
" <div class=\"layui-col-xs5 layui-col-sm4 layui-col-md4 layui-col-lg4\" >\n" +
|
||||
" <img style=\" width:100px; height:125px;\"\n" +
|
||||
" src=\""+hotRecBook.picUrl+"\"/>\n" +
|
||||
"\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"layui-col-xs5 layui-col-sm6 layui-col-md6 layui-col-lg6\">\n" +
|
||||
" <ul>\n" +
|
||||
" <li class=\"line-limit-length\" style=\"font-weight: bold\">"+hotRecBook.bookName+"</li>\n" +
|
||||
" <li>作者:"+hotRecBook.authorName+"</li>\n" +
|
||||
" <li style=\"width: 180px;height:40px;overflow: hidden\">简介: "+hotRecBook.bookDesc+"" +
|
||||
" </ul>\n" +
|
||||
" </div>\n" +
|
||||
" <div style=\"font-style: italic;color: red\"\n" +
|
||||
" class=\"layui-col-xs2 layui-col-sm2 layui-col-md2 layui-col-lg2\"></div>\n" +
|
||||
" </a>\n" +
|
||||
" </div>");
|
||||
}
|
||||
$("#hotRecBooks").html(hotRecBooksHtml);
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
//更新榜单查询
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/book/listUpdateRank",
|
||||
data: {},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
var updateRankBooks = data.data;
|
||||
var updateRankBookHtml = "";
|
||||
for (var i = 0; i < 10; i++) {
|
||||
|
||||
var updateRankBook = updateRankBooks[i];
|
||||
if(updateRankBook.bookDesc){
|
||||
updateRankBook.bookDesc = updateRankBook.bookDesc.replace(/<[^>]+>/g,"").replace(/\s+/g,"");
|
||||
}
|
||||
|
||||
updateRankBookHtml += ("<div style=\"padding-bottom: 30px\"\n" +
|
||||
" class=\"layui-col-xs12 layui-col-sm6 layui-col-md6 layui-col-lg6\">\n" +
|
||||
"\n" +
|
||||
" <a href=\"/book/"+updateRankBook.id+".html\">\n" +
|
||||
" <div class=\"line-limit-length layui-col-xs8 layui-col-sm6 layui-col-md6 layui-col-lg6\"><b>"+(i+1)+"."+updateRankBook.bookName+"</b> - <span class=\"layui-elip\">"+updateRankBook.authorName+"</span>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"layui-col-sm3 layui-col-md3 layui-col-lg3\"\n" +
|
||||
" style=\"color: #FF5722;float: right;margin-right:5px\"><i>"+updateRankBook.lastIndexUpdateTime+"</i></div>\n" +
|
||||
"\n" +
|
||||
" <div style=\"clear: both\"></div>\n" +
|
||||
" <div style=\"padding-left: 5px;padding-top: 5px\"\n" +
|
||||
" class=\"layui-elip layui-col-md11 layui-col-sm11 layui-col-lg11\">简介: "+updateRankBook.bookDesc+"" +
|
||||
" </div></a>\n" +
|
||||
" </div>");
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
$("#updateRankBooks").html(updateRankBookHtml);
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
}
|
||||
,
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
function moreNewBooks(event) {
|
||||
window.location.href = "/book/book_ranking.html?sortBy=last_index_update_time";
|
||||
}
|
||||
|
||||
function searchBooks() {
|
||||
var keywords = $("#title").val();
|
||||
window.location.href = "/book/book_ranking.html?keyword=" + encodeURI(keywords);
|
||||
}
|
||||
|
||||
function toMyCollect() {
|
||||
var token = localStorage.getItem("token");
|
||||
if (token) {
|
||||
window.location.href = "/book/book_ranking.html?token=" + token;
|
||||
} else {
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
364
templates/dark/html/mobile/book/book_content.html
Normal file
@ -0,0 +1,364 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta th:if="${catId == 9}" name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=1">
|
||||
<meta th:if="${catId != 9}" name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title th:utext="${book.bookName}+${bookIndex.indexName}"></title>
|
||||
|
||||
<meta name="keywords" th:content="${book.bookName}+','+${bookIndex.indexName}">
|
||||
|
||||
<meta name="description"
|
||||
th:content="${book.bookName}+'最新更新章节免费在线阅读TXT下载'">
|
||||
|
||||
|
||||
|
||||
<div th:include="mobile/common/css :: css"></div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
function reinitIframe(){
|
||||
|
||||
var iframe = document.getElementById("frame_content");
|
||||
try{
|
||||
iframe.height = iframe.contentWindow.document.documentElement.scrollHeight;
|
||||
}catch (ex){}
|
||||
}
|
||||
window.setInterval("reinitIframe()", 200);
|
||||
</script>
|
||||
<script th:fragment="js" src="/mobile/js/jquery-1.9.1.js"></script>
|
||||
<script th:fragment="js" src="/mobile/layui/layui.all.js"></script>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
.indexP p a {
|
||||
color: #4c6978;
|
||||
}
|
||||
|
||||
.Readarea {
|
||||
font-size: 18px;
|
||||
line-height: 35px;
|
||||
padding: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
div, p {
|
||||
wrap-work: break-word;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
word-break: normal;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.indexDiv a {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.Readpage {
|
||||
font-size: 14px;
|
||||
padding: 0;
|
||||
background: #d4eaf2;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div, p {
|
||||
wrap-work: break-word;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
word-break: normal;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
/* background-attachment: fixed; */
|
||||
}
|
||||
|
||||
user agent stylesheet
|
||||
p {
|
||||
display: block;
|
||||
-webkit-margin-before: 1em;
|
||||
-webkit-margin-after: 1em;
|
||||
-webkit-margin-start: 0px;
|
||||
-webkit-margin-end: 0px;
|
||||
}
|
||||
|
||||
.huyanon {
|
||||
border: 1px solid #64c878;
|
||||
box-shadow: 0 1px 2px #b9ecc4 inset, 0 -1px 0 #6c9f76 inset, 0 -2px 3px #b9ecc4 inset;
|
||||
background: -webkit-linear-gradient(top, #90dfa2, #84d494);
|
||||
background: -moz-linear-gradient(top, #90dfa2, #84d494);
|
||||
background: linear-gradient(top, #90dfa2, #84d494);
|
||||
}
|
||||
|
||||
.Readpage a {
|
||||
font-size: 16px;
|
||||
padding: 2px 2px;
|
||||
line-height: 35px;
|
||||
}
|
||||
|
||||
.lightoff, .huyanoff, .sizebgon {
|
||||
border: 1px solid #333;
|
||||
box-shadow: 0 1px 2px #8b8b8b inset, 0 -1px 0 #3d3d3d inset, 0 -2px 3px #8b8b8b inset;
|
||||
background: -webkit-linear-gradient(top, #656565, #4c4c4c);
|
||||
background: -moz-linear-gradient(top, #656565, #4a4a4a);
|
||||
background: linear-gradient(top, #656565, #4a4a4a);
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 40px;
|
||||
line-height: 38px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px 1px #333;
|
||||
border-radius: 5px;
|
||||
margin: 3px 0px 0px 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4c6978;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.lighton {
|
||||
border: 1px solid #d2a000;
|
||||
box-shadow: 0 1px 2px #fedd71 inset, 0 -1px 0 #a38b39 inset, 0 -2px 3px #fedd71 inset;
|
||||
background: -webkit-linear-gradient(top, #fece34, #d8a605);
|
||||
background: -moz-linear-gradient(top, #fece34, #d8a605);
|
||||
background: linear-gradient(top, #fece34, #d8a605);
|
||||
}
|
||||
|
||||
.screen_toolbar {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0px;
|
||||
bottom: 100px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body id="read">
|
||||
<div id="content">
|
||||
|
||||
|
||||
<input type="hidden" id="bookIdHidden" th:value="${book.id}"/>
|
||||
|
||||
<input type="hidden" id="bookNameHidden" th:value="${book.bookName}"/>
|
||||
|
||||
<input type="hidden" id="contentIdHidden" th:value="${bookIndex.id}"/>
|
||||
|
||||
<input type="hidden" id="indexNameHidden" th:value="${bookIndex.indexName}"/>
|
||||
|
||||
<input type="hidden" id="indexNumHidden" th:value="${bookIndex.indexNum}"/>
|
||||
|
||||
<script>
|
||||
var token = localStorage.getItem("token");
|
||||
</script>
|
||||
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="width:10%;float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<a style="color: #ffffff;" th:href="'/book/'+ ${book.id} + '.html'"><b style="padding-left: 5%;float: left;width: 69%" class="line-limit-length" th:utext="${bookIndex.indexName}+' '+${book.bookName}"></b></a>
|
||||
<div style="width:10%;float: right;margin-right: 10px"><a href="/">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p class="Readpage" style="background:#FFFFFF;padding:2px;">
|
||||
<a id="lightdiv" class="button lighton" onclick="nr_setbg('light')">开灯</a>
|
||||
<a id="huyandiv" class="button huyanon" onclick="nr_setbg('huyan')">护眼</a>
|
||||
字体:<a id="fontbig" class="sizebg" onclick="nr_setbg('big')">大</a> <a id="fontmiddle" class="button sizebgon"
|
||||
onclick="nr_setbg('middle')">中</a> <a
|
||||
id="fontsmall" class="sizebg" onclick="nr_setbg('small')">小</a>
|
||||
</p>
|
||||
<div class="indexDiv" style="height: 42px;line-height: 42px;text-align:center;background: #f2f2f2">
|
||||
|
||||
<a th:href="${preBookIndexId!=0?'/book/'+book.id+'/'+preBookIndexId+'.html':'#'}">上一章</a>
|
||||
<a th:href="'/book/indexList-'+${book.id}+'.html'">目录</a>
|
||||
<a th:href="${nextBookIndexId!=0?'/book/'+book.id+'/'+nextBookIndexId+'.html':'#'}">下一章</a>
|
||||
</div>
|
||||
<!--<div id="screenInput" class="screen_toolbar" style="display: none">
|
||||
<div style="height: 5px" class="layui-col-xs2 layui-col-sm3 layui-col-md3 layui-col-lg3"></div>
|
||||
<div class="layui-col-xs6 layui-col-sm4 layui-col-md4 layui-col-lg4">
|
||||
<input type="text" id="screenBulletText" required lay-verify="required" placeholder="请输入弹幕内容,右下角开关可控制弹幕是否开启" autocomplete="off"
|
||||
class="layui-input">
|
||||
|
||||
</div>
|
||||
<div class="layui-col-xs2 layui-col-sm1 layui-col-md1 layui-col-lg1">
|
||||
<button class="layui-btn send">发送</button>
|
||||
</div>
|
||||
</div>
|
||||
<form id="screenSwitch" class="layui-form">
|
||||
<div class="layui-form-item" style="position: fixed;right: 0px;bottom: 100px" title="弹幕开关">
|
||||
<!– <label class="layui-form-label" style="opacity:0.5;font-weight: bold;color: red;">弹幕</label>–>
|
||||
<div class="layui-input-block">
|
||||
<input class="clear" type="checkbox" name="switch" lay-skin="switch">
|
||||
</div>
|
||||
</div>
|
||||
</form>-->
|
||||
<div th:replace="mobile/common/js :: js">
|
||||
</div>
|
||||
<div id="chaptercontent" class="Readarea ReadAjax_content screen_container"
|
||||
style="color: rgb(0, 0, 0); font-size: 25px;" th:if="${!needBuy}">
|
||||
<p style="width:100%;text-alight:center; overflow: auto;-webkit-overflow-scrolling:touch;" >
|
||||
<span
|
||||
th:utext="${bookContent.content}"></span></p>
|
||||
</div>
|
||||
<div class="Readarea ReadAjax_content screen_container"
|
||||
style="color: rgb(0, 0, 0); font-size: 10px;background-color: #fff" th:if="${needBuy}">
|
||||
<h5>此章为VIP章节,需要订阅后才能继续阅读</h5>
|
||||
价格:<span style="color: red" th:text="${bookIndex.bookPrice}+'屋币(1元=100屋币)'"></span><br/>
|
||||
<a href="javascript:buyBookIndex()" type="button" class="layui-btn layui-btn-sm layui-btn-radius">购买</a>
|
||||
|
||||
</div>
|
||||
<div class="indexDiv" style="height: 42px;line-height: 42px;text-align:center;background: #f2f2f2">
|
||||
|
||||
<a th:href="${preBookIndexId!=0?'/book/'+book.id+'/'+preBookIndexId+'.html':'#'}">上一章</a>
|
||||
<a th:href="'/book/indexList-'+${book.id}+'.html'">目录</a>
|
||||
<a th:href="${nextBookIndexId!=0?'/book/'+book.id+'/'+nextBookIndexId+'.html':'#'}">下一章</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div th:replace="mobile/common/footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
var ua = navigator.userAgent;
|
||||
|
||||
var ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
|
||||
|
||||
isIphone =!ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
|
||||
|
||||
isAndroid = ua.match(/(Android)\s+([\d.]+)/),
|
||||
|
||||
isMobile = isIphone || isAndroid;
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
<script>
|
||||
(function () {
|
||||
|
||||
//添加阅读记录
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/user/addReadHistory",
|
||||
data: {'bookId': $("#bookIdHidden").val(), 'preContentId': $("#contentIdHidden").val()},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
|
||||
},
|
||||
error: function () {
|
||||
}
|
||||
})
|
||||
|
||||
$("#content").css("min-height",($(window).height()-60)+"px");
|
||||
|
||||
|
||||
})();
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script src="/mobile/js/read.js"></script>
|
||||
<script language="javascript">getset()</script>
|
||||
<script language="javascript">getset1()</script>
|
||||
<script language="javascript">
|
||||
var books = localStorage.getItem("historyBooks");
|
||||
var item = parseInt($("#bookIdHidden").val());
|
||||
if (books) {
|
||||
var booksArr = JSON.parse(books);
|
||||
if (booksArr.length >= 50) {
|
||||
booksArr.splice(0, 1);
|
||||
}
|
||||
booksArr.remove(item);
|
||||
booksArr[booksArr.length] = item;
|
||||
} else {
|
||||
var booksArr = [item];
|
||||
}
|
||||
|
||||
localStorage.setItem("historyBooks", JSON.stringify(booksArr));//
|
||||
|
||||
function toMyCollect() {
|
||||
var token = localStorage.getItem("token");
|
||||
if (token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
} else {
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
|
||||
function buyBookIndex(){
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/user/buyBookIndex",
|
||||
data: {'bookId':$("#bookIdHidden").val(),"bookName":$("#bookNameHidden").val(),
|
||||
"bookIndexId":$("#contentIdHidden").val(),"bookIndexName":$("#indexNameHidden").val()},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
location.reload();
|
||||
|
||||
|
||||
} else if(data.code == 1001){
|
||||
//未登录
|
||||
|
||||
}else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
$.post("/book/addVisitCount", {"bookId": $("#bookIdHidden").val()}, function () {
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</html>
|
354
templates/dark/html/mobile/book/book_detail.html
Normal file
@ -0,0 +1,354 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title th:utext="${book.bookName}+'小说最新章节免费阅读和下载'"></title>
|
||||
|
||||
<meta name="keywords" th:content="${book.bookName}+','+${book.bookName}+'最新章节,'+${book.bookName}+'免费阅读,'+${book.bookName}+'TXT下载'">
|
||||
|
||||
<meta name="description"
|
||||
th:content="${book.bookName}+'最新章节列表,'+${book.bookName}+'最新更新章节免费无广告无弹窗在线阅读,'+${book.bookName}+'小说TXT免费下载。'">
|
||||
|
||||
|
||||
|
||||
|
||||
<div th:include="mobile/common/css :: css"></div>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
.indexP p a{
|
||||
color:#4c6978;
|
||||
}
|
||||
|
||||
.tag-list {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 20px;
|
||||
position: fixed;
|
||||
top:50px;
|
||||
right: 0px;
|
||||
width: 120px;
|
||||
z-index:100000;
|
||||
}
|
||||
|
||||
.tag-list .tag {
|
||||
float: right;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.tag-list .tag a {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.tag-list .highlight {
|
||||
padding: 5px 9px;
|
||||
border: 1px solid #f90;
|
||||
color: #f90;
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
.tag-list .highlight .text {
|
||||
color: #f90;
|
||||
}
|
||||
.tag-list .tag .text {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
color: #f90;
|
||||
}
|
||||
|
||||
ul, li {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.tag-list .tag a {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tag-list .highlight .icn {
|
||||
color: #f90;
|
||||
}
|
||||
.tag-list .tag .icn {
|
||||
margin-right: 5px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.tag-list .highlight .text {
|
||||
padding-left: 3px;
|
||||
color: #f90;
|
||||
}
|
||||
.tag-list .tag .text {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
color: #f90;
|
||||
}
|
||||
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
|
||||
<ul class="tag-list clearfix" id="tagLi">
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<input type="hidden" id="bookIdHidden" th:value="${bookId}"/>
|
||||
<input type="hidden" id="bookNamedHidden" th:value="${book.bookName}"/>
|
||||
<input type="hidden" id="preContentId" th:value="${firstBookIndexId}"/>
|
||||
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<b class="layui-icon" th:utext="${book.bookName}"></b>
|
||||
<div style="float: right;margin-right: 10px">
|
||||
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-row" style="background: #f2f2f2">
|
||||
<div style="padding: 10px" class="layui-col-xs4 layui-col-sm2 layui-col-md2 layui-col-lg2">
|
||||
<img style=" width:auto; height:auto; max-width:100%; max-height:100%;" th:src="${book.picUrl}"/>
|
||||
|
||||
</div>
|
||||
<div style="position:relative;padding: 10px 20px" class="layui-col-xs8 layui-col-sm8 layui-col-md8 layui-col-lg8">
|
||||
<a th:href="'javascript:searchBooks(\''+ ${book.authorName}+'\')'"><div style=";color: #4c6978;" th:utext="'作者:'+ ${book.authorName}"></div></a>
|
||||
<a th:href="'/book/book_ranking.html?catId='+${book.catId}"><div style="margin-top: 5px;color: #4c6978;" th:text="'类别:'+ ${book.catName}"></div></a>
|
||||
<div style="margin-top: 5px;color: #4c6978;" th:text="'状态:'+ ${book.bookStatus==0?'连载':'完结'}"></div>
|
||||
<div style="margin-top: 5px;color: #4c6978;">更新:<i th:text="${#dates.format(book.lastIndexUpdateTime, 'yy-MM-dd')}"></i></div>
|
||||
<div style="margin-top: 5px;color: #4c6978;">评分:<i style="font-weight:bold;color: red" th:text="${book.score} + '分'"></i></div>
|
||||
<div style="margin-top: 5px;color: #4c6978;">点击:<i style="font-weight:bold;color: red" th:text="${book.visitCount}"></i></div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div style="text-align: center;height: 45px;line-height: 45px">
|
||||
<a th:href="'/book/'+${book.id}+'/'+${firstBookIndexId}+'.html'" type="button" class="layui-btn layui-btn-sm layui-btn-radius">开始阅读</a>
|
||||
<!--
|
||||
<button type="button" onclick="downloadFile()" class="layui-btn layui-btn-sm layui-btn-radius layui-bg-normal">下载TXT</button>
|
||||
-->
|
||||
</div>
|
||||
<p style="line-height: 23px;padding: 10px;font-size: 14px;color: #4c6978;" th:utext="${book.bookDesc}">
|
||||
|
||||
</p>
|
||||
|
||||
<div class="layui-collapse">
|
||||
<div class="layui-colla-item" >
|
||||
<h2 class="layui-colla-title">
|
||||
<span>最新章节</span>
|
||||
<span style="margin-left: 30px">
|
||||
更新: <i th:text="${#dates.format(book.lastIndexUpdateTime, 'yy-MM-dd HH:mm:ss')}"></i>
|
||||
</span>
|
||||
</h2>
|
||||
<div class="layui-colla-content layui-show indexP layui-row" id="indexList">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 42px;color:#4c6978;line-height: 42px;padding-left: 30px;background: #f2f2f2" >
|
||||
|
||||
<a th:href="'/book/indexList-'+${book.id}+'.html'">查看完整目录</a>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div style="position: fixed;top:0px;left:0px;z-index:-100;opacity: 0" th:utext="${attacDivForSearch}"></div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div th:replace="mobile/common/footer :: footer">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
<div th:replace="mobile/common/js :: js">
|
||||
</div>
|
||||
<script>
|
||||
//查询是否在书架
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/user/queryIsInShelf",
|
||||
data: {'bookId': $("#bookIdHidden").val()},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
if (data.data) {
|
||||
$("#cFavs").html("<button type=\"button\" id=\"cFavs\" class=\"layui-btn layui-btn-sm layui-btn-radius layui-btn-warm\">已在书架</button>");
|
||||
}
|
||||
|
||||
|
||||
} else if (data.code == 1001) {
|
||||
//未登录
|
||||
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
//查询最新目录集合
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/book/queryNewIndexList",
|
||||
data: {'bookId': $("#bookIdHidden").val()},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
var indexListHtml = "";
|
||||
for(var i = 0 ; i < data.data.length ; i++){
|
||||
var bookIndex = data.data[i];
|
||||
indexListHtml+=("<p class=\"line-limit-length layui-col-xs12 layui-col-sm4 layui-col-md3 layui-col-lg2\" style=\"padding-left:10px;height: 50px;line-height: 50px;\"><a href=\"/book/"+$("#bookIdHidden").val()+"/"+bookIndex.id+".html\">"+bookIndex.indexName+"</a></p>");
|
||||
}
|
||||
|
||||
$("#indexList").html(indexListHtml);
|
||||
|
||||
|
||||
|
||||
} else if (data.code == 1001) {
|
||||
//未登录
|
||||
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
function addInShell() {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/user/addToBookShelf",
|
||||
data: {'bookId': $("#bookIdHidden").val(), 'preContentId': $("#preContentId").val()},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
$("#cFavs").html("<button type=\"button\" id=\"cFavs\" class=\"layui-btn layui-btn-sm layui-btn-radius layui-btn-warm\">已在书架</button>");
|
||||
|
||||
|
||||
} else if (data.code == 1001) {
|
||||
//未登录
|
||||
location.href = '/user/login.html?originUrl=' + decodeURIComponent(location.href);
|
||||
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$("#content").css("min-height",($(window).height()-60)+"px");
|
||||
|
||||
function downloadFile() {
|
||||
var fileUrl = '/book/download?bookId='+$("#bookIdHidden").val()+'&bookName='+$("#bookNamedHidden").val();
|
||||
window.location.href=fileUrl;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function toMyCollect(){
|
||||
var token = localStorage.getItem("token");
|
||||
if(token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
}else{
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
|
||||
function addToCollect(){
|
||||
var token = localStorage.getItem("token");
|
||||
|
||||
if(token) {
|
||||
$.get("/user/addToCollect",{"bookId":$("#bookIdHidden").val(),"token":token},function(data){
|
||||
layer.alert(data.desc);
|
||||
if(data.code == 1) {
|
||||
$('#collectButton').unbind("click");
|
||||
$("#collectButton").text("撤下书架");
|
||||
$("#collectButton").click(function () {
|
||||
cancelToCollect();
|
||||
});
|
||||
}
|
||||
});
|
||||
}else{
|
||||
window.location.href = "/user/login.html?bookId="+$("#bookIdHidden").val();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function cancelToCollect(){
|
||||
var token = localStorage.getItem("token");
|
||||
|
||||
if(token) {
|
||||
$.get("/user/cancelToCollect",{"bookId":$("#bookIdHidden").val(),"token":token},function(data){
|
||||
layer.alert(data.desc);
|
||||
if(data.code == 1) {
|
||||
$('#collectButton').unbind("click");
|
||||
$("#collectButton").text("加入书架");
|
||||
$("#collectButton").click(function () {
|
||||
addToCollect();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}else{
|
||||
window.location.href = "/user/login.html?bookId="+$("#bookIdHidden").val();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function searchBooks(keyword) {
|
||||
window.location.href = "/book/book_ranking.html?keyword=" + encodeURI(keyword);
|
||||
}
|
||||
|
||||
$.post("/book/addVisitCount", {"bookId": $("#bookIdHidden").val()}, function () {
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
96
templates/dark/html/mobile/book/book_index.html
Normal file
@ -0,0 +1,96 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title th:utext="${book.bookName}+'最新免费章节目录列表'"></title>
|
||||
|
||||
<meta name="keywords" th:content="${book.bookName}+','+${book.bookName}+'最新章节'">
|
||||
|
||||
<meta name="description"
|
||||
th:content="${book.bookName}+'最新章节列表,'+${book.bookName}+'最新更新章节免费无广告无弹窗在线阅读TXT下载。'">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div th:include="mobile/common/css :: css"></div>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
.indexP p a {
|
||||
color: #4c6978;
|
||||
}
|
||||
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="content">
|
||||
<input type="hidden" id="bookIdHidden" th:value="${book.id}"/>
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<a style="color: #ffffff;" th:href="'/book/'+ ${book.id} + '.html'"><b class="layui-icon" th:utext="${book.bookName}"></b></a>
|
||||
<div style="float: right;margin-right: 10px">
|
||||
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p style="height: 30px;line-height: 30px;padding: 10px">
|
||||
|
||||
<a href="#buttom" style="color: red"> ↓直达页面底部</a>
|
||||
</p>
|
||||
|
||||
|
||||
<div class="layui-colla-content layui-show indexP layui-row">
|
||||
<p class="line-limit-length layui-col-xs12 layui-col-sm4 layui-col-md3 layui-col-lg2" style="padding-left:10px;height: 50px;line-height: 50px;" th:each="index : ${bookIndexList}">
|
||||
<a th:href="'/book/'+${index.bookId}+'/'+${index.id}+'.html'" th:utext="${index.indexName}">
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div th:replace="mobile/common/footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
<div th:replace="mobile/common/js :: js">
|
||||
</div>
|
||||
<script>
|
||||
$("#content").css("min-height",($(window).height()-60)+"px");
|
||||
$.get("/book/addVisit",{"bookId":$("#bookIdHidden").val()},function(){});
|
||||
function toMyCollect(){
|
||||
var token = localStorage.getItem("token");
|
||||
if(token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
}else{
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
320
templates/dark/html/mobile/book/book_ranking.html
Normal file
@ -0,0 +1,320 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title th:text="#{website.name}+'列表'"></title>
|
||||
|
||||
<meta name="keywords"
|
||||
th:content="#{website.name}+',精品小说,弹幕网站,弹幕,弹幕小说网站,免费小说,小说阅读,小说排行,轻小说,txt小说下载,电子书下载,动漫轻小说,日本轻小说'">
|
||||
|
||||
<meta name="description"
|
||||
th:content="#{website.name}+'是国内优秀的小说弹幕网站,'+#{website.name}+'提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。'">
|
||||
|
||||
|
||||
<div th:include="mobile/common/css :: css"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
.indexP p a {
|
||||
color: #4c6978;
|
||||
}
|
||||
|
||||
.Readarea {
|
||||
font-size: 18px;
|
||||
line-height: 35px;
|
||||
padding: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
div, p {
|
||||
wrap-work: break-word;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
word-break: normal;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.indexDiv a {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 130px;
|
||||
height: 180px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<input type="hidden" id="limit" th:value="${limit}"/>
|
||||
<input type="hidden" id="curr" th:value="${curr}"/>
|
||||
<input type="hidden" id="total" th:value="${total}"/>
|
||||
<input type="hidden" id="ids" th:value="${ids}"/>
|
||||
<input type="hidden" id="bookStatus" th:value="${bookStatus}"/>
|
||||
<input type="hidden" id="token" th:value="${token}"/>
|
||||
<input type="hidden" id="keyword" th:value="${keyword}"/>
|
||||
<input type="hidden" id="catId" th:value="${catId}"/>
|
||||
<input type="hidden" id="sortBy" th:value="${sortBy}"/>
|
||||
<input type="hidden" id="sort" th:value="${sort}"/>
|
||||
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<b class="layui-icon">小说列表</b>
|
||||
<div style="float: right;margin-right: 10px">
|
||||
<a href="/"><i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-container">
|
||||
<div class="layui-row">
|
||||
|
||||
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
|
||||
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
|
||||
autocomplete="off"
|
||||
class="layui-input" th:value="${keyword}">
|
||||
</div>
|
||||
<div class="layui-col-xs1" style="padding: 1%">
|
||||
<button onclick="search(1,20)" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="bookList">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="books" style="text-align: center"></div>
|
||||
|
||||
|
||||
<div th:replace="mobile/common/footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
|
||||
<div th:replace="mobile/common/js :: js"></div>
|
||||
|
||||
<script>
|
||||
|
||||
var catId = getQueryVariable("catId");
|
||||
var bookStatus = getQueryVariable("bookStatus");
|
||||
var sortBy = getQueryVariable("sortBy");
|
||||
var keyword = getQueryVariable("keyword");
|
||||
|
||||
if(keyword != false){
|
||||
$("#title").val(decodeURI(keyword));
|
||||
}else{
|
||||
keyword = "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
search(1,20);
|
||||
|
||||
function search(curr,limit) {
|
||||
|
||||
|
||||
|
||||
var searchData = {};
|
||||
|
||||
searchData.curr = curr;
|
||||
searchData.limit = limit;
|
||||
|
||||
keyword = $("#title").val();
|
||||
|
||||
if(catId != false){
|
||||
searchData.catId = catId;
|
||||
}
|
||||
|
||||
if(bookStatus != false){
|
||||
searchData.bookStatus = bookStatus;
|
||||
}
|
||||
|
||||
if(sortBy != false){
|
||||
searchData.sort = sortBy;
|
||||
}else if(!keyword){
|
||||
sortBy = "last_index_update_time";
|
||||
}
|
||||
|
||||
if(keyword){
|
||||
searchData.keyword = keyword;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/book/searchByPage",
|
||||
data: searchData,
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
var bookList = data.data.list;
|
||||
var bookListHtml = "";
|
||||
for (var i = 0; i < bookList.length; i++) {
|
||||
var book = bookList[i];
|
||||
|
||||
/*var end = book.bookDesc.indexOf("<");
|
||||
if(end != -1) {
|
||||
book.bookDesc = book.bookDesc.substring(0,end);
|
||||
}*/
|
||||
|
||||
if(book.bookDesc){
|
||||
book.bookDesc = book.bookDesc.replace(/<[^>]+>/g,"").replace(/\s+/g,"").replace(/ /g,"");
|
||||
}
|
||||
|
||||
bookListHtml += ("<div class=\"layui-row\" style=\"margin-bottom:10px;padding:10px;background: #f2f2f2\">\n" +
|
||||
" <a href=\"/book/"+book.id+".html\">\n" +
|
||||
" <div class=\"layui-col-xs6 layui-col-sm3 layui-col-md2 layui-col-lg2\" style=\"text-align: center\">\n" +
|
||||
" <img width='150' height='180' align=\"center\"\n" +
|
||||
" src=\""+book.picUrl+"\"/>\n" +
|
||||
"\n" +
|
||||
" </div>\n" +
|
||||
" </a>\n" +
|
||||
" <div style=\"padding: 10px\" class=\"layui-col-xs6 layui-col-sm8 layui-col-md8 layui-col-lg8\">\n" +
|
||||
" <a href=\"/book/"+book.id+".html\">\n" +
|
||||
" <div class=\"line-limit-length\" style=\";color: #4c6978;font-weight: bold;font-size: 15px\">"+book.bookName+"</div>\n" +
|
||||
" </a>\n" +
|
||||
" <div style=\";color: #4c6978;float: right;\"><i style=\"color: red\"></i></div>\n" +
|
||||
" <a href=\"/book/book_ranking.html?keyword="+encodeURI(book.authorName)+"\">\n" +
|
||||
" <div style=\";color: #4c6978;\" class=\"line-limit-length\">作者:"+book.authorName+"</div>\n" +
|
||||
" </a>\n" +
|
||||
" <div style=\"margin-top: 5px;color: #4c6978;\">类别:"+book.catName+"</div>\n" +
|
||||
" <div style=\"margin-top: 5px;color: #4c6978;\">状态:"+(book.bookStatus==0?'连载':'完结')+"</div>\n" +
|
||||
" <div style=\"margin-top: 5px;color: #4c6978;\">更新:<i>"+book.lastIndexUpdateTime.substr(0,11)+"</i>\n" +
|
||||
" </div>\n" +
|
||||
" <div style=\"margin-top: 5px;color: #4c6978;\">简介:"+(book.bookDesc?(book.bookDesc.length>20?(book.bookDesc.substr(0,20)+"..."):book.bookDesc):book.bookDesc)+"</div>\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
" </div>\n" +
|
||||
"\n" +
|
||||
" </div>");
|
||||
}
|
||||
$("#bookList").html(bookListHtml);
|
||||
|
||||
layui.use('laypage', function () {
|
||||
var laypage = layui.laypage;
|
||||
|
||||
//执行一个laypage实例
|
||||
laypage.render({
|
||||
elem: 'books' //注意,这里的 test1 是 ID,不用加 # 号
|
||||
, count: data.data.total //数据总数,从服务端得到,
|
||||
, curr: data.data.pageNum
|
||||
, limit: data.data.pageSize
|
||||
, jump: function (obj, first) {
|
||||
|
||||
|
||||
//obj包含了当前分页的所有参数,比如:
|
||||
console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。
|
||||
console.log(obj.limit); //得到每页显示的条数
|
||||
|
||||
|
||||
//首次不执行
|
||||
if (!first) {
|
||||
search(obj.curr, obj.limit);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function searchByAllCondition(curr, limit, newKeyword) {
|
||||
var toUrl = "/book/search?curr=" + curr + "&limit=" + limit;
|
||||
var ids = $("#ids").val();
|
||||
if (ids) {
|
||||
toUrl += ("&historyBookIds=" + ids);
|
||||
}
|
||||
var token = $("#token").val();
|
||||
if (token) {
|
||||
toUrl += ("&token=" + token);
|
||||
}
|
||||
var keyword = $("#keyword").val();
|
||||
if (newKeyword) {
|
||||
toUrl += encodeURI("&keyword=" + newKeyword);
|
||||
} else if (keyword) {
|
||||
toUrl += encodeURI("&keyword=" + keyword);
|
||||
}
|
||||
var bookStatus = $("#bookStatus").val();
|
||||
if (bookStatus) {
|
||||
toUrl += ("&bookStatus=" + bookStatus);
|
||||
}
|
||||
var catId = $("#catId").val();
|
||||
if (catId) {
|
||||
toUrl += ("&catId=" + catId);
|
||||
}
|
||||
|
||||
var sortBy = $("#sortBy").val();
|
||||
if (sortBy) {
|
||||
toUrl += ("&sortBy=" + sortBy);
|
||||
}
|
||||
|
||||
var sort = $("#sort").val();
|
||||
if (sort) {
|
||||
toUrl += ("&sort=" + sort);
|
||||
}
|
||||
|
||||
window.location.href = toUrl;
|
||||
}
|
||||
|
||||
function searchBooks() {
|
||||
var keywords = $("#title").val();
|
||||
$("#keyword").val("");
|
||||
searchByAllCondition(1, 20, keywords);
|
||||
}
|
||||
|
||||
</script>
|
||||
<script>
|
||||
|
||||
|
||||
|
||||
|
||||
function toMyCollect() {
|
||||
var token = localStorage.getItem("token");
|
||||
if (token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
} else {
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
88
templates/dark/html/mobile/book/book_submit.html
Normal file
@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>小说提交</title>
|
||||
|
||||
<div th:include="common/css :: css"></div>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body id="read" >
|
||||
|
||||
</div>
|
||||
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<b class="layui-icon">单本小说提交</b>
|
||||
<div style="float: right;margin-right: 10px"><a href="/">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 800px;padding: 20px;border: 1px solid #eee;">
|
||||
<form class="layui-form" action="">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">详情页Url:</label>
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1" >
|
||||
<input type="text" id="bookUrl" name="bookUrl" required lay-verify="required" placeholder="请输入源站小说详情页Url" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小说名:</label>
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1" >
|
||||
<input type="text" id="bookName" name="bookName" required lay-verify="required" placeholder="请输入小说名" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小说评分:</label>
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1">
|
||||
<input type="number" id="score" name="score" required lay-verify="required" placeholder="请输入小说评分" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit lay-filter="formDemo">提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div th:replace="common/footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
<div th:replace="common/js :: js"></div>
|
||||
|
||||
|
||||
<script>
|
||||
//Demo
|
||||
layui.use('form', function(){
|
||||
var form = layui.form;
|
||||
|
||||
//监听提交
|
||||
form.on('submit(formDemo)', function(){
|
||||
$.post("/book/submit",{"bookUrl":$("#bookUrl").val(),"bookName":$("#bookName").val(),"score":$("#score").val()},function (data) {
|
||||
if(data.code == 1 ){
|
||||
layer.alert("提交成功,任务排队中,请过一段时间后再搜索查看");
|
||||
}else{
|
||||
layer.alert("提交失败");
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
270
templates/dark/html/mobile/book/mh_book_search.html
Normal file
@ -0,0 +1,270 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title th:text="${application.seoConfig.page['mh-search.title']}"></title>
|
||||
|
||||
<meta name="keywords" th:content="${application.seoConfig.page['mh-search.keyword']}">
|
||||
|
||||
<meta name="description"
|
||||
th:content="${application.seoConfig.page['mh-search.description']}">
|
||||
|
||||
<div th:include="common/css :: css"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
.indexP p a {
|
||||
color: #4c6978;
|
||||
}
|
||||
|
||||
.Readarea {
|
||||
font-size: 18px;
|
||||
line-height: 35px;
|
||||
padding: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
div, p {
|
||||
wrap-work: break-word;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
word-break: normal;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.indexDiv a {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 147px;
|
||||
height: 197px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<input type="hidden" id="limit" th:value="${limit}"/>
|
||||
<input type="hidden" id="curr" th:value="${curr}"/>
|
||||
<input type="hidden" id="total" th:value="${total}"/>
|
||||
<input type="hidden" id="ids" th:value="${ids}"/>
|
||||
<input type="hidden" id="keyword" th:value="${keyword}"/>
|
||||
<input type="hidden" id="softTag" th:value="${softTag}"/>
|
||||
<input type="hidden" id="sortBy" th:value="${sortBy}"/>
|
||||
<input type="hidden" id="sort" th:value="${sort}"/>
|
||||
<input type="hidden" id="bookStatus" th:value="${bookStatus}"/>
|
||||
<input type="hidden" id="softCat" th:value="${softCat}"/>
|
||||
|
||||
<ul class="layui-nav" lay-filter="" style="padding:0 20px;text-align: center" >
|
||||
<li id="menunew" class="layui-nav-item"><a href="/book/searchSoftBook.html?catId=9">最新</a></li>
|
||||
<li id="menu21" class="layui-nav-item"><a href="/book/searchSoftBook.html?catId=9&softCat=3262">少年漫</a></li>
|
||||
<li id="menu22" class="layui-nav-item"><a href="/book/searchSoftBook.html?catId=9&softCat=3263">少女漫</a></li>
|
||||
<li id="menucomplete" class="layui-nav-item"><a >完本</a>
|
||||
<dl class="layui-nav-child"> <!-- 二级菜单 -->
|
||||
<dd><a href="/book/searchSoftBook.html?catId=9&bookStatus=已完成">全部</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?catId=9&bookStatus=已完成&softCat=3262">少年漫</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?catId=9&bookStatus=已完成&softCat=3263">少女漫</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li id="menuhot" class="layui-nav-item"><a >排行</a>
|
||||
<dl class="layui-nav-child"> <!-- 二级菜单 -->
|
||||
<dd><a href="/book/searchSoftBook.html?catId=9&sortBy=score">全部</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?catId=9&sortBy=score&softCat=3262">少年漫</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?catId=9&bookStatus=已完成&softCat=3263">少女漫</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<div class="layui-container">
|
||||
<div class="layui-row">
|
||||
|
||||
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
|
||||
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
|
||||
autocomplete="off"
|
||||
class="layui-input" th:value="${keyword}">
|
||||
</div>
|
||||
<div class="layui-col-xs1" style="padding: 1%">
|
||||
<button onclick="searchBooks()" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div th:each="book : ${books}" class="layui-row" style="margin-bottom:10px;padding:10px;background: #f2f2f2">
|
||||
<a th:href="'/book/'+ ${book.id} + '.html'">
|
||||
<div class="layui-col-xs6 layui-col-sm3 layui-col-md2 layui-col-lg2" style="text-align: center" th:switch = "${application.noLazy}">
|
||||
<img th:case="'1'" align="center"
|
||||
th:attr="data-src=${book.picUrl}"/>
|
||||
<img th:case="*" align="center"
|
||||
class="lazyload" th:attr="data-src=${book.picUrl}"/>
|
||||
</div>
|
||||
</a>
|
||||
<div style="padding: 20px" class="layui-col-xs6 layui-col-sm8 layui-col-md8 layui-col-lg8">
|
||||
<a th:href="'/book/'+ ${book.id} + '.html'">
|
||||
<div class="line-limit-length" style=";color: #4c6978;font-weight: bold;font-size: 15px"
|
||||
th:text="${book.bookName}"></div>
|
||||
</a>
|
||||
<div style=";color: #4c6978;float: right;"><i style="color: red" th:text="${book.score} + '分'"></i></div>
|
||||
<a th:href="'/book/searchSoftBook.html?catId=9&keyword='+ ${book.author}">
|
||||
<div style=";color: #4c6978;" class="line-limit-length" th:text="'作者:'+ ${book.author}"></div>
|
||||
</a>
|
||||
<div style="margin-top: 5px;color: #4c6978;" th:text="'类别:'+ ${book.cateName}"></div>
|
||||
<div style="margin-top: 5px;color: #4c6978;" th:text="'状态:'+ ${book.bookStatus}"></div>
|
||||
<div style="margin-top: 5px;color: #4c6978;">更新:<i th:text="${#dates.format(book.updateTime, 'yy-MM-dd')}"></i>
|
||||
</div>
|
||||
<div class="layui-collapse" style="margin-top: 5px;">
|
||||
<div class="layui-colla-item">
|
||||
<h2 style="color: #4c6978;" class="layui-colla-title">简介:</h2>
|
||||
<div style="color: #4c6978;" class="layui-colla-content" th:utext="${book.bookDesc}">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="books" style="text-align: center"></div>
|
||||
|
||||
|
||||
<div th:replace="common/soft_footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
|
||||
<div th:replace="common/js :: js"></div>
|
||||
<script src="/js/lazyload.js"></script>
|
||||
|
||||
<script>
|
||||
lazyload();
|
||||
layui.use('laypage', function () {
|
||||
var laypage = layui.laypage;
|
||||
|
||||
//执行一个laypage实例
|
||||
laypage.render({
|
||||
elem: 'books' //注意,这里的 test1 是 ID,不用加 # 号
|
||||
, count: $("#total").val() //数据总数,从服务端得到,
|
||||
, curr: $("#curr").val()
|
||||
, limit: $("#limit").val()
|
||||
, jump: function (obj, first) {
|
||||
|
||||
|
||||
//obj包含了当前分页的所有参数,比如:
|
||||
console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。
|
||||
console.log(obj.limit); //得到每页显示的条数
|
||||
|
||||
|
||||
//首次不执行
|
||||
if (!first) {
|
||||
searchByAllCondition(obj.curr,obj.limit);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function searchByAllCondition(curr,limit,newKeyword){
|
||||
var toUrl = "/book/searchSoftBook.html?catId=9&curr=" + curr + "&limit=" + limit;
|
||||
var ids = $("#ids").val();
|
||||
if(ids){
|
||||
toUrl += ("&historyBookIds=" + ids);
|
||||
}
|
||||
var keyword = $("#keyword").val();
|
||||
if(newKeyword){
|
||||
toUrl += encodeURI("&keyword=" + newKeyword);
|
||||
}else if (keyword) {
|
||||
toUrl += encodeURI("&keyword=" + keyword);
|
||||
}
|
||||
var bookStatus = $("#bookStatus").val();
|
||||
if(bookStatus){
|
||||
toUrl += ("&bookStatus=" + bookStatus);
|
||||
}
|
||||
var softCat = $("#softCat").val();
|
||||
if (softCat) {
|
||||
toUrl += ("&softCat=" + softCat);
|
||||
}
|
||||
var softTag = $("#softTag").val();
|
||||
if (softTag) {
|
||||
toUrl += ("&softTag=" + softTag);
|
||||
}
|
||||
|
||||
var sortBy = $("#sortBy").val();
|
||||
if (sortBy) {
|
||||
toUrl += ("&sortBy=" + sortBy);
|
||||
}
|
||||
|
||||
var sort = $("#sort").val();
|
||||
if (sort) {
|
||||
toUrl += ("&sort=" + sort);
|
||||
}
|
||||
|
||||
window.location.href = toUrl;
|
||||
}
|
||||
|
||||
function searchBooks() {
|
||||
var keywords = $("#title").val();
|
||||
$("#keyword").val("");
|
||||
searchByAllCondition(1,20,keywords);
|
||||
}
|
||||
|
||||
</script>
|
||||
<script>
|
||||
(function(){
|
||||
|
||||
|
||||
var sortCat = $("#softCat").val();
|
||||
var sortBy = $("#sortBy").val();
|
||||
if(sortBy == 'score'){
|
||||
$("#menuhot").addClass("layui-this");
|
||||
}else if($("#bookStatus").val()){
|
||||
$("#menucomplete").addClass("layui-this");
|
||||
}else if(sortCat){
|
||||
$("#menu"+sortCat).addClass("layui-this");
|
||||
}else{
|
||||
$("#menunew").addClass("layui-this");
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
|
||||
function toMyCollect(){
|
||||
var token = localStorage.getItem("token");
|
||||
if(token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
}else{
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</html>
|
294
templates/dark/html/mobile/book/soft_book_search.html
Normal file
@ -0,0 +1,294 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title th:text="${application.seoConfig.page['soft-search.title']}"></title>
|
||||
|
||||
<meta name="keywords" th:content="${application.seoConfig.page['soft-search.keyword']}">
|
||||
|
||||
<meta name="description"
|
||||
th:content="${application.seoConfig.page['soft-search.description']}">
|
||||
|
||||
<div th:include="common/css :: css"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
.indexP p a {
|
||||
color: #4c6978;
|
||||
}
|
||||
|
||||
.Readarea {
|
||||
font-size: 18px;
|
||||
line-height: 35px;
|
||||
padding: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
div, p {
|
||||
wrap-work: break-word;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
word-break: normal;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.indexDiv a {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 147px;
|
||||
height: 197px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<input type="hidden" id="limit" th:value="${limit}"/>
|
||||
<input type="hidden" id="curr" th:value="${curr}"/>
|
||||
<input type="hidden" id="total" th:value="${total}"/>
|
||||
<input type="hidden" id="ids" th:value="${ids}"/>
|
||||
<input type="hidden" id="keyword" th:value="${keyword}"/>
|
||||
<input type="hidden" id="softTag" th:value="${softTag}"/>
|
||||
<input type="hidden" id="sortBy" th:value="${sortBy}"/>
|
||||
<input type="hidden" id="sort" th:value="${sort}"/>
|
||||
<input type="hidden" id="bookStatus" th:value="${bookStatus}"/>
|
||||
<input type="hidden" id="softCat" th:value="${softCat}"/>
|
||||
|
||||
<ul class="layui-nav" lay-filter="" style="padding:0 20px;text-align: center">
|
||||
<li id="menunew" class="layui-nav-item"><a href="/book/searchSoftBook.html">最新</a></li>
|
||||
<li id="menu21" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=21">魔幻</a></li>
|
||||
<li id="menu22" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=22">玄幻</a></li>
|
||||
<li id="menu23" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=23">古风</a></li>
|
||||
<li id="menu24" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=24">科幻</a></li>
|
||||
<li id="menu25" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=25">校园</a></li>
|
||||
<li id="menu26" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=26">都市</a></li>
|
||||
<li id="menu27" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=27">游戏</a></li>
|
||||
<li id="menu28" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=28">同人</a></li>
|
||||
<li id="menu29" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=29">悬疑</a></li>
|
||||
<li id="menu0" class="layui-nav-item"><a href="/book/searchSoftBook.html?softCat=0">动漫</a></li>
|
||||
<li id="menucomplete" class="layui-nav-item"><a>完本</a>
|
||||
<dl class="layui-nav-child"> <!-- 二级菜单 -->
|
||||
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成">全部</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=21">魔幻</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=22">玄幻</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=23">古风</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=24">科幻</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=25">校园</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=26">都市</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=27">游戏</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=28">同人</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=29">悬疑</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?bookStatus=已完成&softCat=0">动漫</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li id="menuhot" class="layui-nav-item"><a>排行</a>
|
||||
<dl class="layui-nav-child"> <!-- 二级菜单 -->
|
||||
<dd><a href="/book/searchSoftBook.html?sortBy=score">全部</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=21">魔幻</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=22">玄幻</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=23">古风</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=24">科幻</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=25">校园</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=26">都市</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=27">游戏</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=28">同人</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=29">悬疑</a></dd>
|
||||
<dd><a href="/book/searchSoftBook.html?sortBy=score&softCat=0">动漫</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<div class="layui-container">
|
||||
<div class="layui-row">
|
||||
|
||||
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
|
||||
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
|
||||
autocomplete="off"
|
||||
class="layui-input" th:value="${keyword}">
|
||||
</div>
|
||||
<div class="layui-col-xs1" style="padding: 1%">
|
||||
<button onclick="searchBooks()" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div th:each="book : ${books}" class="layui-row" style="margin-bottom:10px;padding:10px;background: #f2f2f2">
|
||||
<a th:href="'/book/'+ ${book.id} + '.html'">
|
||||
<div class="layui-col-xs6 layui-col-sm3 layui-col-md2 layui-col-lg2" style="text-align: center"
|
||||
th:switch="${application.noLazy}">
|
||||
<img th:case="'1'" align="center"
|
||||
th:attr="data-src=${book.picUrl}"/>
|
||||
<img th:case="*" align="center"
|
||||
class="lazyload" th:attr="data-src=${book.picUrl}"/>
|
||||
</div>
|
||||
</a>
|
||||
<div style="padding: 20px" class="layui-col-xs6 layui-col-sm8 layui-col-md8 layui-col-lg8">
|
||||
<a th:href="'/book/'+ ${book.id} + '.html'">
|
||||
<div class="line-limit-length" style=";color: #4c6978;font-weight: bold;font-size: 15px"
|
||||
th:text="${book.bookName}"></div>
|
||||
</a>
|
||||
<div style=";color: #4c6978;float: right;"><i style="color: red" th:text="${book.score} + '分'"></i></div>
|
||||
<a th:href="'/book/searchSoftBook.html?keyword='+ ${book.author}">
|
||||
<div style=";color: #4c6978;" class="line-limit-length" th:text="'作者:'+ ${book.author}"></div>
|
||||
</a>
|
||||
<div style="margin-top: 5px;color: #4c6978;" th:text="'类别:'+ ${book.cateName}"></div>
|
||||
<div style="margin-top: 5px;color: #4c6978;" th:text="'状态:'+ ${book.bookStatus}"></div>
|
||||
<div style="margin-top: 5px;color: #4c6978;">更新:<i th:text="${#dates.format(book.updateTime, 'yy-MM-dd')}"></i>
|
||||
</div>
|
||||
<div class="layui-collapse" style="margin-top: 5px;">
|
||||
<div class="layui-colla-item">
|
||||
<h2 style="color: #4c6978;" class="layui-colla-title">简介:</h2>
|
||||
<div style="color: #4c6978;" class="layui-colla-content" th:utext="${book.bookDesc}">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="books" style="text-align: center"></div>
|
||||
|
||||
|
||||
<div th:replace="common/soft_footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
|
||||
<div th:replace="common/js :: js"></div>
|
||||
<script src="/js/lazyload.js"></script>
|
||||
|
||||
<script>
|
||||
lazyload();
|
||||
layui.use('laypage', function () {
|
||||
var laypage = layui.laypage;
|
||||
|
||||
//执行一个laypage实例
|
||||
laypage.render({
|
||||
elem: 'books' //注意,这里的 test1 是 ID,不用加 # 号
|
||||
, count: $("#total").val() //数据总数,从服务端得到,
|
||||
, curr: $("#curr").val()
|
||||
, limit: $("#limit").val()
|
||||
, jump: function (obj, first) {
|
||||
|
||||
|
||||
//obj包含了当前分页的所有参数,比如:
|
||||
console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。
|
||||
console.log(obj.limit); //得到每页显示的条数
|
||||
|
||||
|
||||
//首次不执行
|
||||
if (!first) {
|
||||
searchByAllCondition(obj.curr, obj.limit);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function searchByAllCondition(curr, limit, newKeyword) {
|
||||
var toUrl = "/book/searchSoftBook.html?curr=" + curr + "&limit=" + limit;
|
||||
var ids = $("#ids").val();
|
||||
if (ids) {
|
||||
toUrl += ("&historyBookIds=" + ids);
|
||||
}
|
||||
var keyword = $("#keyword").val();
|
||||
if (newKeyword) {
|
||||
toUrl += encodeURI("&keyword=" + newKeyword);
|
||||
} else if (keyword) {
|
||||
toUrl += encodeURI("&keyword=" + keyword);
|
||||
}
|
||||
var bookStatus = $("#bookStatus").val();
|
||||
if (bookStatus) {
|
||||
toUrl += ("&bookStatus=" + bookStatus);
|
||||
}
|
||||
var softCat = $("#softCat").val();
|
||||
if (softCat) {
|
||||
toUrl += ("&softCat=" + softCat);
|
||||
}
|
||||
var softTag = $("#softTag").val();
|
||||
if (softTag) {
|
||||
toUrl += ("&softTag=" + softTag);
|
||||
}
|
||||
|
||||
var sortBy = $("#sortBy").val();
|
||||
if (sortBy) {
|
||||
toUrl += ("&sortBy=" + sortBy);
|
||||
}
|
||||
|
||||
var sort = $("#sort").val();
|
||||
if (sort) {
|
||||
toUrl += ("&sort=" + sort);
|
||||
}
|
||||
|
||||
window.location.href = toUrl;
|
||||
}
|
||||
|
||||
function searchBooks() {
|
||||
var keywords = $("#title").val();
|
||||
$("#keyword").val("");
|
||||
searchByAllCondition(1, 20, keywords);
|
||||
}
|
||||
|
||||
</script>
|
||||
<script>
|
||||
(function () {
|
||||
|
||||
|
||||
var sortCat = $("#softCat").val();
|
||||
var sortBy = $("#sortBy").val();
|
||||
if (sortBy == 'score') {
|
||||
$("#menuhot").addClass("layui-this");
|
||||
} else if ($("#bookStatus").val()) {
|
||||
$("#menucomplete").addClass("layui-this");
|
||||
} else if (sortCat) {
|
||||
$("#menu" + sortCat).addClass("layui-this");
|
||||
} else {
|
||||
$("#menunew").addClass("layui-this");
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
|
||||
function toMyCollect() {
|
||||
var token = localStorage.getItem("token");
|
||||
if (token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
} else {
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
24
templates/dark/html/mobile/common/css.html
Normal file
@ -0,0 +1,24 @@
|
||||
<div th:fragment="css">
|
||||
<link rel="stylesheet" href="/mobile/layui/css/layui.css">
|
||||
<style type="text/css">
|
||||
.app {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.app {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.pc {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.pc {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</div>
|
11
templates/dark/html/mobile/common/footer.html
Normal file
@ -0,0 +1,11 @@
|
||||
<div th:fragment="footer" style="height: 60px;line-height: 60px;text-align: center" class="layui-footer footer footer-demo layui-bg-cyan">
|
||||
<!--<a href="/mobile/book/searchSoftBook.html" style="font-size: 14px;color: #92B8B1;">轻小说</a>
|
||||
<a href="/mobile/book/searchSoftBook.html?catId=9" style="font-size: 14px;color: #92B8B1;margin-left: 8px">漫画</a>-->
|
||||
<a href="/?to=pc" style="font-size: 14px;color: #92B8B1;margin-left: 8px">电脑站</a>
|
||||
<!--<a href="https://www.zinglizingli.xyz/me/index.html" style="font-size: 14px;color: #92B8B1;margin-left: 8px">开发者</a>-->
|
||||
|
||||
|
||||
<div style="float: right"><a href="#top"><i class="layui-icon"
|
||||
style="margin-right:15px;font-size: 30px;color:#92B8B1 "></i></a>
|
||||
</div>
|
||||
</div>
|
3
templates/dark/html/mobile/common/js.html
Normal file
@ -0,0 +1,3 @@
|
||||
<script th:fragment="js" src="/mobile/js/jquery-1.9.1.js"></script>
|
||||
<script th:fragment="js" src="/mobile/js/common.js"></script>
|
||||
<script th:fragment="js" src="/mobile/layui/layui.all.js"></script>
|
19
templates/dark/html/mobile/common/soft_footer.html
Normal file
@ -0,0 +1,19 @@
|
||||
<div th:fragment="footer" style="height: 60px;line-height: 60px;text-align: center" class="layui-footer footer footer-demo layui-bg-cyan">
|
||||
<a href="/book" style="font-size: 14px;color: #92B8B1;">更多小说</a>
|
||||
<a href="javascript:readHistory()" style="font-size: 14px;color: #92B8B1;margin-left: 8px">阅读记录</a>
|
||||
<a href="javascript:toMyCollect()" style="font-size: 14px;color: #92B8B1;margin-left: 8px">书架</a>
|
||||
<a href="/mobile/HotBook.apk" style="font-size: 14px;color: #92B8B1;margin-left: 8px">客户端</a>
|
||||
<!--<a href="https://www.zinglizingli.xyz/me/index.html" style="font-size: 14px;color: #92B8B1;margin-left: 8px">开发者</a>-->
|
||||
|
||||
|
||||
<div style="float: right"><a href="#top"><i class="layui-icon"
|
||||
style="margin-right:15px;font-size: 30px;color:#92B8B1 "></i></a>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
var src = (document.location.protocol == "http:") ? "http://js.passport.qihucdn.com/11.0.1.js?0acfeb0f37ba0d8942c2bbf459016f21":"https://jspassport.ssl.qhimg.com/11.0.1.js?0acfeb0f37ba0d8942c2bbf459016f21";
|
||||
document.write('<script src="' + src + '" id="sozz"><\/script>');
|
||||
})();
|
||||
</script>
|
||||
</div>
|
388
templates/dark/html/mobile/index.html
Normal file
@ -0,0 +1,388 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
|
||||
|
||||
<title th:text="#{website.name}"></title>
|
||||
|
||||
<meta name="keywords" th:content="#{website.name}+',精品小说,弹幕网站,弹幕,弹幕小说网站,免费小说,小说阅读,小说排行,轻小说,txt小说下载,电子书下载,动漫轻小说,日本轻小说'">
|
||||
|
||||
<meta name="description"
|
||||
th:content="#{website.name}+'是国内优秀的小说弹幕网站,'+#{website.name}+'提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。'">
|
||||
|
||||
<meta property="og:type" content="novel_index"/>
|
||||
<meta property="og:title" th:content="#{website.name}"/>
|
||||
<meta property="og:description"
|
||||
th:content="#{website.name}+'是国内优秀的小说弹幕网站,'+#{website.name}+'提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。'"/>
|
||||
|
||||
|
||||
<div th:include="mobile/common/css :: css"></div>
|
||||
|
||||
<style>
|
||||
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
.layui-nav .layui-nav-item {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
body ul.layui-nav li.layui-nav-item a {
|
||||
display: block;
|
||||
transition: all .3s;
|
||||
-webkit-transition: all .3s;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<!-- 你的HTML代码 -->
|
||||
<a name="top"></a>
|
||||
<ul class="layui-nav app" lay-filter="" style="display:none;padding:0 10px;text-align: center">
|
||||
<li class="layui-nav-item"><a>分类</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a href="/book/book_ranking.html?catId=1&sort=last_index_update_time">玄幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=2&sort=last_index_update_time">修真小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=3&sort=last_index_update_time">都市小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=4&sort=last_index_update_time">历史小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=6&sort=last_index_update_time">网游小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=5&sort=last_index_update_time">科幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?catId=7&sort=last_index_update_time">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="layui-nav-item"><a>全本</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1">全部小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=1">玄幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=2">修真小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=3">都市小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=4">历史小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=6">网游小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=5">科幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=7">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="layui-nav-item"><a>排行</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count">全部小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=1">玄幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=2">修真小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=3">都市小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=4">历史小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=6">网游小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=5">科幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=7">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<ul class="layui-nav pc" lay-filter="" style="padding:0 36px;text-align: center">
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=1&sort=last_index_update_time">玄幻小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=2&sort=last_index_update_time">修真小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=3&sort=last_index_update_time">都市小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=4&sort=last_index_update_time">历史小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=6&sort=last_index_update_time">网游小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=5&sort=last_index_update_time">科幻小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/book_ranking.html?catId=7&sort=last_index_update_time">女频小说</a></li>
|
||||
<li class="layui-nav-item"><a>完本小说</a>
|
||||
<dl class="layui-nav-child"> <!-- 二级菜单 -->
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1">全部小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=1">玄幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=2">修真小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=3">都市小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=4">历史小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=6">网游小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=5">科幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?bookStatus=1&catId=7">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="layui-nav-item"><a>小说排行</a>
|
||||
<dl class="layui-nav-child"> <!-- 二级菜单 -->
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count">全部小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=1">玄幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=2">修真小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=3">都市小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=4">历史小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=6">网游小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=5">科幻小说</a></dd>
|
||||
<dd><a href="/book/book_ranking.html?sortBy=visit_count&catId=7">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="layui-container">
|
||||
<div class="layui-row">
|
||||
|
||||
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
|
||||
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
|
||||
autocomplete="off"
|
||||
class="layui-input">
|
||||
</div>
|
||||
<div class="layui-col-xs1" style="padding: 1%">
|
||||
<button onclick="searchBooks()" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="height: 1px" class="layui-col-lg1"></div>
|
||||
<div class="layui-collapse layui-col-lg10">
|
||||
<div class="layui-colla-item">
|
||||
<h2 class="layui-colla-title">本站推荐</h2>
|
||||
<div class="layui-colla-content layui-show">
|
||||
|
||||
|
||||
<div class="layui-container" style="padding: 0px">
|
||||
|
||||
<div class="layui-row" style="text-align: center" id="currentWeek">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-colla-item">
|
||||
<h2 class="layui-colla-title">热门小说推荐</h2>
|
||||
<div class="layui-colla-content layui-show">
|
||||
|
||||
<div class="layui-container">
|
||||
<div class="layui-row" id="hotRecBooks">
|
||||
|
||||
|
||||
<!--<div th:each="hotBook : ${hotBooks}" style="margin-top: 1%"
|
||||
class="layui-col-xs12 layui-col-sm6 layui-col-md6 layui-col-lg6">
|
||||
<a th:href="'/book/'+${hotBook.id}+'.html'">
|
||||
<div class="layui-col-xs5 layui-col-sm3 layui-col-md3 layui-col-lg3">
|
||||
<img style=" width:100px; height:125px;"
|
||||
th:src="${hotBook.picUrl}"/>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md7 layui-col-lg7"
|
||||
style="float: left;padding-right: 10px">
|
||||
<div><b th:text="${hotBook.bookName}"></b></div>
|
||||
<div class="layui-col-xs8 layui-col-sm9 layui-col-md10 layui-col-lg10"
|
||||
th:text="'作者:'+ ${hotBook.author}"></div>
|
||||
<div class="layui-col-xs3 layui-col-sm2 layui-col-md1 layui-col-lg1" style="text-align: right;">
|
||||
<b><i style="color: red"
|
||||
th:text="${hotBook.score} + '分'"></i></b></div>
|
||||
</div>
|
||||
<div class="layui-elip layui-col-xs12 layui-col-sm9 layui-col-md10 layui-col-lg10 layui-col-sm9 layui-col-md10 layui-col-lg10"
|
||||
th:text="${hotBook.bookDesc}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
<div style="height: 1px" class="layui-col-lg1"></div>
|
||||
<div class="layui-colla-item layui-col-lg10"
|
||||
style="border-width: 1px;border-style: solid;border-radius: 2px;border-top-width: 0px"><a
|
||||
href="javascript:moreNewBooks()">
|
||||
<h2 class="layui-colla-title">最近更新小说
|
||||
<div style="float: right; margin-right: 20px"><i style="font-size: 14px;"
|
||||
class="layui-icon">更多</i>
|
||||
</div>
|
||||
</h2>
|
||||
</a>
|
||||
<div class="layui-colla-content layui-show">
|
||||
|
||||
<div class="layui-container" style="padding-left: 2px;padding-right: 5px">
|
||||
<div class="layui-row" id="updateRankBooks">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
<div th:replace="mobile/common/footer :: footer">
|
||||
</div>
|
||||
<div th:replace="mobile/common/js :: js">
|
||||
</div>
|
||||
|
||||
<script src="/mobile/js/wap_collect.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
//加载首页书籍设置数据
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/book/listBookSetting",
|
||||
data: {},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
|
||||
//本周强推
|
||||
var rightListBooks = data.data[2];
|
||||
var rightListBooksHtml = "";
|
||||
for (var i = 0; i < 3; i++) {
|
||||
var rightListBook = rightListBooks[i];
|
||||
var classHtml = "";
|
||||
if (i == 0) {
|
||||
classHtml = "on";
|
||||
}
|
||||
if (i < 3) {
|
||||
classHtml += (" num" + (i + 1));
|
||||
}
|
||||
|
||||
rightListBooksHtml += (" <span>\n" +
|
||||
" <a href=\"/book/"+rightListBook.bookId+".html\">\n" +
|
||||
" <div style=\"padding: 1%\" class=\"layui-col-xs4 layui-col-sm4 layui-col-md4 layui-col-lg4\">\n" +
|
||||
" <img style=\" width:80%; height:auto; max-width:100%; max-height:100%;\"\n" +
|
||||
" src=\""+rightListBook.picUrl+"\"/>\n" +
|
||||
"\n" +
|
||||
" <br/>\n" +
|
||||
" <span>"+rightListBook.bookName+"</span>\n" +
|
||||
"\n" +
|
||||
" </div>\n" +
|
||||
" </a>\n" +
|
||||
" </span>");
|
||||
}
|
||||
$("#currentWeek").html(rightListBooksHtml);
|
||||
|
||||
//热门推荐
|
||||
var hotRecBooks = data.data[3];
|
||||
var hotRecBooksHtml = "";
|
||||
for (var i = 0; i < 6; i++) {
|
||||
var hotRecBook = hotRecBooks[i];
|
||||
|
||||
if(hotRecBook.bookDesc){
|
||||
hotRecBook.bookDesc = hotRecBook.bookDesc.replace(/<[^>]+>/g,"").replace(/\s+/g,"");
|
||||
}
|
||||
|
||||
hotRecBooksHtml += ("<div style=\"margin-bottom: 5px\" class=\"layui-col-xs12 layui-col-sm6 layui-col-md4 layui-col-lg4\">\n" +
|
||||
" <a href=\"/book/"+hotRecBook.bookId+".html\">\n" +
|
||||
" <div class=\"layui-col-xs5 layui-col-sm4 layui-col-md4 layui-col-lg4\" >\n" +
|
||||
" <img style=\" width:100px; height:125px;\"\n" +
|
||||
" src=\""+hotRecBook.picUrl+"\"/>\n" +
|
||||
"\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"layui-col-xs5 layui-col-sm6 layui-col-md6 layui-col-lg6\">\n" +
|
||||
" <ul>\n" +
|
||||
" <li class=\"line-limit-length\" style=\"font-weight: bold\">"+hotRecBook.bookName+"</li>\n" +
|
||||
" <li>作者:"+hotRecBook.authorName+"</li>\n" +
|
||||
" <li style=\"width: 180px;height:40px;overflow: hidden\">简介: "+hotRecBook.bookDesc+"" +
|
||||
" </ul>\n" +
|
||||
" </div>\n" +
|
||||
" <div style=\"font-style: italic;color: red\"\n" +
|
||||
" class=\"layui-col-xs2 layui-col-sm2 layui-col-md2 layui-col-lg2\"></div>\n" +
|
||||
" </a>\n" +
|
||||
" </div>");
|
||||
}
|
||||
$("#hotRecBooks").html(hotRecBooksHtml);
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
},
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
//更新榜单查询
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/book/listUpdateRank",
|
||||
data: {},
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
var updateRankBooks = data.data;
|
||||
var updateRankBookHtml = "";
|
||||
for (var i = 0; i < 10; i++) {
|
||||
|
||||
var updateRankBook = updateRankBooks[i];
|
||||
if(updateRankBook.bookDesc){
|
||||
updateRankBook.bookDesc = updateRankBook.bookDesc.replace(/<[^>]+>/g,"").replace(/\s+/g,"");
|
||||
}
|
||||
|
||||
updateRankBookHtml += ("<div style=\"padding-bottom: 30px\"\n" +
|
||||
" class=\"layui-col-xs12 layui-col-sm6 layui-col-md6 layui-col-lg6\">\n" +
|
||||
"\n" +
|
||||
" <a href=\"/book/"+updateRankBook.id+".html\">\n" +
|
||||
" <div class=\"line-limit-length layui-col-xs8 layui-col-sm6 layui-col-md6 layui-col-lg6\"><b>"+(i+1)+"."+updateRankBook.bookName+"</b> - <span class=\"layui-elip\">"+updateRankBook.authorName+"</span>\n" +
|
||||
" </div>\n" +
|
||||
" <div class=\"layui-col-sm3 layui-col-md3 layui-col-lg3\"\n" +
|
||||
" style=\"color: #FF5722;float: right;margin-right:5px\"><i>"+updateRankBook.lastIndexUpdateTime+"</i></div>\n" +
|
||||
"\n" +
|
||||
" <div style=\"clear: both\"></div>\n" +
|
||||
" <div style=\"padding-left: 5px;padding-top: 5px\"\n" +
|
||||
" class=\"layui-elip layui-col-md11 layui-col-sm11 layui-col-lg11\">简介: "+updateRankBook.bookDesc+"" +
|
||||
" </div></a>\n" +
|
||||
" </div>");
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
$("#updateRankBooks").html(updateRankBookHtml);
|
||||
} else {
|
||||
layer.alert(data.msg);
|
||||
}
|
||||
|
||||
}
|
||||
,
|
||||
error: function () {
|
||||
layer.alert('网络异常');
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
function moreNewBooks(event) {
|
||||
window.location.href = "/book/book_ranking.html?sortBy=last_index_update_time";
|
||||
}
|
||||
|
||||
function searchBooks() {
|
||||
var keywords = $("#title").val();
|
||||
window.location.href = "/book/book_ranking.html?keyword=" + encodeURI(keywords);
|
||||
}
|
||||
|
||||
function toMyCollect() {
|
||||
var token = localStorage.getItem("token");
|
||||
if (token) {
|
||||
window.location.href = "/book/book_ranking.html?token=" + token;
|
||||
} else {
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
113
templates/dark/html/mobile/user/login.html
Normal file
@ -0,0 +1,113 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>登录|注册</title>
|
||||
|
||||
<div th:include="common/css :: css"></div>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body id="read" >
|
||||
|
||||
</div>
|
||||
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<b class="layui-icon">登录|注册</b>
|
||||
<div style="float: right;margin-right: 10px"><a href="/">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form style="height: 500px;margin-top: 50px" class="layui-form" action="">
|
||||
<input type="hidden" id="bookIdHidden" name="bookId" th:value="${bookId}"/>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">登录名</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" id="loginName" name="loginName" required lay-verify="required" placeholder="请输入登录名" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">密码</label>
|
||||
<div class="layui-input-inline">
|
||||
<input id="password" type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">如果登录名不存在,则直接注册!</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit lay-filter="formDemo">登录|注册</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
<div th:replace="common/footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
<div th:replace="common/js :: js"></div>
|
||||
|
||||
<script>
|
||||
$.get("/book/addVisit",{"bookId":$("#bookIdHidden").val()},function(){});
|
||||
|
||||
</script>
|
||||
|
||||
<script>
|
||||
//Demo
|
||||
layui.use('form', function(){
|
||||
var form = layui.form;
|
||||
|
||||
//监听提交
|
||||
form.on('submit(formDemo)', function(){
|
||||
$.post("/user/loginOrRegist",{"bookId":$("#bookIdHidden").val(),"loginName":$("#loginName").val(),"password":$("#password").val()},function (data) {
|
||||
if(data.code == 1 || data.code == 2){
|
||||
localStorage.setItem("token",data.token);
|
||||
layer.alert(data.desc);
|
||||
setTimeout(function () {
|
||||
var bookId = $("#bookIdHidden").val();
|
||||
if(bookId){
|
||||
//加入书架
|
||||
window.location.href="/book/"+bookId+".html";
|
||||
}else{
|
||||
//我的书架
|
||||
window.location.href="/book/search?token="+data.token;
|
||||
}
|
||||
},3000)
|
||||
|
||||
}else{
|
||||
layer.alert(data.desc);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
|
||||
|
||||
|
||||
function toMyCollect(){
|
||||
var token = localStorage.getItem("token");
|
||||
if(token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
}else{
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
113
templates/dark/html/user/login.html
Normal file
@ -0,0 +1,113 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>登录|注册</title>
|
||||
|
||||
<div th:include="common/css :: css"></div>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body id="read" >
|
||||
|
||||
</div>
|
||||
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<b class="layui-icon">登录|注册</b>
|
||||
<div style="float: right;margin-right: 10px"><a href="/">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form style="height: 500px;margin-top: 50px" class="layui-form" action="">
|
||||
<input type="hidden" id="bookIdHidden" name="bookId" th:value="${bookId}"/>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">登录名</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" id="loginName" name="loginName" required lay-verify="required" placeholder="请输入登录名" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">密码</label>
|
||||
<div class="layui-input-inline">
|
||||
<input id="password" type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">如果登录名不存在,则直接注册!</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit lay-filter="formDemo">登录|注册</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
<div th:replace="common/footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
<div th:replace="common/js :: js"></div>
|
||||
|
||||
<script>
|
||||
$.get("/book/addVisit",{"bookId":$("#bookIdHidden").val()},function(){});
|
||||
|
||||
</script>
|
||||
|
||||
<script>
|
||||
//Demo
|
||||
layui.use('form', function(){
|
||||
var form = layui.form;
|
||||
|
||||
//监听提交
|
||||
form.on('submit(formDemo)', function(){
|
||||
$.post("/user/loginOrRegist",{"bookId":$("#bookIdHidden").val(),"loginName":$("#loginName").val(),"password":$("#password").val()},function (data) {
|
||||
if(data.code == 1 || data.code == 2){
|
||||
localStorage.setItem("token",data.token);
|
||||
layer.alert(data.desc);
|
||||
setTimeout(function () {
|
||||
var bookId = $("#bookIdHidden").val();
|
||||
if(bookId){
|
||||
//加入书架
|
||||
window.location.href="/book/"+bookId+".html";
|
||||
}else{
|
||||
//我的书架
|
||||
window.location.href="/book/search?token="+data.token;
|
||||
}
|
||||
},3000)
|
||||
|
||||
}else{
|
||||
layer.alert(data.desc);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
|
||||
|
||||
|
||||
function toMyCollect(){
|
||||
var token = localStorage.getItem("token");
|
||||
if(token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
}else{
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
BIN
templates/dark/static/HotBook.apk
Normal file
BIN
templates/dark/static/IMG_1470.JPG
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
templates/dark/static/favicon.ico
Normal file
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 439 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 70 KiB |
270
templates/dark/static/html/note_1.html
Normal file
@ -0,0 +1,270 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta http-equiv="Content-Style-Type" content="text/css"/>
|
||||
<meta name="generator" content="Aspose.Words for .NET 15.1.0.0"/>
|
||||
<title>RestTemplate中文乱码问题源码分析与解决</title></head>
|
||||
<body>
|
||||
<div><p style="font-size:18pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_499-1566046872517"></a><a
|
||||
style="color:#003884" href="http://www.zinglizingli.xyz"><span
|
||||
style="background-color:#ffffff; color:#003884; font-family:'Times New Roman'; font-size:18pt; font-weight:bold; text-decoration:underline">RestTemplate中文乱码问题源码分析与解决</span></a>
|
||||
</p>
|
||||
<p style="font-size:18pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_668-1566076102707"></a><span
|
||||
style="background-color:#ffffff; color:#393939; font-family:'Times New Roman'; font-size:18pt; font-weight:bold">--- 请求响应数据乱码源码原理分析</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_359-1566070296357"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_090-1566070299368"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="margin:0pt"><a name="_374-1566070299635"></a><span
|
||||
style="background-color:#ffffff; color:#df402a; font-family:微软雅黑; font-size:15pt; font-weight:bold">============================原理===================</span>
|
||||
</p>
|
||||
<p style="margin:0pt"><a name="_115-1566075419335"></a><span
|
||||
style="color:#7b5ba1; font-family:SimSun; font-size:11pt; font-style:italic">//默认方式:</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_398-1566075426884"></a><span
|
||||
style="color:#7b5ba1; font-family:SimSun; font-size:11pt; font-style:italic">//RestTemplate restTemplate = new RestTemplate();</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_535-1566075426884"></a><span
|
||||
style="color:#7b5ba1; font-family:SimSun; font-size:11pt; font-style:italic">// 当返回的response-header的content-type属性有charset值时,</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_832-1566075426884"></a><span
|
||||
style="color:#7b5ba1; font-family:SimSun; font-size:11pt; font-style:italic">// restTemplate的 StringHttpMessageConverter会读取该charset值,并使用该值进行</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_044-1566081046911"></a><span
|
||||
style="color:#7b5ba1; font-family:SimSun; font-size:11pt; font-style:italic">//IO流 = 》字符串的转换,否则则使用默认的字符集</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_025-1566075590776"></a><span
|
||||
style="color:#7b5ba1; font-family:SimSun; font-size:11pt; font-style:italic">// </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_437-1566081514760"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_917-1566081515252"></a><span
|
||||
style="color:#7b5ba1; font-family:SimSun; font-size:11pt; font-style:italic">通过源码可以发现restTemplate底层默认使用了</span><span
|
||||
style="background-color:#ff0000; color:#ffffff; font-family:SimSun; font-size:11pt">HttpURLConnection</span><span
|
||||
style="background-color:#ffffff; color:#7b5ba1; font-family:SimSun; font-size:11pt">,可以支持其他多种http客户端,如httpclient、okhttp等,通过</span><span
|
||||
style="background-color:#ffffff; color:#df402a; font-family:SimSun; font-size:11pt">工厂方法模式</span><span
|
||||
style="background-color:#ffffff; color:#7b5ba1; font-family:SimSun; font-size:11pt">创建请求:</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_345-1566082269458"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_991-1566082211397"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.001.png" width="553" height="144" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_880-1566082349718"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_793-1566082349718"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.002.png" width="553" height="345" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_565-1566082347503"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_974-1566082347716"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_859-1566082347902"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_055-1566082348093"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_542-1566081537855"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.003.png" width="553" height="277" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_721-1566075426884"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_131-1566077535593"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:0pt"><span
|
||||
style="font:7.0pt 'Times New Roman'">                         </span><a
|
||||
name="_460-1566077535917"></a><span
|
||||
style="color:#df402a; font-family:SimSun; font-size:11pt; font-style:italic">restTemplate调用excute方法</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_598-1566077659788"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.004.png" width="553" height="271" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:0pt"><span
|
||||
style="font:7.0pt 'Times New Roman'">                         </span><a
|
||||
name="_383-1566077653687"></a><span
|
||||
style="color:#df402a; font-family:SimSun; font-size:11pt; font-style:italic">restTemplate调用了doExecute方法</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_000-1566077736808"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.005.png" width="553" height="236" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:0pt"><span
|
||||
style="font:7.0pt 'Times New Roman'">                         </span><a
|
||||
name="_340-1566077732786"></a><span
|
||||
style="color:#df402a; font-family:SimSun; font-size:11pt; font-style:italic">执行请求,调用</span><span
|
||||
style="background-color:#ffffff; color:#df402a; font-family:SimSun; font-size:11pt">ResponseExtractor </span><span
|
||||
style="color:#df402a; font-family:SimSun; font-size:11pt; font-style:italic">responseExtractor.extractData()对相应结果进行数据提取</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_150-1566078107678"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.006.png" width="553" height="382" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:0pt"><span
|
||||
style="font:7.0pt 'Times New Roman'">                         </span><a
|
||||
name="_593-1566078099144"></a><span
|
||||
style="color:#df402a; font-family:SimSun; font-size:11pt; font-style:italic">调用</span><span
|
||||
style="color:#df402a; font-family:'Times New Roman'; font-size:11pt">HttpMessageConverterExtractor </span><span
|
||||
style="color:#df402a; font-family:SimSun; font-size:11pt; font-style:italic">this.delegate.extractData()执行抽取数据的操作</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_666-1566078333273"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.007.png" width="553" height="285" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:0pt"><span
|
||||
style="font:7.0pt 'Times New Roman'">                         </span><a
|
||||
name="_657-1566078289591"></a><span
|
||||
style="color:#df402a; font-family:SimSun; font-size:11pt; font-style:italic">获取response-header的content-type,</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_561-1566078994408"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.008.png" width="553" height="316" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_699-1566078994408"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_240-1566078897012"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.009.png" width="553" height="303" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:0pt"><span
|
||||
style="font:7.0pt 'Times New Roman'">                         </span><a
|
||||
name="_090-1566078895423"></a><span
|
||||
style="color:#df402a; font-family:SimSun; font-size:11pt; font-style:italic">判断消息转换器对应的支持媒体类型supportMediaType是否包含该content-type</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_470-1566079766383"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.010.png" width="553" height="275" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:0pt"><span
|
||||
style="font:7.0pt 'Times New Roman'">                         </span><a
|
||||
name="_142-1566079701403"></a><span
|
||||
style="color:#df402a; font-family:SimSun; font-size:11pt; font-style:italic">调用第一个包含该content-type的</span><span
|
||||
style="background-color:#ffffff; color:#df402a; font-family:SimSun; font-size:11pt">GenericHttpMessageConverter转换数据读取数据</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_247-1566080661650"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.011.png" width="553" height="247" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_813-1566080714156"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_896-1566080714156"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.012.png" width="553" height="308" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:0pt"><span
|
||||
style="font:7.0pt 'Times New Roman'">                         </span><a
|
||||
name="_223-1566080677140"></a><span style="color:#df402a; font-family:'Times New Roman'; font-size:11pt">读取数据的时候会再一次获取</span><span
|
||||
style="color:#df402a; font-family:SimSun; font-size:11pt; font-style:italic">response-header的content-type</span><span
|
||||
style="color:#df402a; font-family:'Times New Roman'; font-size:11pt">的字符集</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:21pt"><a name="_092-1566080909997"></a><span
|
||||
style="color:#df402a; font-family:'Times New Roman'; font-size:11pt">如果该字符集存在,则使用该字符集进行 IO流 =》字符串 转换</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_512-1566080804579"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.013.png" width="553" height="294" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_470-1566080966519"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_225-1566080966519"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.014.png" width="553" height="307" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_627-1566078282891"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_729-1566075429719"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_937-1566081177561"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="margin:0pt"><a name="_699-1566081177711"></a><span
|
||||
style="color:#df402a; font-family:微软雅黑; font-size:15pt; font-weight:bold">案例</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_026-1566075429891"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_059-1566071031255"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.015.png" width="553" height="251" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:42pt"><a name="_176-1566070330576"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:42pt"><a name="_530-1566072661453"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_299-1566072723246"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.016.png" width="367" height="101" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:42pt"><a name="_671-1566072721602"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:12pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:42pt"><a name="_075-1566072855176"></a><span
|
||||
style="color:#df402a; font-family:'Times New Roman'; font-size:12pt; font-weight:bold">响应头中并没有content-type的header,照理说浏览器应该不知道服务端返回的输入流编码,如果和浏览器默认的编码不匹配应该会出现乱码,但是现在浏览器有编码自动识别功能,所以上面的代码没有加content-type的Header也没有问题</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:42pt"><a name="_245-1566072658054"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt; text-indent:42pt"><a name="_872-1566072191117"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_972-1566072692409"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.017.png" width="439" height="462" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_066-1566072088274"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_580-1566075732276"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_942-1566075732559"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="margin:0pt"><a name="_150-1566075732802"></a><span
|
||||
style="color:#df402a; font-family:微软雅黑; font-size:15pt; font-weight:bold">实际上下面的做法更规范:</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_139-1566072089816"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.018.png" width="553" height="188" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="margin:0pt"><a name="_337-1566070344498"></a><span
|
||||
style="color:#df402a; font-family:微软雅黑; font-size:15pt; font-weight:bold">源码:</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_773-1566073175445"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.019.png" width="553" height="366" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_074-1566085375320"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_689-1566085375320"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.020.png" width="553" height="222" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_837-1566085044019"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_120-1566085034872"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.021.png" width="553" height="127" alt="clipboard.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="margin:0pt"><a name="_080-1566073168924"></a><span style="font-family:'Times New Roman'; font-size:11pt"> </span>
|
||||
</p>
|
||||
<p style="margin:0pt"><a name="_415-1566085038805"></a><span style="font-family:'Times New Roman'; font-size:11pt"> </span>
|
||||
</p>
|
||||
<p style="margin:0pt"><a name="_122-1566085039048"></a><span
|
||||
style="background-color:#ffffff; color:#df402a; font-family:微软雅黑; font-size:15pt; font-weight:bold">============================原理=====================</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_073-1566070331260"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_256-1566070331284"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_812-1566070331308"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_451-1566070331332"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_130-1566070331359"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_999-1566070331383"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_029-1566070331405"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_074-1566070331428"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_078-1566046874710"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_579-1566047010084"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.022.png" width="553" height="1"
|
||||
alt="初探RestTemplate--解决中文乱码问题 - mryang125的博客 - CSDN博客.jpg"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_666-1566047010084"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p></div>
|
||||
</body>
|
||||
</html>
|
280
templates/dark/static/html/note_2.html
Normal file
@ -0,0 +1,280 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta http-equiv="Content-Style-Type" content="text/css"/>
|
||||
<meta name="generator" content="Aspose.Words for .NET 15.1.0.0"/>
|
||||
<title>服务器跨域处理</title></head>
|
||||
<body>
|
||||
<div><p style="margin:0pt"><a name="_073-1565689474241"></a><span
|
||||
style="font-family:微软雅黑; font-size:15pt; font-weight:bold"><a href="http://m.zinglizingli.xyz">跨域处理</a></span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_011-1565689506880"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_400-1565689507090"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt">跨域是什么?浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、 协议任一不同,都是跨域 。我们是采用前后端分离开发的,也是前后端分离部署的,必然会存在跨域问题。 怎么解决跨域?很简单,只需要在controller类上添加注解 @CrossOrigin 即可!这个注解其实是CORS的实现。 </span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_460-1565689522680"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt">CORS(Cross-Origin Resource Sharing, 跨源资源共享)是W3C出的一个标准,其思 想是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成 功,还是应该失败。因此,要想实现CORS进行跨域,需要服务器进行一些设置,同时前端也需要做一些配置和分析。本文简单的对服务端的配置和前端的一些设置进行分析。</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_845-1565689480275"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_065-1565689480471"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt">1️⃣</span><span
|
||||
style="color:#df402a; font-family:'Times New Roman'; font-size:11pt">在controller类上添加注解 @CrossOrigin,表示Controller上的所以方法允许跨域,在方法上添加注解 @CrossOrigin,表示该方法允许跨域</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_231-1565689931759"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_436-1565689932017"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt">@Target({ ElementType.METHOD, ElementType.TYPE })</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_134-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt">@Retention(RetentionPolicy.RUNTIME)</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_249-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt">@Documented</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_993-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt">public @interface CrossOrigin {</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_860-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_082-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> String[] DEFAULT_ORIGINS = { "*" };</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_340-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_077-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> String[] DEFAULT_ALLOWED_HEADERS = { "*" };</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_080-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_672-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> boolean DEFAULT_ALLOW_CREDENTIALS = true;</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_262-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_435-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> long DEFAULT_MAX_AGE = 1800;</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_682-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_040-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_925-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> /**</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_940-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * 同origins属性一样</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_047-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> */</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_939-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> @AliasFor("origins")</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_774-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> String[] value() default {};</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_570-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_575-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> /**</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_114-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * 所有支持域的集合,例如"http://domain1.com"。</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_373-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * <p>这些值都显示在请求头中的Access-Control-Allow-Origin</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_316-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * "*"代表所有域的请求都支持</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_011-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * <p>如果没有定义,所有请求的域都支持</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_880-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * @see #value</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_783-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> */</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_681-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> @AliasFor("value")</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_042-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> String[] origins() default {};</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_140-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_747-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> /**</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_226-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * 允许请求头中的header,默认都支持</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_485-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> */</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_047-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> String[] allowedHeaders() default {};</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_052-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_280-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> /**</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_742-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * 响应头中允许访问的header,默认为空</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_186-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> */</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_068-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> String[] exposedHeaders() default {};</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_680-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_547-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> /**</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_089-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * 请求支持的方法,例如"{RequestMethod.GET, RequestMethod.POST}"}。</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_880-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * 默认支持RequestMapping中设置的方法</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_922-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> */</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_840-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> RequestMethod[] methods() default {};</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_090-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_066-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> /**</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_985-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * 是否允许cookie随请求发送,使用时必须指定具体的域</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_972-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> */</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_119-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> String allowCredentials() default "";</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_127-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_478-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> /**</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_580-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> * 预请求的结果的有效期,默认30分钟</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_510-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> */</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_534-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> long maxAge() default -1;</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_743-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_586-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt">}</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_052-1565689932796"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_129-1565689558428"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_873-1565689558663"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt">2️⃣</span><span
|
||||
style="color:#df402a; font-family:'Times New Roman'; font-size:11pt">配置 CorsFilter(全局配置)</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_025-1565690417616"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_510-1565690417783"></a><span
|
||||
style="background-color:#ffffff; color:#808000; font-family:SimSun; font-size:11pt">@Configuration</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_314-1565690418407"></a><span
|
||||
style="background-color:#ffffff; color:#000080; font-family:SimSun; font-size:11pt; font-weight:bold">public class </span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">GlobalCorsConfig {</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_117-1565690418407"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_834-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> </span><span
|
||||
style="background-color:#ffffff; color:#808000; font-family:SimSun; font-size:11pt">@Bean</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_074-1565690418407"></a><span
|
||||
style="background-color:#ffffff; color:#808000; font-family:SimSun; font-size:11pt"> </span><span
|
||||
style="background-color:#ffffff; color:#000080; font-family:SimSun; font-size:11pt; font-weight:bold">public </span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">CorsFilter corsFilter() {</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_037-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> </span><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic">//1.添加CORS配置信息</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_231-1565690418407"></a><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic"> </span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">CorsConfiguration config = </span><span
|
||||
style="background-color:#ffffff; color:#000080; font-family:SimSun; font-size:11pt; font-weight:bold">new </span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">CorsConfiguration();</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_560-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> </span><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic">//1) 允许的域,不要写*,否则cookie就无法使用了</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_937-1565690418407"></a><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic"> </span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">config.addAllowedOrigin(</span><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:SimSun; font-size:11pt; font-weight:bold">"http://manage.shop.com"</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_288-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> config.addAllowedOrigin(</span><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:SimSun; font-size:11pt; font-weight:bold">"http://www.shop.com"</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_712-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> </span><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic">//2) 是否发送Cookie信息</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_250-1565690418407"></a><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic"> </span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">config.setAllowCredentials(</span><span
|
||||
style="background-color:#ffffff; color:#000080; font-family:SimSun; font-size:11pt; font-weight:bold">true</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_149-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> </span><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic">//3) 允许的请求方式</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_028-1565690418407"></a><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic"> </span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">config.addAllowedMethod(</span><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:SimSun; font-size:11pt; font-weight:bold">"OPTIONS"</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_040-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> config.addAllowedMethod(</span><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:SimSun; font-size:11pt; font-weight:bold">"HEAD"</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_940-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> config.addAllowedMethod(</span><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:SimSun; font-size:11pt; font-weight:bold">"GET"</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_487-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> config.addAllowedMethod(</span><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:SimSun; font-size:11pt; font-weight:bold">"PUT"</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_065-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> config.addAllowedMethod(</span><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:SimSun; font-size:11pt; font-weight:bold">"POST"</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_034-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> config.addAllowedMethod(</span><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:SimSun; font-size:11pt; font-weight:bold">"DELETE"</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_286-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> config.addAllowedMethod(</span><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:SimSun; font-size:11pt; font-weight:bold">"PATCH"</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_584-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> </span><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic">// 4)允许的头信息</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_339-1565690418407"></a><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic"> </span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">config.addAllowedHeader(</span><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:SimSun; font-size:11pt; font-weight:bold">"*"</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_440-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> </span><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic">// 5) 有效时长</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_023-1565690418407"></a><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic">// config.setMaxAge(3600L);</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_025-1565690418407"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_612-1565690418407"></a><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic"> //2.添加映射路径,我们拦截一切请求</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_816-1565690418407"></a><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic"> </span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">UrlBasedCorsConfigurationSource configSource = </span><span
|
||||
style="background-color:#ffffff; color:#000080; font-family:SimSun; font-size:11pt; font-weight:bold">new </span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">UrlBasedCorsConfigurationSource();</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_520-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> configSource.registerCorsConfiguration(</span><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:SimSun; font-size:11pt; font-weight:bold">"/**"</span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">, config);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_929-1565690418407"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_591-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> </span><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic">//3.返回新的CorsFilter.</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_259-1565690418407"></a><span
|
||||
style="background-color:#ffffff; color:#808080; font-family:SimSun; font-size:11pt; font-style:italic"> </span><span
|
||||
style="background-color:#ffffff; color:#000080; font-family:SimSun; font-size:11pt; font-weight:bold">return new </span><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">CorsFilter(configSource);</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_877-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt"> }</span></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_415-1565690418407"></a><span
|
||||
style="background-color:#ffffff; font-family:SimSun; font-size:11pt">}</span></p></div>
|
||||
</body>
|
||||
</html>
|
243
templates/dark/static/html/note_3.html
Normal file
@ -0,0 +1,243 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta http-equiv="Content-Style-Type" content="text/css"/>
|
||||
<meta name="generator" content="Aspose.Words for .NET 15.1.0.0"/>
|
||||
<title>对分布式事务的理解</title></head>
|
||||
<body>
|
||||
<div><p style="font-size:18pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_848-1565404932800"></a><a
|
||||
style="color:#000000" href="http://www.zinglizingli.xyz"><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:18pt">对分布式事务及两阶段提交和三阶段提交的理解</span></a></p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_635-1565404934953"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="margin:0pt 0pt 10pt"><a name="_338-1565404935257"></a><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:Verdana; font-size:16pt; font-weight:bold">一、分布式数据一致性</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_989-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">在分布式系统中,为了保证数据的高可用,通常会将数据保留多个副本(replica),这些副本会放置在不同的物理的机器上。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_565-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt; font-weight:bold">1.什么是数据一致性</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_151-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">在数据有多份副本的情况下,如果网络、服务器或者软件出现故障,会导致部分副本写入成功,部分副本写入失败。这就造成各个副本之间的数据不一致,数据内容冲突。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_436-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">造成事实上的数据不一致。</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_810-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt; font-weight:bold">2.CAP定理</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_066-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">CAP理论认为在分布式的环境下设计和部署系统时,有3个核心的需求:</span>
|
||||
</p>
|
||||
<p style="font-size:12pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_928-1565405011043"></a><span
|
||||
style="background-color:#ffffff; color:#800000; font-family:Verdana; font-size:12pt; font-weight:bold">Consistency,Availability和Partition Tolerance,即CAP。</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_842-1565405011043"></a><span
|
||||
style="font-family:'Times New Roman'; font-size:11pt"> </span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_811-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">Consistency:一致性,这个和数据库ACID的一致性类似,但这里关注的所有数据节点上的数据一致性和正确性,而数据库的ACID关注的是在在一个事务内,对数据的一些约束。系统在执行过某项操作后仍然处于一致的状态。在分布式系统中,更新操作执行成功后所有的用户都应该读取到最新值。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_016-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">Availability:可用性,每一个操作总是能够在一定时间内返回结果。需要注意“一定时间”和“返回结果”。“一定时间”是指,系统结果必须在给定时间内返回。“返回结果”是指系统返回操作成功或失败的结果。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_115-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">Partition Tolerance:分区容忍性,是否可以对数据进行分区。这是考虑到性能和可伸缩性。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_237-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt; font-weight:bold">3.数据一致性模型</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_943-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">一些分布式系统通过复制数据来提高系统的可靠性和容错性,并且将数据的不同的副本存放在不同的机器。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_047-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">强一致性:</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_172-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据 CAP 理论,这种实现需要牺牲可用性。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_182-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">弱一致性:</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_317-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">系统并不保证续进程或者线程的访问都会返回最新的更新过的值。用户读到某一操作对系统特定数据的更新需要一段时间,我们称这段时间为“不一致性窗口”。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_443-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">最终一致性:</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_483-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">是弱一致性的一种特例。系统保证在没有后续更新的前提下,系统最终返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。DNS 是一个典型的最终一致性系统。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_856-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt"> </span></p>
|
||||
<p style="margin:0pt 0pt 10pt"><a name="_788-1565405011043"></a><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:Verdana; font-size:16pt; font-weight:bold">二、典型的分布式事务实例</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_082-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">跨行转账问题是一个典型的分布式事务,用户A向B的一个转账1000,要进行A的余额-1000,B的余额+1000,显然必须保证这两个操作的事务性。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_085-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">类似的还有,电商系统中,当有用户下单后,除了在订单表插入记,还要在商品表更新库存等,特别是随着微服务架构的流行,分布式事务的场景更变得更普遍。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_090-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt"> </span></p>
|
||||
<p style="margin:0pt 0pt 10pt"><a name="_157-1565405011043"></a><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:Verdana; font-size:16pt; font-weight:bold">三、两阶段提交协议</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_571-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">两阶段提交协议是协调所有分布式原子事务参与者,并决定提交或取消(回滚)的分布式算法。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_016-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt; font-weight:bold">1.协议参与者</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_050-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">在两阶段提交协议中,系统一般包含两类机器(或节点):一类为协调者(coordinator),通常一个系统中只有一个;另一类为事务参与者(participants,cohorts或workers),一般包含多个,在数据存储系统中可以理解为数据副本的个数。协议中假设每个节点都会记录写前日志(write-ahead log)并持久性存储,即使节点发生故障日志也不会丢失。协议中同时假设节点不会发生永久性故障而且任意两个节点都可以互相通信。</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_760-1565405011043"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.023.png" width="553" height="358" alt="61-160357634.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_560-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt; font-weight:bold">2.两个阶段的执行</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_474-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">1.请求阶段(commit-request phase,或称表决阶段,voting phase)</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_786-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">在请求阶段,协调者将通知事务参与者准备提交或取消事务,然后进入表决过程。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_710-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">在表决过程中,参与者将告知协调者自己的决策:同意(事务参与者本地作业执行成功)或取消(本地作业执行故障)。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_125-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">2.提交阶段(commit phase)</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_067-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">在该阶段,协调者将基于第一个阶段的投票结果进行决策:提交或取消。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_981-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">当且仅当所有的参与者同意提交事务协调者才通知所有的参与者提交事务,否则协调者将通知所有的参与者取消事务。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_532-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">参与者在接收到协调者发来的消息后将执行响应的操作。</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_080-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt; font-weight:bold">(3)两阶段提交的缺点</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_646-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">1.同步阻塞问题。执行过程中,所有参与节点都是事务阻塞型的。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_014-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_488-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">2.单点故障。由于协调者的重要性,一旦协调者发生故障。</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_765-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_010-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">3.数据不一致。在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_785-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据部一致性的现象。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt; font-weight:bold">(4)两阶段提交无法解决的问题</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_450-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">当协调者出错,同时参与者也出错时,两阶段无法保证事务执行的完整性。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_279-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">考虑协调者再发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_793-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_037-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt"> </span></p>
|
||||
<p style="margin:0pt 0pt 10pt"><a name="_052-1565405011043"></a><span
|
||||
style="background-color:#ffffff; color:#008000; font-family:Verdana; font-size:16pt; font-weight:bold">四、三阶段提交协议</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_420-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">三阶段提交协议在协调者和参与者中都引入超时机制,并且把两阶段提交协议的第一个阶段拆分成了两步:询问,然后再锁资源,最后真正提交。</span>
|
||||
</p>
|
||||
<p style="font-size:11pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_180-1565405011043"></a><img
|
||||
src="9a4a540e-1759-4268-90fa-7fb652c3604a.024.png" width="553" height="479" alt="92-920273519.png"
|
||||
style="-aw-left-pos:0pt; -aw-rel-hpos:column; -aw-rel-vpos:paragraph; -aw-top-pos:0pt; -aw-wrap-type:inline"/>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_743-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt; font-weight:bold">(1)三个阶段的执行</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_294-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">1.CanCommit阶段</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_945-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">3PC的CanCommit阶段其实和2PC的准备阶段很像。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_981-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">协调者向参与者发送commit请求,参与者如果可以提交就返回Yes响应,否则返回No响应。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_220-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">2.PreCommit阶段</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_740-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">Coordinator根据Cohort的反应情况来决定是否可以继续事务的PreCommit操作。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_866-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">根据响应情况,有以下两种可能。</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_992-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">A.假如Coordinator从所有的Cohort获得的反馈都是Yes响应,那么就会进行事务的预执行:</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_627-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">发送预提交请求。Coordinator向Cohort发送PreCommit请求,并进入Prepared阶段。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_214-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">事务预提交。Cohort接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_012-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">响应反馈。如果Cohort成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_068-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">B.假如有任何一个Cohort向Coordinator发送了No响应,或者等待超时之后,Coordinator都没有接到Cohort的响应,那么就中断事务:</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_646-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">发送中断请求。Coordinator向所有Cohort发送abort请求。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_143-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">中断事务。Cohort收到来自Coordinator的abort请求之后(或超时之后,仍未收到Cohort的请求),执行事务的中断。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_223-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">3.DoCommit阶段</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_678-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">该阶段进行真正的事务提交,也可以分为以下两种情况:</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_532-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">执行提交</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_431-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">A.发送提交请求。Coordinator接收到Cohort发送的ACK响应,那么他将从预提交状态进入到提交状态。并向所有Cohort发送doCommit请求。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_533-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">B.事务提交。Cohort接收到doCommit请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_010-1565405011043"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">C.响应反馈。事务提交完之后,向Coordinator发送ACK响应。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_145-1565405011044"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">D.完成事务。Coordinator接收到所有Cohort的ACK响应之后,完成事务。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_084-1565405011044"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">中断事务</span></p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_752-1565405011044"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">Coordinator没有接收到Cohort发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_841-1565405011044"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt; font-weight:bold">(2)三阶段提交协议和两阶段提交协议的不同</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_499-1565405011044"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">对于协调者(Coordinator)和参与者(Cohort)都设置了超时机制(在2PC中,只有协调者拥有超时机制,即如果在一定时间内没有收到cohort的消息则默认失败)。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_629-1565405011044"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">在2PC的准备阶段和提交阶段之间,插入预提交阶段,使3PC拥有CanCommit、PreCommit、DoCommit三个阶段。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_049-1565405011044"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">PreCommit是一个缓冲,保证了在最后提交阶段之前各参与节点的状态是一致的。</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_674-1565405011044"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt; font-weight:bold">(2)三阶段提交协议的缺点</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_085-1565405011044"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">如果进入PreCommit后,Coordinator发出的是abort请求,假设只有一个Cohort收到并进行了abort操作,</span>
|
||||
</p>
|
||||
<p style="font-size:10pt; line-height:115%; margin:0pt 0pt 10pt"><a name="_298-1565405011044"></a><span
|
||||
style="background-color:#ffffff; font-family:Verdana; font-size:10pt">而其他对于系统状态未知的Cohort会根据3PC选择继续Commit,此时系统状态发生不一致性。</span>
|
||||
</p></div>
|
||||
</body>
|
||||
</html>
|