Compare commits

...

93 Commits

Author SHA1 Message Date
3849a9b86f build: 修改版本号 2024-11-02 18:32:01 +08:00
71b9d1d916 模版更新 2024-11-02 18:31:47 +08:00
4b9dbe969c 修复i笔趣阁爬虫规则 2024-11-02 18:26:40 +08:00
2136f7490f 增加爬虫规则 2024-11-02 13:24:28 +08:00
3586ffbc0a 优化 2024-09-21 11:14:07 +08:00
f78a2a36cf 优化 2024-09-21 11:10:44 +08:00
a8219253e9 优化 2024-09-21 10:15:45 +08:00
5c35f7af0a 更换默认logo图片 2024-09-16 21:08:32 +08:00
d55e1a3e22 revert: sql格式化还原 2024-08-06 22:42:43 +08:00
21a6a49ce9 fix: 作家稿费统计 2024-08-06 21:14:22 +08:00
3735023cef perf(novel-front): UI优化 2024-07-20 21:48:29 +08:00
89992dc781 perf(novel-crawl): 增加小说内容过滤 2024-06-01 09:56:07 +08:00
976db9420e build: 修改版本号 2024-05-31 20:59:34 +08:00
e33db86081 Update README.md 2024-05-28 12:34:00 +08:00
48a70c2aca build: 修改版本号 2024-05-28 09:45:23 +08:00
ea5c0e8bd1 模版更新 2024-05-28 09:42:27 +08:00
b0c249cdca fix: 默认logo图片失效 2024-05-26 22:50:57 +08:00
730fcb4c76 fix: 默认logo图片失效 2024-05-26 22:46:46 +08:00
b976a00389 perf: UI优化 2024-05-26 22:31:26 +08:00
6d9b563583 fix: 文件上传大小限制 2024-05-25 22:05:03 +08:00
bfb7d6cc5c fix: i笔趣阁域名更换 2024-05-12 17:26:59 +08:00
9d4dc409c6 fix: URI编码 2024-03-03 11:10:46 +08:00
34d211afbf fix: 只推荐有内容的小说 2024-02-21 19:27:48 +08:00
2d218076c4 chore: 修改打包默认模版 2024-02-18 10:28:29 +08:00
674e4df84c chore: 模版更新 2024-02-07 14:59:31 +08:00
331f56d112 fix: 移动端首页在数据量小于10时报错 2024-02-07 14:58:36 +08:00
f494aae2c7 chore: 模版更新 2024-02-07 14:23:32 +08:00
2fc533f8ae fix(novel-crawl): 登录页样式问题 2024-02-05 21:12:41 +08:00
82758271e3 feat: 增加语音播放小说内容 2024-02-05 12:05:26 +08:00
4c82c2d720 perf: 优化支付宝支付流程 2024-02-04 12:25:26 +08:00
4665b5c4b9 fix: bug 2024-02-03 16:14:36 +08:00
7bbabb3492 fix: 修复充值页面的未登录跳转路径 2024-02-03 14:03:23 +08:00
d6093d8182 fix(novel-admin): 友情链接URL格式校验 2023-12-29 18:54:53 +08:00
f77792aa3c perf: 限制昵称长度并优化显示 2023-12-29 00:34:04 +08:00
c62da9bb3a fix: nickName、userPhoto 更新校验 2023-12-29 00:11:01 +08:00
8a63cff0b5 Update README.md 2023-10-31 08:24:54 +08:00
07bed12fa5 fix(mobile): 充值页标题 2023-10-30 14:17:03 +08:00
0d6e0ffb06 perf(mobile): 内容页优化
去掉小说内容前面的多余空格
2023-10-30 14:07:31 +08:00
e7005004bb perf(mobile): 登录/注册页优化 2023-10-30 14:01:39 +08:00
ff68cdd829 perf(mobile): 首页优化 2023-10-30 14:01:24 +08:00
b61dc4d0d5 build(Docker): 管理 Dockerfile 文件 2023-10-22 19:20:52 +08:00
98f1f804c3 chore(sql): 自动创建 novel_plus 数据库 2023-10-22 19:07:32 +08:00
5978d6cbcc build: 修改版本号 2023-10-21 21:21:54 +08:00
ef290bed9c fix: 书架列表时间格式化 2023-10-21 21:02:00 +08:00
5543e5aa57 perf: 设置网站 ico 图标 2023-10-15 20:30:11 +08:00
0332802fe5 feat(crawl): 账号退出 2023-10-15 19:13:07 +08:00
a55f456b3d perf: 更新爬虫管理系统主题颜色 2023-10-15 17:54:44 +08:00
f6d66e69fb Update README.md 2023-10-14 18:19:00 +08:00
96960789e1 fix(alipay): 修改默认支付宝支付成功跳转地址 2023-10-14 17:50:14 +08:00
1998dcd460 fix(alipay): 修复支付宝支付页面报错
沙箱环境自动升级到新版后,没有在代码中更换新版本的应用/网关/账号信息,也没有从左边栏沙箱工具中下载最新版本的沙箱支付宝APP安装使用。
2023-10-14 17:42:42 +08:00
a33d8f68a2 删除垃圾文件 2023-10-14 13:42:37 +08:00
30959da038 删除垃圾文件 2023-10-14 13:39:11 +08:00
5406783344 删除垃圾文件 2023-10-14 12:54:33 +08:00
d84345918b Update README.md 2023-10-14 10:32:46 +08:00
a5394cb426 Update README.md 2023-10-14 10:20:16 +08:00
2275b85752 chore: 模版更新 2023-10-14 10:16:41 +08:00
2062123edd perf(mobile): 去除手机网站底部空白间隙 2023-10-14 10:06:16 +08:00
255b3f8c4b feat(templates): 新增绿色主题模版,并设置为默认模版
和文档站点 docs.xxyopen.com 风格保持一致
2023-10-13 21:21:21 +08:00
00179359bd chore: 更新 Dockerfile 文件 2023-10-12 16:33:57 +08:00
6019ce11c7 build: 修改版本号 2023-10-12 10:02:50 +08:00
3e1c1f02e9 chore: 模版更新 2023-10-12 09:59:08 +08:00
98a5157623 feat: 支付宝手机网站支付 2023-10-12 09:49:03 +08:00
05d65c19a7 perf: 手机端页面优化 2023-10-12 09:42:28 +08:00
4c9f39ab19 feat: 手机端阅读历史页面适配 2023-10-12 09:28:29 +08:00
8bc05a1606 Merge remote-tracking branch 'Gitee/4.1.x' into develop_xxy 2023-10-12 09:03:32 +08:00
f9aad61b10 chore: 模版更新 2023-10-10 19:31:26 +08:00
8311681b23 perf(mobile): 加入书架按钮样式优化 2023-10-10 19:29:26 +08:00
4497dd1974 chore: 模版更新 2023-09-29 19:25:06 +08:00
44bf0cd693 fix: 修复作家专区小说封面更新问题 2023-09-29 19:23:12 +08:00
f333a2c084 perf: 优化小说推荐管理 2023-09-29 19:18:42 +08:00
bff5b0827e perf: 爬虫配置自定义登录页面 2023-06-09 19:25:42 +08:00
14f9205d76 docs: 修正小说内容保存配置的注释 2023-06-05 13:17:43 +08:00
cb2ff39b1e build: 移除 Elasticsearch 依赖 2023-05-28 21:51:07 +08:00
3eaa526093 fix: 修复CVE漏洞 2023-05-28 21:44:44 +08:00
04d7b45334 feat: 移除 FastDFS 模块 2023-05-28 19:14:21 +08:00
24c80e381c fix: 修改依赖组件漏洞 2023-05-28 18:43:05 +08:00
9fe51eab74 fix: 页面请求异常处理 2023-05-17 23:43:27 +08:00
e1c800d78f feat: 手机端用户中心优化 2023-05-14 07:05:36 +08:00
eb982b51f7 feat: 手机端充值页面适配 2023-05-14 06:58:42 +08:00
18f5fbf508 feat: 手机端我的书架页面适配 2023-05-13 23:40:54 +08:00
c63b4d617e feat: 手机端用户中心页面适配 2023-05-13 23:02:53 +08:00
4fb0d478f3 feat: 手机端注册页面适配 2023-05-13 19:57:19 +08:00
dabfb9d1e8 feat: 手机端登录页面适配 2023-05-13 15:15:42 +08:00
dce8a21c0d feat: 首页是否登录识别 2023-05-13 13:11:10 +08:00
d9ad02e3f5 fix(sql): 网站信息修改提示未授权
超级管理员增加网站信息修改权限
2023-05-08 15:52:02 +08:00
b02a2b3b2c build: 4.1.0 发布 2023-04-18 12:00:50 +08:00
f28c8a9c16 revert: 恢复误删文件
作家专区稿费收入报错
2023-04-18 11:34:26 +08:00
e44978617f feat: 后台会员反馈管理 2023-04-18 11:23:45 +08:00
aa2929a3cd feat: 后台小说推荐管理 2023-04-18 10:58:33 +08:00
281561c85b fix: 会员注册验证码 2023-04-18 09:17:30 +08:00
cab350dbb2 fix: 刷新首页新闻缓存 2023-04-18 08:58:30 +08:00
9ed465784a fix: 网站信息管理的权限问题 2023-04-17 10:55:20 +08:00
e2cfa5a788 Update README.md 2023-04-16 08:32:19 +08:00
789 changed files with 65590 additions and 20815 deletions

View File

@ -9,7 +9,7 @@
</p>
<p align="center">
👉 <a href='https://novel.xxyopen.com'>官网</a> | 👉 <a href='http://47.106.243.172:8888'>演示站点</a> | 👉 <a href='https://docs.xxyopen.com/course/novelplus/'>项目文档(含安装教程</a>
👉 <a href='https://novel.xxyopen.com'>官网</a> | 👉 <a href='https://www.bilibili.com/video/BV1Zo4y187Mi'>项目演示</a> | 👉 <a href='https://docs.xxyopen.com/course/novelplus/1.html'>安装教程</a>
</p>
## 项目介绍
@ -50,17 +50,24 @@ novel-plus -- 父工程
| Spring Security | 安全框架
| Apache Shiro | 安全框架
| Redis | 缓存方案
| Aliyun OSS | 阿里云对象存储服务(图片存储方式之一一行配置即可切换)
| FastDFS | 开源轻量级分布式文件系统(图片存储方式之一一行配置即可切换)
| Aliyun OSS | 阿里云对象存储服务图片存储备选方案
| Lombok | 简化对象封装工具
| Docker | 应用容器引擎
| MySQL | 数据库服务
| Thymeleaf | 模板引擎
| Layui | 前端 UI 框架
## 项目演示
## 项目截图
https://www.bilibili.com/video/BV1Zo4y187Mi
### 绿色主题模版
[![点击查看大图](https://www.xxyopen.com/images/green_novel.png)](https://www.xxyopen.com/images/green_novel.png)
[![点击查看大图](https://www.xxyopen.com/images/resource/os/novel-plus/green3.png)](https://www.xxyopen.com/images/resource/os/novel-plus/green3.png)
[![点击查看大图](https://www.xxyopen.com/images/resource/os/novel-plus/green2.png)](https://www.xxyopen.com/images/resource/os/novel-plus/green2.png)
## 演示视频
https://www.bilibili.com/video/BV18e41197xs
## 增值服务

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 411 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 461 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 357 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 929 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 764 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

View File

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

51
doc/sql/20230418.sql Normal file
View File

@ -0,0 +1,51 @@
INSERT INTO sys_dict (name, value, type, description, sort, parent_id, create_by, create_date, update_by,
update_date, remarks, del_flag)
VALUES ('轮播图', '0', 'book_rec_type', '小说推荐类型', 0, null, null, null, null, null, '', null);
INSERT INTO sys_dict (name, value, type, description, sort, parent_id, create_by, create_date, update_by,
update_date, remarks, del_flag)
VALUES ('顶部小说栏', '1', 'book_rec_type', '小说推荐类型', 1, null, null, null, null, null, '', null);
INSERT INTO sys_dict (name, value, type, description, sort, parent_id, create_by, create_date, update_by,
update_date, remarks, del_flag)
VALUES ('本周强推', '2', 'book_rec_type', '小说推荐类型', 2, null, null, null, null, null, '', null);
INSERT INTO sys_dict (name, value, type, description, sort, parent_id, create_by, create_date, update_by,
update_date, remarks, del_flag)
VALUES ('热门推荐', '3', 'book_rec_type', '小说推荐类型', 3, null, null, null, null, null, '', null);
INSERT INTO sys_dict (name, value, type, description, sort, parent_id, create_by, create_date, update_by,
update_date, remarks, del_flag)
VALUES ('精品推荐', '4', 'book_rec_type', '小说推荐类型', 4, null, null, null, null, null, '', null);
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (320, '300', '小说推荐', 'novel/bookSetting', 'novel:bookSetting:bookSetting', '1', 'fa', '6');
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (321, '320', '查看', null, 'novel:bookSetting:detail', '2', null, '6');
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (322, '320', '新增', null, 'novel:bookSetting:add', '2', null, '6');
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (323, '320', '修改', null, 'novel:bookSetting:edit', '2', null, '6');
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (324, '320', '删除', null, 'novel:bookSetting:remove', '2', null, '6');
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (325, '320', '批量删除', null, 'novel:bookSetting:batchRemove', '2', null, '6');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 320);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 321);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 322);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 323);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 324);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 325);
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (410, '400', '会员反馈', 'novel/userFeedback', 'novel:userFeedback:userFeedback', '1', 'fa', '16');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 410);

4
doc/sql/20230508.sql Normal file
View File

@ -0,0 +1,4 @@
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (305, '301', '修改', null, 'novel:websiteInfo:edit', '2', null, '6');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 305);

3
doc/sql/20240512.sql Normal file
View File

@ -0,0 +1,3 @@
update crawl_source
set crawl_rule = replace(crawl_rule, 'ibiquge.net', 'ibiquzw.org')
where id = 16;

2
doc/sql/Dockerfile Normal file
View File

@ -0,0 +1,2 @@
FROM mysql:8.0
COPY novel_plus.sql /docker-entrypoint-initdb.d/init.sql

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +0,0 @@
FROM java:8
ADD novel-admin-1.0.0.jar /root
ENV dburl=""
ENV username=""
ENV password=""
ENTRYPOINT ["sh","-c","java -Dspring.datasource.url=${dburl} -Dspring.datasource.username=${username} -Dspring.datasource.password=${password} -jar /root/novel-admin-1.0.0.jar"]

View File

@ -5,7 +5,7 @@
<groupId>com.java2nb</groupId>
<artifactId>novel-admin</artifactId>
<version>4.0.0</version>
<version>4.4.0</version>
<packaging>jar</packaging>
<name>novel-admin</name>
@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<version>2.1.18.RELEASE</version>
<relativePath/>
</parent>
@ -25,6 +25,7 @@
<velocity.version>1.7</velocity.version>
<activiti.version>5.22.0</activiti.version>
<sharding.jdbc.version>3.0.0</sharding.jdbc.version>
<jackson.version>2.15.1</jackson.version>
</properties>
<dependencies>
@ -63,12 +64,12 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
<version>8.0.29</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
<version>3.5.6</version>
</dependency>
<dependency>
@ -80,7 +81,7 @@
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.28</version>
<version>1.2.9</version>
</dependency>
<!--commons -->
<dependency>
@ -96,18 +97,18 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
<version>2.9.0</version>
</dependency>
<!--shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
<version>1.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.7.0</version>
<version>1.11.0</version>
</dependency>
<!-- shiro ehcache -->
<dependency>
@ -119,7 +120,7 @@
<artifactId>ehcache-core</artifactId>
</exclusion>
</exclusions>
<version>1.4.0</version>
<version>1.11.0</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
@ -130,7 +131,7 @@
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
<version>1.2.83</version>
</dependency>
<!--velocity代码生成使用模板 -->
<dependency>
@ -208,6 +209,12 @@
<version>${sharding.jdbc.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!--war包部署需要-->
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
@ -289,6 +296,9 @@
<zip destfile='${project.build.directory}/build/${project.artifactId}.zip'>
<zipfileset filemode="755" dir='${project.build.directory}/build/'/>
</zip>
<copy file="${basedir}/src/main/build/docker/Dockerfile"
tofile="${project.build.directory}/build/Dockerfile"/>
</tasks>
</configuration>
</execution>

View File

@ -0,0 +1,9 @@
FROM openjdk:8
ADD novel-admin.jar /root
ENV dburl=""
ENV username=""
ENV password=""
ENV redishost = ""
ENV redisport = ""
ENV redispwd = ""
ENTRYPOINT ["sh","-c","java -Dspring.datasource.url=${dburl} -Dspring.datasource.username=${username} -Dspring.datasource.password=${password} -Dspring.redis.host=${redishost} -Dspring.redis.port=${redisport} -Dspring.redis.password=${redispwd} -jar /root/novel-admin.jar"]

View File

@ -68,6 +68,7 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/favicon.ico", "anon");
filterChainDefinitionMap.put("/docs/**", "anon");
filterChainDefinitionMap.put("/layuimini/**", "anon");
filterChainDefinitionMap.put("/upload/**", "anon");

View File

@ -0,0 +1,134 @@
package com.java2nb.novel.controller;
import com.java2nb.common.config.CacheKey;
import com.java2nb.common.utils.PageBean;
import com.java2nb.common.utils.Query;
import com.java2nb.common.utils.R;
import com.java2nb.novel.domain.BookSettingDO;
import com.java2nb.novel.service.BookSettingService;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 首页小说推荐
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2023-04-18 10:01:13
*/
@Controller
@RequestMapping("/novel/bookSetting")
public class BookSettingController {
@Autowired
private BookSettingService bookSettingService;
@Autowired
private StringRedisTemplate redisTemplate;
@GetMapping()
@RequiresPermissions("novel:bookSetting:bookSetting")
String BookSetting() {
return "novel/bookSetting/bookSetting";
}
@ApiOperation(value = "获取首页小说设置表列表", notes = "获取首页小说设置表列表")
@ResponseBody
@GetMapping("/list")
@RequiresPermissions("novel:bookSetting:bookSetting")
public R list(@RequestParam Map<String, Object> params) {
//查询列表数据
Query query = new Query(params);
List<BookSettingDO> bookSettingList = bookSettingService.list(query);
int total = bookSettingService.count(query);
PageBean pageBean = new PageBean(bookSettingList, total);
return R.ok().put("data", pageBean);
}
@ApiOperation(value = "新增首页小说设置表页面", notes = "新增首页小说设置表页面")
@GetMapping("/add")
@RequiresPermissions("novel:bookSetting:add")
String add() {
return "novel/bookSetting/add";
}
@ApiOperation(value = "修改首页小说设置表页面", notes = "修改首页小说设置表页面")
@GetMapping("/edit/{id}")
@RequiresPermissions("novel:bookSetting:edit")
String edit(@PathVariable("id") Long id, Model model) {
BookSettingDO bookSetting = bookSettingService.get(id);
model.addAttribute("bookSetting", bookSetting);
return "novel/bookSetting/edit";
}
@ApiOperation(value = "查看首页小说设置表页面", notes = "查看首页小说设置表页面")
@GetMapping("/detail/{id}")
@RequiresPermissions("novel:bookSetting:detail")
String detail(@PathVariable("id") Long id, Model model) {
BookSettingDO bookSetting = bookSettingService.get(id);
model.addAttribute("bookSetting", bookSetting);
return "novel/bookSetting/detail";
}
/**
* 保存
*/
@ApiOperation(value = "新增首页小说设置表", notes = "新增首页小说设置表")
@ResponseBody
@PostMapping("/save")
@RequiresPermissions("novel:bookSetting:add")
public R save(BookSettingDO bookSetting) {
if (bookSettingService.save(bookSetting) > 0) {
return R.ok();
}
return R.error();
}
/**
* 修改
*/
@ApiOperation(value = "修改首页小说设置表", notes = "修改首页小说设置表")
@ResponseBody
@RequestMapping("/update")
@RequiresPermissions("novel:bookSetting:edit")
public R update(BookSettingDO bookSetting) {
bookSettingService.update(bookSetting);
redisTemplate.delete(CacheKey.INDEX_BOOK_SETTINGS_KEY);
return R.ok();
}
/**
* 删除
*/
@ApiOperation(value = "删除首页小说设置表", notes = "删除首页小说设置表")
@PostMapping("/remove")
@ResponseBody
@RequiresPermissions("novel:bookSetting:remove")
public R remove(Long id) {
if (bookSettingService.remove(id) > 0) {
return R.ok();
}
return R.error();
}
/**
* 删除
*/
@ApiOperation(value = "批量删除首页小说设置表", notes = "批量删除首页小说设置表")
@PostMapping("/batchRemove")
@ResponseBody
@RequiresPermissions("novel:bookSetting:batchRemove")
public R remove(@RequestParam("ids[]") Long[] ids) {
bookSettingService.batchRemove(ids);
return R.ok();
}
}

View File

@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@ -83,7 +84,7 @@ public class FriendLinkController {
@ResponseBody
@PostMapping("/save")
@RequiresPermissions("novel:friendLink:add")
public R save(FriendLinkDO friendLink) {
public R save(@Validated FriendLinkDO friendLink) {
if (friendLinkService.save(friendLink) > 0) {
redisTemplate.delete(CacheKey.INDEX_LINK_KEY);
return R.ok();
@ -98,7 +99,7 @@ public class FriendLinkController {
@ResponseBody
@RequestMapping("/update")
@RequiresPermissions("novel:friendLink:edit")
public R update(FriendLinkDO friendLink) {
public R update(@Validated FriendLinkDO friendLink) {
friendLinkService.update(friendLink);
redisTemplate.delete(CacheKey.INDEX_LINK_KEY);
return R.ok();

View File

@ -1,26 +1,21 @@
package com.java2nb.novel.controller;
import java.util.List;
import java.util.Map;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import io.swagger.annotations.ApiOperation;
import com.java2nb.novel.domain.NewsDO;
import com.java2nb.novel.service.NewsService;
import com.java2nb.common.config.CacheKey;
import com.java2nb.common.utils.PageBean;
import com.java2nb.common.utils.Query;
import com.java2nb.common.utils.R;
import com.java2nb.novel.domain.NewsDO;
import com.java2nb.novel.service.NewsService;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 新闻表
@ -33,8 +28,11 @@ import com.java2nb.common.utils.R;
@Controller
@RequestMapping("/novel/news")
public class NewsController {
@Autowired
private NewsService newsService;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@GetMapping()
@RequiresPermissions("novel:news:news")
@ -66,7 +64,7 @@ public class NewsController {
@GetMapping("/edit/{id}")
@RequiresPermissions("novel:news:edit")
String edit(@PathVariable("id") Long id, Model model) {
NewsDO news = newsService.get(id);
NewsDO news = newsService.get(id);
model.addAttribute("news", news);
return "novel/news/edit";
}
@ -75,7 +73,7 @@ public class NewsController {
@GetMapping("/detail/{id}")
@RequiresPermissions("novel:news:detail")
String detail(@PathVariable("id") Long id, Model model) {
NewsDO news = newsService.get(id);
NewsDO news = newsService.get(id);
model.addAttribute("news", news);
return "novel/news/detail";
}
@ -87,8 +85,9 @@ public class NewsController {
@ResponseBody
@PostMapping("/save")
@RequiresPermissions("novel:news:add")
public R save( NewsDO news) {
public R save(NewsDO news) {
if (newsService.save(news) > 0) {
redisTemplate.delete(CacheKey.INDEX_NEWS_KEY);
return R.ok();
}
return R.error();
@ -101,8 +100,9 @@ public class NewsController {
@ResponseBody
@RequestMapping("/update")
@RequiresPermissions("novel:news:edit")
public R update( NewsDO news) {
newsService.update(news);
public R update(NewsDO news) {
newsService.update(news);
redisTemplate.delete(CacheKey.INDEX_NEWS_KEY);
return R.ok();
}
@ -113,8 +113,9 @@ public class NewsController {
@PostMapping("/remove")
@ResponseBody
@RequiresPermissions("novel:news:remove")
public R remove( Long id) {
public R remove(Long id) {
if (newsService.remove(id) > 0) {
redisTemplate.delete(CacheKey.INDEX_NEWS_KEY);
return R.ok();
}
return R.error();
@ -128,7 +129,8 @@ public class NewsController {
@ResponseBody
@RequiresPermissions("novel:news:batchRemove")
public R remove(@RequestParam("ids[]") Long[] ids) {
newsService.batchRemove(ids);
newsService.batchRemove(ids);
redisTemplate.delete(CacheKey.INDEX_NEWS_KEY);
return R.ok();
}

View File

@ -0,0 +1,135 @@
package com.java2nb.novel.controller;
import java.util.List;
import java.util.Map;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import io.swagger.annotations.ApiOperation;
import com.java2nb.novel.domain.UserFeedbackDO;
import com.java2nb.novel.service.UserFeedbackService;
import com.java2nb.common.utils.PageBean;
import com.java2nb.common.utils.Query;
import com.java2nb.common.utils.R;
/**
*
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2023-04-18 11:08:54
*/
@Controller
@RequestMapping("/novel/userFeedback")
public class UserFeedbackController {
@Autowired
private UserFeedbackService userFeedbackService;
@GetMapping()
@RequiresPermissions("novel:userFeedback:userFeedback")
String UserFeedback() {
return "novel/userFeedback/userFeedback";
}
@ApiOperation(value = "获取列表", notes = "获取列表")
@ResponseBody
@GetMapping("/list")
@RequiresPermissions("novel:userFeedback:userFeedback")
public R list(@RequestParam Map<String, Object> params) {
//查询列表数据
Query query = new Query(params);
List<UserFeedbackDO> userFeedbackList = userFeedbackService.list(query);
int total = userFeedbackService.count(query);
PageBean pageBean = new PageBean(userFeedbackList, total);
return R.ok().put("data", pageBean);
}
@ApiOperation(value = "新增页面", notes = "新增页面")
@GetMapping("/add")
@RequiresPermissions("novel:userFeedback:add")
String add() {
return "novel/userFeedback/add";
}
@ApiOperation(value = "修改页面", notes = "修改页面")
@GetMapping("/edit/{id}")
@RequiresPermissions("novel:userFeedback:edit")
String edit(@PathVariable("id") Long id, Model model) {
UserFeedbackDO userFeedback = userFeedbackService.get(id);
model.addAttribute("userFeedback", userFeedback);
return "novel/userFeedback/edit";
}
@ApiOperation(value = "查看页面", notes = "查看页面")
@GetMapping("/detail/{id}")
@RequiresPermissions("novel:userFeedback:detail")
String detail(@PathVariable("id") Long id, Model model) {
UserFeedbackDO userFeedback = userFeedbackService.get(id);
model.addAttribute("userFeedback", userFeedback);
return "novel/userFeedback/detail";
}
/**
* 保存
*/
@ApiOperation(value = "新增", notes = "新增")
@ResponseBody
@PostMapping("/save")
@RequiresPermissions("novel:userFeedback:add")
public R save( UserFeedbackDO userFeedback) {
if (userFeedbackService.save(userFeedback) > 0) {
return R.ok();
}
return R.error();
}
/**
* 修改
*/
@ApiOperation(value = "修改", notes = "修改")
@ResponseBody
@RequestMapping("/update")
@RequiresPermissions("novel:userFeedback:edit")
public R update( UserFeedbackDO userFeedback) {
userFeedbackService.update(userFeedback);
return R.ok();
}
/**
* 删除
*/
@ApiOperation(value = "删除", notes = "删除")
@PostMapping("/remove")
@ResponseBody
@RequiresPermissions("novel:userFeedback:remove")
public R remove( Long id) {
if (userFeedbackService.remove(id) > 0) {
return R.ok();
}
return R.error();
}
/**
* 删除
*/
@ApiOperation(value = "批量删除", notes = "批量删除")
@PostMapping("/batchRemove")
@ResponseBody
@RequiresPermissions("novel:userFeedback:batchRemove")
public R remove(@RequestParam("ids[]") Long[] ids) {
userFeedbackService.batchRemove(ids);
return R.ok();
}
}

View File

@ -28,7 +28,7 @@ public class WebsiteInfoController {
private WebsiteInfoService websiteInfoService;
@GetMapping()
@RequiresPermissions("novel:websiteInfo:detail")
@RequiresPermissions("novel:websiteInfo:websiteInfo")
String detail(Model model) {
WebsiteInfoDO websiteInfo = websiteInfoService.get(1L);
model.addAttribute("websiteInfo", websiteInfo);

View File

@ -0,0 +1,32 @@
package com.java2nb.novel.dao;
import com.java2nb.novel.domain.BookSettingDO;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
/**
* 首页小说设置表
* @author xiongxy
* @email 1179705413@qq.com
* @date 2023-04-18 10:01:13
*/
@Mapper
public interface BookSettingDao {
BookSettingDO get(Long id);
List<BookSettingDO> list(Map<String,Object> map);
int count(Map<String,Object> map);
int save(BookSettingDO bookSetting);
int update(BookSettingDO bookSetting);
int remove(Long id);
int batchRemove(Long[] ids);
}

View File

@ -0,0 +1,32 @@
package com.java2nb.novel.dao;
import com.java2nb.novel.domain.UserFeedbackDO;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
/**
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2023-04-18 11:08:54
*/
@Mapper
public interface UserFeedbackDao {
UserFeedbackDO get(Long id);
List<UserFeedbackDO> list(Map<String,Object> map);
int count(Map<String,Object> map);
int save(UserFeedbackDO userFeedback);
int update(UserFeedbackDO userFeedback);
int remove(Long id);
int batchRemove(Long[] ids);
}

View File

@ -0,0 +1,175 @@
package com.java2nb.novel.domain;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.java2nb.common.jsonserializer.LongToStringSerializer;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* 首页小说设置表
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2023-04-18 10:01:13
*/
public class BookSettingDO implements Serializable {
private static final long serialVersionUID = 1L;
//
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long id;
//小说ID
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long bookId;
//排序号
private Integer sort;
//类型0轮播图1顶部小说栏设置2本周强推3热门推荐4精品推荐
private Integer type;
//创建时间
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
//创建人ID
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long createUserId;
//更新时间
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
//更新人ID
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long updateUserId;
private String bookName;
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
/**
* 设置:
*/
public void setId(Long id) {
this.id = id;
}
/**
* 获取:
*/
public Long getId() {
return id;
}
/**
* 设置小说ID
*/
public void setBookId(Long bookId) {
this.bookId = bookId;
}
/**
* 获取小说ID
*/
public Long getBookId() {
return bookId;
}
/**
* 设置:排序号
*/
public void setSort(Integer sort) {
this.sort = sort;
}
/**
* 获取:排序号
*/
public Integer getSort() {
return sort;
}
/**
* 设置类型0轮播图1顶部小说栏设置2本周强推3热门推荐4精品推荐
*/
public void setType(Integer type) {
this.type = type;
}
/**
* 获取类型0轮播图1顶部小说栏设置2本周强推3热门推荐4精品推荐
*/
public Integer getType() {
return type;
}
/**
* 设置:创建时间
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* 获取:创建时间
*/
public Date getCreateTime() {
return createTime;
}
/**
* 设置创建人ID
*/
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
/**
* 获取创建人ID
*/
public Long getCreateUserId() {
return createUserId;
}
/**
* 设置:更新时间
*/
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
/**
* 获取:更新时间
*/
public Date getUpdateTime() {
return updateTime;
}
/**
* 设置更新人ID
*/
public void setUpdateUserId(Long updateUserId) {
this.updateUserId = updateUserId;
}
/**
* 获取更新人ID
*/
public Long getUpdateUserId() {
return updateUserId;
}
}

View File

@ -1,163 +1,175 @@
package com.java2nb.novel.domain;
import java.io.Serializable;
import java.math.BigDecimal;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.java2nb.common.jsonserializer.LongToStringSerializer;
import org.hibernate.validator.constraints.URL;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
*
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2023-04-14 15:12:25
*/
public class FriendLinkDO implements Serializable {
private static final long serialVersionUID = 1L;
//主键
private Integer id;
//链接名
private String linkName;
//链接url
private String linkUrl;
//排序号
private Integer sort;
//是否开启0不开启1开启
private Integer isOpen;
//创建人id
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long createUserId;
//创建时间
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
//更新者用户id
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long updateUserId;
//更新时间
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
private static final long serialVersionUID = 1L;
/**
* 设置:主键
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取:主键
*/
public Integer getId() {
return id;
}
/**
* 设置:链接名
*/
public void setLinkName(String linkName) {
this.linkName = linkName;
}
/**
* 获取:链接名
*/
public String getLinkName() {
return linkName;
}
/**
* 设置链接url
*/
public void setLinkUrl(String linkUrl) {
this.linkUrl = linkUrl;
}
/**
* 获取链接url
*/
public String getLinkUrl() {
return linkUrl;
}
/**
* 设置:排序号
*/
public void setSort(Integer sort) {
this.sort = sort;
}
/**
* 获取:排序号
*/
public Integer getSort() {
return sort;
}
/**
* 设置是否开启0不开启1开启
*/
public void setIsOpen(Integer isOpen) {
this.isOpen = isOpen;
}
/**
* 获取是否开启0不开启1开启
*/
public Integer getIsOpen() {
return isOpen;
}
/**
* 设置创建人id
*/
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
/**
* 获取创建人id
*/
public Long getCreateUserId() {
return createUserId;
}
/**
* 设置:创建时间
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* 获取:创建时间
*/
public Date getCreateTime() {
return createTime;
}
/**
* 设置更新者用户id
*/
public void setUpdateUserId(Long updateUserId) {
this.updateUserId = updateUserId;
}
/**
* 获取更新者用户id
*/
public Long getUpdateUserId() {
return updateUserId;
}
/**
* 设置:更新时间
*/
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
/**
* 获取:更新时间
*/
public Date getUpdateTime() {
return updateTime;
}
//主键
private Integer id;
//链接名
private String linkName;
//链接url
@URL
private String linkUrl;
//排序号
private Integer sort;
//是否开启0不开启1开启
private Integer isOpen;
//创建人id
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long createUserId;
//创建时间
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
//更新者用户id
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long updateUserId;
//更新时间
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 设置:主键
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取:主键
*/
public Integer getId() {
return id;
}
/**
* 设置:链接名
*/
public void setLinkName(String linkName) {
this.linkName = linkName;
}
/**
* 获取:链接名
*/
public String getLinkName() {
return linkName;
}
/**
* 设置链接url
*/
public void setLinkUrl(String linkUrl) {
this.linkUrl = linkUrl;
}
/**
* 获取链接url
*/
public String getLinkUrl() {
return linkUrl;
}
/**
* 设置:排序号
*/
public void setSort(Integer sort) {
this.sort = sort;
}
/**
* 获取:排序号
*/
public Integer getSort() {
return sort;
}
/**
* 设置是否开启0不开启1开启
*/
public void setIsOpen(Integer isOpen) {
this.isOpen = isOpen;
}
/**
* 获取是否开启0不开启1开启
*/
public Integer getIsOpen() {
return isOpen;
}
/**
* 设置创建人id
*/
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
/**
* 获取创建人id
*/
public Long getCreateUserId() {
return createUserId;
}
/**
* 设置:创建时间
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* 获取:创建时间
*/
public Date getCreateTime() {
return createTime;
}
/**
* 设置更新者用户id
*/
public void setUpdateUserId(Long updateUserId) {
this.updateUserId = updateUserId;
}
/**
* 获取更新者用户id
*/
public Long getUpdateUserId() {
return updateUserId;
}
/**
* 设置:更新时间
*/
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
/**
* 获取:更新时间
*/
public Date getUpdateTime() {
return updateTime;
}
}

View File

@ -0,0 +1,103 @@
package com.java2nb.novel.domain;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.java2nb.common.jsonserializer.LongToStringSerializer;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @author xiongxy
* @email 1179705413@qq.com
* @date 2023-04-18 11:08:54
*/
public class UserFeedbackDO implements Serializable {
private static final long serialVersionUID = 1L;
//主键id
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long id;
//用户id
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long userId;
//反馈内容
private String content;
//反馈时间
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
/**
* 设置主键id
*/
public void setId(Long id) {
this.id = id;
}
/**
* 获取主键id
*/
public Long getId() {
return id;
}
/**
* 设置用户id
*/
public void setUserId(Long userId) {
this.userId = userId;
}
/**
* 获取用户id
*/
public Long getUserId() {
return userId;
}
/**
* 设置:反馈内容
*/
public void setContent(String content) {
this.content = content;
}
/**
* 获取:反馈内容
*/
public String getContent() {
return content;
}
/**
* 设置:反馈时间
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* 获取:反馈时间
*/
public Date getCreateTime() {
return createTime;
}
}

View File

@ -0,0 +1,30 @@
package com.java2nb.novel.service;
import com.java2nb.novel.domain.BookSettingDO;
import java.util.List;
import java.util.Map;
/**
* 首页小说设置表
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2023-04-18 10:01:13
*/
public interface BookSettingService {
BookSettingDO get(Long id);
List<BookSettingDO> list(Map<String, Object> map);
int count(Map<String, Object> map);
int save(BookSettingDO bookSetting);
int update(BookSettingDO bookSetting);
int remove(Long id);
int batchRemove(Long[] ids);
}

View File

@ -0,0 +1,30 @@
package com.java2nb.novel.service;
import com.java2nb.novel.domain.UserFeedbackDO;
import java.util.List;
import java.util.Map;
/**
*
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2023-04-18 11:08:54
*/
public interface UserFeedbackService {
UserFeedbackDO get(Long id);
List<UserFeedbackDO> list(Map<String, Object> map);
int count(Map<String, Object> map);
int save(UserFeedbackDO userFeedback);
int update(UserFeedbackDO userFeedback);
int remove(Long id);
int batchRemove(Long[] ids);
}

View File

@ -0,0 +1,67 @@
package com.java2nb.novel.service.impl;
import com.java2nb.novel.dao.BookDao;
import com.java2nb.novel.dao.BookSettingDao;
import com.java2nb.novel.domain.BookDO;
import com.java2nb.novel.domain.BookSettingDO;
import com.java2nb.novel.service.BookSettingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class BookSettingServiceImpl implements BookSettingService {
@Autowired
private BookSettingDao bookSettingDao;
@Autowired
private BookDao bookDao;
@Override
public BookSettingDO get(Long id) {
return bookSettingDao.get(id);
}
@Override
public List<BookSettingDO> list(Map<String, Object> map) {
List<BookSettingDO> list = bookSettingDao.list(map);
if (!CollectionUtils.isEmpty(list)) {
List<Long> bookIds = list.stream().map(BookSettingDO::getBookId).collect(Collectors.toList());
Map<Long, String> bookNameMap = bookDao.batchGet(bookIds).stream()
.collect(Collectors.toMap(BookDO::getId, BookDO::getBookName));
list.forEach(v -> v.setBookName(bookNameMap.get(v.getBookId())));
}
return list;
}
@Override
public int count(Map<String, Object> map) {
return bookSettingDao.count(map);
}
@Override
public int save(BookSettingDO bookSetting) {
return bookSettingDao.save(bookSetting);
}
@Override
public int update(BookSettingDO bookSetting) {
return bookSettingDao.update(bookSetting);
}
@Override
public int remove(Long id) {
return bookSettingDao.remove(id);
}
@Override
public int batchRemove(Long[] ids) {
return bookSettingDao.batchRemove(ids);
}
}

View File

@ -0,0 +1,67 @@
package com.java2nb.novel.service.impl;
import com.java2nb.novel.dao.UserDao;
import com.java2nb.novel.dao.UserFeedbackDao;
import com.java2nb.novel.domain.UserDO;
import com.java2nb.novel.domain.UserFeedbackDO;
import com.java2nb.novel.service.UserFeedbackService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class UserFeedbackServiceImpl implements UserFeedbackService {
@Autowired
private UserFeedbackDao userFeedbackDao;
@Autowired
private UserDao userDao;
@Override
public UserFeedbackDO get(Long id) {
return userFeedbackDao.get(id);
}
@Override
public List<UserFeedbackDO> list(Map<String, Object> map) {
List<UserFeedbackDO> list = userFeedbackDao.list(map);
if (!CollectionUtils.isEmpty(list)) {
List<Long> userIds = list.stream().map(UserFeedbackDO::getUserId).collect(Collectors.toList());
Map<Long, String> userNameMap = userDao.batchGet(userIds).stream()
.collect(Collectors.toMap(UserDO::getId, UserDO::getUsername));
list.forEach(v -> v.setUserName(userNameMap.get(v.getUserId())));
}
return list;
}
@Override
public int count(Map<String, Object> map) {
return userFeedbackDao.count(map);
}
@Override
public int save(UserFeedbackDO userFeedback) {
return userFeedbackDao.save(userFeedback);
}
@Override
public int update(UserFeedbackDO userFeedback) {
return userFeedbackDao.update(userFeedback);
}
@Override
public int remove(Long id) {
return userFeedbackDao.remove(id);
}
@Override
public int batchRemove(Long[] ids) {
return userFeedbackDao.batchRemove(ids);
}
}

View File

@ -18,11 +18,12 @@ spring:
profiles:
active: dev
#上传文件的最大值10M
#上传文件的最大值100M
servlet:
multipart:
max-file-size: 10485760
max-file-size: 100MB
max-request-size: 100MB
devtools:
restart:
enabled: true

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

View File

@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.novel.dao.BookSettingDao">
<select id="get" resultType="com.java2nb.novel.domain.BookSettingDO">
select `id`,
`book_id`,
`sort`,
`type`,
`create_time`,
`create_user_id`,
`update_time`,
`update_user_id`
from book_setting
where id = #{value}
</select>
<select id="list" resultType="com.java2nb.novel.domain.BookSettingDO">
select `id`,`book_id`,`sort`,`type`,`create_time`,`create_user_id`,`update_time`,`update_user_id` from
book_setting
<where>
<if test="id != null and id != ''">and id = #{id}</if>
<if test="bookId != null and bookId != ''">and book_id = #{bookId}</if>
<if test="sort != null and sort != ''">and sort = #{sort}</if>
<if test="type != null and type != ''">and type = #{type}</if>
<if test="createTime != null and createTime != ''">and create_time = #{createTime}</if>
<if test="createUserId != null and createUserId != ''">and create_user_id = #{createUserId}</if>
<if test="updateTime != null and updateTime != ''">and update_time = #{updateTime}</if>
<if test="updateUserId != null and updateUserId != ''">and update_user_id = #{updateUserId}</if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from book_setting t1 inner join book t2 on t1.book_id = t2.id
<where>
<if test="id != null and id != ''">and t1.id = #{id}</if>
<if test="bookId != null and bookId != ''">and t1.book_id = #{bookId}</if>
<if test="sort != null and sort != ''">and t1.sort = #{sort}</if>
<if test="type != null and type != ''">and t1.type = #{type}</if>
<if test="createTime != null and createTime != ''">and t1.create_time = #{createTime}</if>
<if test="createUserId != null and createUserId != ''">and t1.create_user_id = #{createUserId}</if>
<if test="updateTime != null and updateTime != ''">and t1.update_time = #{updateTime}</if>
<if test="updateUserId != null and updateUserId != ''">and t1.update_user_id = #{updateUserId}</if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.novel.domain.BookSettingDO">
insert into book_setting
(`id`,
`book_id`,
`sort`,
`type`,
`create_time`,
`create_user_id`,
`update_time`,
`update_user_id`)
values (#{id},
#{bookId},
#{sort},
#{type},
#{createTime},
#{createUserId},
#{updateTime},
#{updateUserId})
</insert>
<insert id="saveSelective" parameterType="com.java2nb.novel.domain.BookSettingDO">
insert into book_setting
(
<if test="id != null">`id`,</if>
<if test="bookId != null">`book_id`,</if>
<if test="sort != null">`sort`,</if>
<if test="type != null">`type`,</if>
<if test="createTime != null">`create_time`,</if>
<if test="createUserId != null">`create_user_id`,</if>
<if test="updateTime != null">`update_time`,</if>
<if test="updateUserId != null">`update_user_id`</if>
)
values
(
<if test="id != null">#{id},</if>
<if test="bookId != null">#{bookId},</if>
<if test="sort != null">#{sort},</if>
<if test="type != null">#{type},</if>
<if test="createTime != null">#{createTime},</if>
<if test="createUserId != null">#{createUserId},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="updateUserId != null">#{updateUserId}</if>
)
</insert>
<update id="update" parameterType="com.java2nb.novel.domain.BookSettingDO">
update book_setting
<set>
<if test="bookId != null">`book_id` = #{bookId},</if>
<if test="sort != null">`sort` = #{sort},</if>
<if test="type != null">`type` = #{type},</if>
<if test="createTime != null">`create_time` = #{createTime},</if>
<if test="createUserId != null">`create_user_id` = #{createUserId},</if>
<if test="updateTime != null">`update_time` = #{updateTime},</if>
<if test="updateUserId != null">`update_user_id` = #{updateUserId}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete
from book_setting
where id = #{value}
</delete>
<delete id="batchRemove">
delete from book_setting where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.novel.dao.UserFeedbackDao">
<select id="get" resultType="com.java2nb.novel.domain.UserFeedbackDO">
select `id`,`user_id`,`content`,`create_time` from user_feedback where id = #{value}
</select>
<select id="list" resultType="com.java2nb.novel.domain.UserFeedbackDO">
select `id`,`user_id`,`content`,`create_time` from user_feedback
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="userId != null and userId != ''"> and user_id = #{userId} </if>
<if test="content != null and content != ''"> and content = #{content} </if>
<if test="createTime != null and createTime != ''"> and create_time = #{createTime} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from user_feedback
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="userId != null and userId != ''"> and user_id = #{userId} </if>
<if test="content != null and content != ''"> and content = #{content} </if>
<if test="createTime != null and createTime != ''"> and create_time = #{createTime} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.novel.domain.UserFeedbackDO">
insert into user_feedback
(
`id`,
`user_id`,
`content`,
`create_time`
)
values
(
#{id},
#{userId},
#{content},
#{createTime}
)
</insert>
<insert id="saveSelective" parameterType="com.java2nb.novel.domain.UserFeedbackDO">
insert into user_feedback
(
<if test="id != null"> `id`, </if>
<if test="userId != null"> `user_id`, </if>
<if test="content != null"> `content`, </if>
<if test="createTime != null"> `create_time` </if>
)
values
(
<if test="id != null"> #{id}, </if>
<if test="userId != null"> #{userId}, </if>
<if test="content != null"> #{content}, </if>
<if test="createTime != null"> #{createTime} </if>
)
</insert>
<update id="update" parameterType="com.java2nb.novel.domain.UserFeedbackDO">
update user_feedback
<set>
<if test="userId != null">`user_id` = #{userId}, </if>
<if test="content != null">`content` = #{content}, </if>
<if test="createTime != null">`create_time` = #{createTime}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from user_feedback where id = #{value}
</delete>
<delete id="batchRemove">
delete from user_feedback where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -50,9 +50,6 @@ function load() {
}
},
columns: [
{
checkbox: true
},
{
title: '序号',
formatter: function () {
@ -60,6 +57,11 @@ function load() {
}
},
{
field: 'id',
title: '小说ID'
},
{
field: 'workDirection',
title: '作品方向',

View File

@ -0,0 +1,119 @@
var E = window.wangEditor;
$("[id^='contentEditor']").each(function (index, ele) {
var relName = $(ele).attr("id").substring(13);
var editor = new E('#contentEditor' + relName);
// 自定义菜单配置
editor.customConfig.menus = [
'head', // 标题
'bold', // 粗体
'fontSize', // 字号
'fontName', // 字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
'foreColor', // 文字颜色
//'backColor', // 背景颜色
//'link', // 插入链接
'list', // 列表
'justify', // 对齐方式
'quote', // 引用
'emoticon', // 表情
'image', // 插入图片
//'table', // 表格
//'video', // 插入视频
//'code', // 插入代码
'undo', // 撤销
'redo' // 重复
];
editor.customConfig.onchange = function (html) {
// html 即变化之后的内容
$("#" + relName).val(html);
}
editor.customConfig.uploadImgShowBase64 = true;
editor.create();
})
$("[id^='picImage']").each(function (index, ele) {
var relName = $(ele).attr("id").substring(8);
layui.use('upload', function () {
var upload = layui.upload;
//执行实例
var uploadInst = upload.render({
elem: '#picImage' + relName, //绑定元素
url: '/common/sysFile/upload', //上传接口
size: 1000,
accept: 'file',
done: function (r) {
$("#picImage" + relName).attr("src", r.fileName);
$("#" + relName).val(r.fileName);
},
error: function (r) {
layer.msg(r.msg);
}
});
});
});
$().ready(function () {
validateRule();
});
$.validator.setDefaults({
submitHandler: function () {
save();
}
});
function save() {
$.ajax({
cache: true,
type: "POST",
url: "/novel/bookSetting/save",
data: $('#signupForm').serialize(),// 你的formid
async: false,
error: function (request) {
parent.layer.alert("Connection error");
},
success: function (data) {
if (data.code == 0) {
parent.layer.msg("操作成功");
parent.reLoad();
var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引
parent.layer.close(index);
} else {
parent.layer.alert(data.msg)
}
}
});
}
function validateRule() {
var icon = "<i class='fa fa-times-circle'></i> ";
$("#signupForm").validate({
ignore: "",
rules: {
bookId: {
required: true
}, sort: {
required: true
}, type: {
required: true
}, },
messages: {
bookId: {
required: icon + "请选择小说ID"
}, sort: {
required: icon + "请选择排序号"
}, type: {
required: icon + "请选择推荐类型"
}, }
})
}

View File

@ -0,0 +1,191 @@
var prefix = "/novel/bookSetting"
$(function () {
load();
});
function load() {
$('#exampleTable')
.bootstrapTable(
{
method: 'get', // 服务器数据的请求方式 get or post
url: prefix + "/list", // 服务器数据的加载地址
// showRefresh : true,
// showToggle : true,
// showColumns : true,
iconSize: 'outline',
toolbar: '#exampleToolbar',
striped: true, // 设置为true会有隔行变色效果
dataType: "json", // 服务器返回的数据类型
pagination: true, // 设置为true会在底部显示分页条
// queryParamsType : "limit",
// //设置为limit则会发送符合RESTFull格式的参数
singleSelect: false, // 设置为true将禁止多选
// contentType : "application/x-www-form-urlencoded",
// //发送到服务器的数据编码类型
pageSize: 10, // 如果设置了分页,每页数据条数
pageNumber: 1, // 如果设置了分布,首页页码
//search : true, // 是否显示搜索框
showColumns: false, // 是否显示内容下拉框(选择显示的列)
sidePagination: "server", // 设置在哪里进行分页,可选值为"client" 或者 "server"
queryParams: function (params) {
//说明传入后台的参数包括offset开始索引limit步长sort排序列orderdesc或者,以及所有列的键值对
var queryParams = getFormJson("searchForm");
queryParams.limit = params.limit;
queryParams.offset = params.offset;
return queryParams;
},
// //请求服务器数据时,你可以通过重写参数的方式添加一些额外的参数,例如 toolbar 中的参数 如果
// queryParamsType = 'limit' ,返回参数必须包含
// limit, offset, search, sort, order 否则, 需要包含:
// pageSize, pageNumber, searchText, sortName,
// sortOrder.
// 返回false将会终止请求
responseHandler: function (rs) {
if (rs.code == 0) {
return rs.data;
} else {
parent.layer.alert(rs.msg)
return {total: 0, rows: []};
}
},
columns: [
{
title: '序号',
formatter: function () {
return arguments[2] + 1;
}
},
{
field: 'bookId',
title: '小说ID'
},
{
field: 'bookName',
title: '小说名'
},
{
field: 'type',
title: '推荐类型',
formatter: function (value, row, index) {
return formatDict("book_rec_type", value);
}
},
{
field: 'sort',
title: '排序号'
},
{
title: '操作',
field: 'id',
align: 'center',
formatter: function (value, row, index) {
var d = '<a class="btn btn-primary btn-sm ' + s_detail_h + '" href="#" mce_href="#" title="详情" onclick="detail(\''
+ row.id
+ '\')"><i class="fa fa-file"></i></a> ';
var e = '<a class="btn btn-primary btn-sm ' + s_edit_h + '" href="#" mce_href="#" title="编辑" onclick="edit(\''
+ row.id
+ '\')"><i class="fa fa-edit"></i></a> ';
return d + e;
}
}]
});
}
function reLoad() {
$('#exampleTable').bootstrapTable('refresh');
}
function add() {
layer.open({
type: 2,
title: '增加',
maxmin: true,
shadeClose: false, // 点击遮罩关闭层
area: ['800px', '520px'],
content: prefix + '/add' // iframe的url
});
}
function detail(id) {
layer.open({
type: 2,
title: '详情',
maxmin: true,
shadeClose: false, // 点击遮罩关闭层
area: ['800px', '520px'],
content: prefix + '/detail/' + id // iframe的url
});
}
function edit(id) {
layer.open({
type: 2,
title: '编辑',
maxmin: true,
shadeClose: false, // 点击遮罩关闭层
area: ['800px', '520px'],
content: prefix + '/edit/' + id // iframe的url
});
}
function remove(id) {
layer.confirm('确定要删除选中的记录?', {
btn: ['确定', '取消']
}, function () {
$.ajax({
url: prefix + "/remove",
type: "post",
data: {
'id': id
},
success: function (r) {
if (r.code == 0) {
layer.msg(r.msg);
reLoad();
} else {
layer.msg(r.msg);
}
}
});
})
}
function resetPwd(id) {
}
function batchRemove() {
var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行,当没有选择的记录时,返回一个空数组
if (rows.length == 0) {
layer.msg("请选择要删除的数据");
return;
}
layer.confirm("确认要删除选中的'" + rows.length + "'条数据吗?", {
btn: ['确定', '取消']
// 按钮
}, function () {
var ids = new Array();
// 遍历所有选择的行数据取每条数据对应的ID
$.each(rows, function (i, row) {
ids[i] = row['id'];
});
$.ajax({
type: 'POST',
data: {
"ids": ids
},
url: prefix + '/batchRemove',
success: function (r) {
if (r.code == 0) {
layer.msg(r.msg);
reLoad();
} else {
layer.msg(r.msg);
}
}
});
}, function () {
});
}

View File

@ -0,0 +1,121 @@
var E = window.wangEditor;
$("[id^='contentEditor']").each(function (index, ele) {
var relName = $(ele).attr("id").substring(13);
var editor = new E('#contentEditor' + relName);
// 自定义菜单配置
editor.customConfig.menus = [
'head', // 标题
'bold', // 粗体
'fontSize', // 字号
'fontName', // 字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
'foreColor', // 文字颜色
//'backColor', // 背景颜色
//'link', // 插入链接
'list', // 列表
'justify', // 对齐方式
'quote', // 引用
'emoticon', // 表情
'image', // 插入图片
//'table', // 表格
//'video', // 插入视频
//'code', // 插入代码
'undo', // 撤销
'redo' // 重复
];
editor.customConfig.onchange = function (html) {
// html 即变化之后的内容
$("#" + relName).val(html);
}
editor.customConfig.uploadImgShowBase64 = true;
editor.create();
editor.txt.html($("#" + relName).val());
})
$("[id^='picImage']").each(function (index, ele) {
var relName = $(ele).attr("id").substring(8);
layui.use('upload', function () {
var upload = layui.upload;
//执行实例
var uploadInst = upload.render({
elem: '#picImage' + relName, //绑定元素
url: '/common/sysFile/upload', //上传接口
size: 1000,
accept: 'file',
done: function (r) {
$("#picImage" + relName).attr("src", r.fileName);
$("#" + relName).val(r.fileName);
},
error: function (r) {
layer.msg(r.msg);
}
});
});
});
$().ready(function () {
validateRule();
});
$.validator.setDefaults({
submitHandler: function () {
update();
}
});
function update() {
$.ajax({
cache: true,
type: "POST",
url: "/novel/bookSetting/update",
data: $('#signupForm').serialize(),// 你的formid
async: false,
error: function (request) {
parent.layer.alert("Connection error");
},
success: function (data) {
if (data.code == 0) {
parent.layer.msg("操作成功");
parent.reLoad();
var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引
parent.layer.close(index);
} else {
parent.layer.alert(data.msg)
}
}
});
}
function validateRule() {
var icon = "<i class='fa fa-times-circle'></i> ";
$("#signupForm").validate({
ignore: "",
rules: {
bookId:
{
required: true
}, sort:
{
required: true
}, type:
{
required: true
}, },
messages: {
bookId:
{
required: icon + "请选择小说ID"
}, sort:
{
required: icon + "请选择排序号"
}, type:
{
required: icon + "请选择推荐类型"
}, }
})
}

View File

@ -50,9 +50,6 @@ function load() {
}
},
columns: [
{
checkbox: true
},
{
title: '序号',
formatter: function () {

View File

@ -50,9 +50,6 @@ function load() {
}
},
columns: [
{
checkbox: true
},
{
title: '序号',
formatter: function () {

View File

@ -0,0 +1,107 @@
var E = window.wangEditor;
$("[id^='contentEditor']").each(function (index, ele) {
var relName = $(ele).attr("id").substring(13);
var editor = new E('#contentEditor' + relName);
// 自定义菜单配置
editor.customConfig.menus = [
'head', // 标题
'bold', // 粗体
'fontSize', // 字号
'fontName', // 字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
'foreColor', // 文字颜色
//'backColor', // 背景颜色
//'link', // 插入链接
'list', // 列表
'justify', // 对齐方式
'quote', // 引用
'emoticon', // 表情
'image', // 插入图片
//'table', // 表格
//'video', // 插入视频
//'code', // 插入代码
'undo', // 撤销
'redo' // 重复
];
editor.customConfig.onchange = function (html) {
// html 即变化之后的内容
$("#" + relName).val(html);
}
editor.customConfig.uploadImgShowBase64 = true;
editor.create();
})
$("[id^='picImage']").each(function (index, ele) {
var relName = $(ele).attr("id").substring(8);
layui.use('upload', function () {
var upload = layui.upload;
//执行实例
var uploadInst = upload.render({
elem: '#picImage' + relName, //绑定元素
url: '/common/sysFile/upload', //上传接口
size: 1000,
accept: 'file',
done: function (r) {
$("#picImage" + relName).attr("src", r.fileName);
$("#" + relName).val(r.fileName);
},
error: function (r) {
layer.msg(r.msg);
}
});
});
});
$().ready(function () {
validateRule();
});
$.validator.setDefaults({
submitHandler: function () {
save();
}
});
function save() {
$.ajax({
cache: true,
type: "POST",
url: "/novel/userFeedback/save",
data: $('#signupForm').serialize(),// 你的formid
async: false,
error: function (request) {
parent.layer.alert("Connection error");
},
success: function (data) {
if (data.code == 0) {
parent.layer.msg("操作成功");
parent.reLoad();
var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引
parent.layer.close(index);
} else {
parent.layer.alert(data.msg)
}
}
});
}
function validateRule() {
var icon = "<i class='fa fa-times-circle'></i> ";
$("#signupForm").validate({
ignore: "",
rules: {
},
messages: {
}
})
}

View File

@ -0,0 +1,103 @@
var E = window.wangEditor;
$("[id^='contentEditor']").each(function (index, ele) {
var relName = $(ele).attr("id").substring(13);
var editor = new E('#contentEditor' + relName);
// 自定义菜单配置
editor.customConfig.menus = [
'head', // 标题
'bold', // 粗体
'fontSize', // 字号
'fontName', // 字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
'foreColor', // 文字颜色
//'backColor', // 背景颜色
//'link', // 插入链接
'list', // 列表
'justify', // 对齐方式
'quote', // 引用
'emoticon', // 表情
'image', // 插入图片
//'table', // 表格
//'video', // 插入视频
//'code', // 插入代码
'undo', // 撤销
'redo' // 重复
];
editor.customConfig.onchange = function (html) {
// html 即变化之后的内容
$("#" + relName).val(html);
}
editor.customConfig.uploadImgShowBase64 = true;
editor.create();
editor.txt.html($("#" + relName).val());
})
$("[id^='picImage']").each(function (index, ele) {
var relName = $(ele).attr("id").substring(8);
layui.use('upload', function () {
var upload = layui.upload;
//执行实例
var uploadInst = upload.render({
elem: '#picImage' + relName, //绑定元素
url: '/common/sysFile/upload', //上传接口
size: 1000,
accept: 'file',
done: function (r) {
$("#picImage" + relName).attr("src", r.fileName);
$("#" + relName).val(r.fileName);
},
error: function (r) {
layer.msg(r.msg);
}
});
});
});
$().ready(function () {
validateRule();
});
$.validator.setDefaults({
submitHandler: function () {
update();
}
});
function update() {
$.ajax({
cache: true,
type: "POST",
url: "/novel/userFeedback/update",
data: $('#signupForm').serialize(),// 你的formid
async: false,
error: function (request) {
parent.layer.alert("Connection error");
},
success: function (data) {
if (data.code == 0) {
parent.layer.msg("操作成功");
parent.reLoad();
var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引
parent.layer.close(index);
} else {
parent.layer.alert(data.msg)
}
}
});
}
function validateRule() {
var icon = "<i class='fa fa-times-circle'></i> ";
$("#signupForm").validate({
ignore: "",
rules: {
},
messages: {
}
})
}

View File

@ -0,0 +1,177 @@
var prefix = "/novel/userFeedback"
$(function () {
load();
});
function load() {
$('#exampleTable')
.bootstrapTable(
{
method: 'get', // 服务器数据的请求方式 get or post
url: prefix + "/list", // 服务器数据的加载地址
// showRefresh : true,
// showToggle : true,
// showColumns : true,
iconSize: 'outline',
toolbar: '#exampleToolbar',
striped: true, // 设置为true会有隔行变色效果
dataType: "json", // 服务器返回的数据类型
pagination: true, // 设置为true会在底部显示分页条
// queryParamsType : "limit",
// //设置为limit则会发送符合RESTFull格式的参数
singleSelect: false, // 设置为true将禁止多选
// contentType : "application/x-www-form-urlencoded",
// //发送到服务器的数据编码类型
pageSize: 10, // 如果设置了分页,每页数据条数
pageNumber: 1, // 如果设置了分布,首页页码
//search : true, // 是否显示搜索框
showColumns: false, // 是否显示内容下拉框(选择显示的列)
sidePagination: "server", // 设置在哪里进行分页,可选值为"client" 或者 "server"
queryParams: function (params) {
//说明传入后台的参数包括offset开始索引limit步长sort排序列orderdesc或者,以及所有列的键值对
var queryParams = getFormJson("searchForm");
queryParams.limit = params.limit;
queryParams.offset = params.offset;
return queryParams;
},
// //请求服务器数据时,你可以通过重写参数的方式添加一些额外的参数,例如 toolbar 中的参数 如果
// queryParamsType = 'limit' ,返回参数必须包含
// limit, offset, search, sort, order 否则, 需要包含:
// pageSize, pageNumber, searchText, sortName,
// sortOrder.
// 返回false将会终止请求
responseHandler: function (rs) {
if (rs.code == 0) {
return rs.data;
} else {
parent.layer.alert(rs.msg)
return {total: 0, rows: []};
}
},
columns: [
{
title: '序号',
formatter: function () {
return arguments[2] + 1;
}
},
{
field: 'userName',
title: '反馈用户'
},
{
field: 'content',
title: '反馈内容'
},
{
field: 'createTime',
title: '反馈时间'
}
]
});
}
function reLoad() {
$('#exampleTable').bootstrapTable('refresh');
}
function add() {
layer.open({
type: 2,
title: '增加',
maxmin: true,
shadeClose: false, // 点击遮罩关闭层
area: ['800px', '520px'],
content: prefix + '/add' // iframe的url
});
}
function detail(id) {
layer.open({
type: 2,
title: '详情',
maxmin: true,
shadeClose: false, // 点击遮罩关闭层
area: ['800px', '520px'],
content: prefix + '/detail/' + id // iframe的url
});
}
function edit(id) {
layer.open({
type: 2,
title: '编辑',
maxmin: true,
shadeClose: false, // 点击遮罩关闭层
area: ['800px', '520px'],
content: prefix + '/edit/' + id // iframe的url
});
}
function remove(id) {
layer.confirm('确定要删除选中的记录', {
btn: ['确定', '取消']
}, function () {
$.ajax({
url: prefix + "/remove",
type: "post",
data: {
'id': id
},
success: function (r) {
if (r.code == 0) {
layer.msg(r.msg);
reLoad();
} else {
layer.msg(r.msg);
}
}
});
})
}
function resetPwd(id) {
}
function batchRemove() {
var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行,当没有选择的记录时,返回一个空数组
if (rows.length == 0) {
layer.msg("请选择要删除的数据");
return;
}
layer.confirm("确认要删除选中的'" + rows.length + "'条数据吗?", {
btn: ['确定', '取消']
// 按钮
}, function () {
var ids = new Array();
// 遍历所有选择的行数据取每条数据对应的ID
$.each(rows, function (i, row) {
ids[i] = row['id'];
});
$.ajax({
type: 'POST',
data: {
"ids": ids
},
url: prefix + '/batchRemove',
success: function (r) {
if (r.code == 0) {
layer.msg(r.msg);
reLoad();
} else {
layer.msg(r.msg);
}
}
});
}, function () {
});
}

View File

@ -0,0 +1,18 @@
-- 菜单SQL
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES ('1', '首页小说设置表', 'novel/bookSetting', 'novel:bookSetting:bookSetting', '1', 'fa', '6');
-- 按钮父菜单ID
set @parentId = @@identity;
-- 菜单对应按钮SQL
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '查看', null, 'novel:bookSetting:detail', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '新增', null, 'novel:bookSetting:add', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '修改', null, 'novel:bookSetting:edit', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '删除', null, 'novel:bookSetting:remove', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '批量删除', null, 'novel:bookSetting:batchRemove', '2', null, '6';

View File

@ -0,0 +1,18 @@
-- 菜单SQL
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES ('1', '', 'novel/userFeedback', 'novel:userFeedback:userFeedback', '1', 'fa', '6');
-- 按钮父菜单ID
set @parentId = @@identity;
-- 菜单对应按钮SQL
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '查看', null, 'novel:userFeedback:detail', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '新增', null, 'novel:userFeedback:add', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '修改', null, 'novel:userFeedback:edit', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '删除', null, 'novel:userFeedback:remove', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '批量删除', null, 'novel:userFeedback:batchRemove', '2', null, '6';

View File

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
<div class="wrapper wrapper-content ">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-content">
<form class="form-horizontal m-t" id="signupForm">
<div class="form-group">
<label class="col-sm-3 control-label">小说ID</label>
<div class="col-sm-8">
<input id="bookId" name="bookId"
class="form-control"
type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">排序号:</label>
<div class="col-sm-8">
<input id="sort" name="sort"
class="form-control"
type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">推荐类型:</label>
<div class="col-sm-8">
<select data-placeholder="--选择--" id="type"
name="type"
class="form-control chosen-select" tabindex="2"
dict-type="book_rec_type">
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-8 col-sm-offset-3">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div th:include="include::footer"></div>
<script type="text/javascript" src="/wangEditor/release/wangEditor.js"></script>
<script type="text/javascript" src="/js/appjs/novel/bookSetting/add.js">
</script>
</body>
</html>

View File

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
<div class="wrapper wrapper-content ">
<div class="col-sm-12">
<div class="ibox">
<div class="ibox-body">
<div class="fixed-table-toolbar">
<div class="columns pull-right">
<button class="btn btn-success" onclick="reLoad()">查询</button>
</div>
<form id="searchForm">
<div class="columns pull-right col-md-2">
<select data-placeholder="--推荐类型--" id="type"
name="type"
class="form-control chosen-select" tabindex="2"
dict-type="book_rec_type">
</select>
</div>
</form>
</div>
<table id="exampleTable" data-mobile-responsive="true">
</table>
</div>
</div>
</div>
</div>
<!--shiro控制bootstraptable行内按钮看见性 -->
<div>
<script type="text/javascript">
var s_detail_h = 'hidden';
var s_edit_h = 'hidden';
var s_remove_h = 'hidden';
</script>
</div>
<div shiro:hasPermission="test:order:detail">
<script type="text/javascript">
s_detail_h = '';
</script>
</div>
<div shiro:hasPermission="novel:bookSetting:edit">
<script type="text/javascript">
s_edit_h = '';
</script>
</div>
<div shiro:hasPermission="novel:bookSetting:remove">
<script type="text/javascript">
var s_remove_h = '';
</script>
</div>
<div th:include="include :: footer"></div>
<script type="text/javascript" src="/js/appjs/novel/bookSetting/bookSetting.js"></script>
</body>
</html>

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