Compare commits

...

20 Commits

Author SHA1 Message Date
4aa6b82143 更新书趣阁规则 2020-05-18 20:13:46 +08:00
c80b02caf0 v2.0.2发布 2020-05-18 17:31:00 +08:00
5e16119880 增加笔趣阁书源 2020-05-18 17:08:43 +08:00
231b94f1da v2.0.2发布 2020-05-18 14:51:02 +08:00
92ce982899 1.优化爬虫编写规则,兼容更多网站 2.新增书趣阁书源 2020-05-18 14:01:49 +08:00
8c2e43c04f Merge branch 'master' into release_v2.0.1 2020-05-17 22:21:50 +08:00
f553d23fb9 v2.0.1发布 2020-05-17 22:14:53 +08:00
xxy
9773b73475 修改版本号 2020-05-16 13:29:32 +08:00
xxy
5543b905cd 小说发布防xss攻击 2020-05-16 13:20:08 +08:00
xxy
e273906441 小说发布防xss攻击 2020-05-16 13:05:44 +08:00
xxy
83dc04c50b Merge branch 'develop' of https://gitee.com/xiongxyang/novel-plus into develop 2020-05-16 12:05:33 +08:00
xxy
b4f5b18e93 1.修复昵称修改不会显示在顶部栏的问题
2.修复底部作者专区超链接问题
2020-05-16 12:01:02 +08:00
fe80c21812 Merge branch 'develop' of https://gitee.com/xiongxyang/novel-plus into develop 2020-05-16 11:46:11 +08:00
4c2a7f12c1 gitignore add file 2020-05-16 11:44:33 +08:00
xxy
e24e87b546 修复性别修改问题 2020-05-16 03:05:49 +08:00
xxy
b8b074d40a v2.0.0版本发布 2020-05-14 07:18:17 +08:00
xxy
a662f42bcf 修改版本号 2020-05-13 22:35:25 +08:00
xxy
0fa929f9de 用户购买功能实现 2020-05-13 21:43:07 +08:00
xxy
401d23871d 作家专区开发实现 2020-05-13 19:45:57 +08:00
xxy
4878f17de8 更新版本号 2020-05-11 22:36:06 +08:00
259 changed files with 43266 additions and 226 deletions

3
.gitignore vendored
View File

@ -13,3 +13,6 @@
/novel-admin/target
/*.iml
/novel-admin/*.iml
.DS_Store
/novel-admin/cachedata
/novel-admin/logs

View File

@ -24,9 +24,9 @@
- [x] 排行榜
- [x] 小说评论模块
- [x] 阅读主题模块
- [ ] 作家专区
- [x] 作家专区
- [x] 充值
- [ ] 后台管理系统
- [x] 后台管理系统
- [x] 爬虫管理系统
#### 项目结构
@ -44,17 +44,47 @@ Springboot+Mybatis+Mysql+Ehcache+Thymeleaf+Layui
#### PC站截图
1. 首页
![img](https://oscimg.oschina.net/oscnet/up-bbb1c7f72e183327bff754a9fa8bb75223e.png)
![index](./assets/1588548668698.gif)
2. 分类索引页
![img](https://oscimg.oschina.net/oscnet/up-d0b2e03129bfae47b8bb96a491b73d383c5.png)
3. 排行榜
![index](./assets/1588548784395.gif)
![img](https://oscimg.oschina.net/oscnet/up-78d5a68586cd92a86c669311f414508f922.png)
4. 详情页
![img](https://oscimg.oschina.net/oscnet/up-8be2495a2869f93626b0c9c1df6f329747a.png)
![index](./assets/1588548916980.gif)
5. 阅读页
![img](https://oscimg.oschina.net/oscnet/up-517c84148d2db8e11717a8bbecc57fa1be7.png)
6. 用户中心
![img](https://oscimg.oschina.net/oscnet/up-805a30e7a663a3fd5cb39a7ea26bc132a01.png)
7. 充值
![img](https://oscimg.oschina.net/oscnet/up-5a601b0b3af3224d0bebcfe12fc15075d34.png)
![img](https://oscimg.oschina.net/oscnet/up-face25d02c07b05b2ce954cc4bf4ee6a0cc.png)
8.作家专区
![img](https://oscimg.oschina.net/oscnet/up-30766372cc7f56480ff1d7d55198204f6ea.png)
![img](https://oscimg.oschina.net/oscnet/up-9737995e465b86f3bee3211221f6c3b8a56.png)
9.购买
![img](https://oscimg.oschina.net/oscnet/up-ce0f585efd82a9670335f118cf5897c85e9.png)
![img](https://oscimg.oschina.net/oscnet/up-f849960f4c1303fea77d26e64fc505a7180.png)
@ -86,7 +116,11 @@ Springboot+Mybatis+Mysql+Ehcache+Thymeleaf+Layui
![QQ图片20191018161901](./assets/crawl_index.png)
#### 后台管理系统截图
![img](https://oscimg.oschina.net/oscnet/up-0552343538674a22a64819834100558f39b.png)
![img](https://oscimg.oschina.net/oscnet/up-faf5dda7320674c29a1772bc0c81d74762e.png)
#### 安装步骤
@ -127,7 +161,7 @@ docker安装教程[点击前往](https://my.oschina.net/java2nb/blog/4271989)
#### QQ交流群
![mini-code](./assets/qq_group.png)
![mini-code](./assets/小说精品屋开源项目交流群群聊二维码.png)
#### 捐赠支持

View File

@ -0,0 +1,8 @@
2020-05-13 21:52:00,972 INFO (StartupInfoLogger.java:50)- Starting TestDemo on USER-20180729KA with PID 3532 (started by Administrator in E:\baseprojectparent\novel-plus\novel-admin)
2020-05-13 21:52:01,113 DEBUG (StartupInfoLogger.java:53)- Running with Spring Boot v2.0.1.RELEASE, Spring v5.0.5.RELEASE
2020-05-13 21:52:01,131 INFO (SpringApplication.java:663)- The following profiles are active: dev
2020-05-13 21:52:54,469 DEBUG (ApplicationContextRegister.java:29)- ApplicationContext registed-->org.springframework.web.context.support.GenericWebApplicationContext@5b529706: startup date [Wed May 13 21:52:01 CST 2020]; root of context hierarchy
2020-05-13 21:53:49,622 INFO (StartupInfoLogger.java:59)- Started TestDemo in 114.268 seconds (JVM running for 124.957)
2020-05-18 09:48:03,219 INFO (StartupInfoLogger.java:50)- Starting TestDemo on DESKTOP-CPCLUI6 with PID 13172 (started by 11797 in D:\gitee\novel-plus\novel-admin)
2020-05-18 09:48:03,223 DEBUG (StartupInfoLogger.java:53)- Running with Spring Boot v2.0.1.RELEASE, Spring v5.0.5.RELEASE
2020-05-18 09:48:03,227 INFO (SpringApplication.java:663)- The following profiles are active: dev

View File

@ -50,10 +50,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- NekoHTML 是一个简单地HTML扫描器和标签补偿器(tag balancer) ,使得程序能解析HTML文档并用标准的XML接口来访问其中的信息
这个解析器能投扫描HTML文件并修正许多作者人或机器在编写HTML文档过程中常犯的错误
NekoHTML 能增补缺失的父元素自动用结束标签关闭相应的元素以及不匹配的内嵌元素标签
NekoHTML 的开发使用了Xerces Native Interface (XNI)后者是Xerces2的实现基础-->
<!-- NekoHTML 是一个简单地HTML扫描器和标签补偿器(tag balancer) ,使得程序能解析HTML文档并用标准的XML接口来访问其中的信息
这个解析器能投扫描HTML文件并修正许多作者人或机器在编写HTML文档过程中常犯的错误
NekoHTML 能增补缺失的父元素自动用结束标签关闭相应的元素以及不匹配的内嵌元素标签
NekoHTML 的开发使用了Xerces Native Interface (XNI)后者是Xerces2的实现基础-->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
@ -147,13 +147,13 @@
<!--</dependency>-->
<!-- quartz -->
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-cache</artifactId>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-cache</artifactId>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>net.sf.ehcache</groupId>-->
<!--<artifactId>ehcache</artifactId>-->
<!--<groupId>net.sf.ehcache</groupId>-->
<!--<artifactId>ehcache</artifactId>-->
<!--</dependency>-->
@ -188,7 +188,6 @@
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@ -239,18 +238,22 @@
</configuration>
</plugin>-->
<!--SpringBoot项目默认使用spring-boot-maven-plugin要打成被其他项目引用的jar包需要更换此插件-->
<!-- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<distributionManagement>
<!--<distributionManagement>
<repository>
<id>nexus_release</id>
<name>release</name>
@ -261,5 +264,5 @@
<name>snapshots</name>
<url>http://47.106.243.172:8081/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
</distributionManagement>-->
</project>

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.AuthorCodeDO;
import com.java2nb.novel.service.AuthorCodeService;
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 2020-05-13 11:29:15
*/
@Controller
@RequestMapping("/novel/authorCode")
public class AuthorCodeController {
@Autowired
private AuthorCodeService authorCodeService;
@GetMapping()
@RequiresPermissions("novel:authorCode:authorCode")
String AuthorCode() {
return "novel/authorCode/authorCode";
}
@ApiOperation(value = "获取作家邀请码表列表", notes = "获取作家邀请码表列表")
@ResponseBody
@GetMapping("/list")
@RequiresPermissions("novel:authorCode:authorCode")
public R list(@RequestParam Map<String, Object> params) {
//查询列表数据
Query query = new Query(params);
List<AuthorCodeDO> authorCodeList = authorCodeService.list(query);
int total = authorCodeService.count(query);
PageBean pageBean = new PageBean(authorCodeList, total);
return R.ok().put("data", pageBean);
}
@ApiOperation(value = "新增作家邀请码表页面", notes = "新增作家邀请码表页面")
@GetMapping("/add")
@RequiresPermissions("novel:authorCode:add")
String add() {
return "novel/authorCode/add";
}
@ApiOperation(value = "修改作家邀请码表页面", notes = "修改作家邀请码表页面")
@GetMapping("/edit/{id}")
@RequiresPermissions("novel:authorCode:edit")
String edit(@PathVariable("id") Long id, Model model) {
AuthorCodeDO authorCode = authorCodeService.get(id);
model.addAttribute("authorCode", authorCode);
return "novel/authorCode/edit";
}
@ApiOperation(value = "查看作家邀请码表页面", notes = "查看作家邀请码表页面")
@GetMapping("/detail/{id}")
@RequiresPermissions("novel:authorCode:detail")
String detail(@PathVariable("id") Long id, Model model) {
AuthorCodeDO authorCode = authorCodeService.get(id);
model.addAttribute("authorCode", authorCode);
return "novel/authorCode/detail";
}
/**
* 保存
*/
@ApiOperation(value = "新增作家邀请码表", notes = "新增作家邀请码表")
@ResponseBody
@PostMapping("/save")
@RequiresPermissions("novel:authorCode:add")
public R save( AuthorCodeDO authorCode) {
if (authorCodeService.save(authorCode) > 0) {
return R.ok();
}
return R.error();
}
/**
* 修改
*/
@ApiOperation(value = "修改作家邀请码表", notes = "修改作家邀请码表")
@ResponseBody
@RequestMapping("/update")
@RequiresPermissions("novel:authorCode:edit")
public R update( AuthorCodeDO authorCode) {
authorCodeService.update(authorCode);
return R.ok();
}
/**
* 删除
*/
@ApiOperation(value = "删除作家邀请码表", notes = "删除作家邀请码表")
@PostMapping("/remove")
@ResponseBody
@RequiresPermissions("novel:authorCode:remove")
public R remove( Long id) {
if (authorCodeService.remove(id) > 0) {
return R.ok();
}
return R.error();
}
/**
* 删除
*/
@ApiOperation(value = "批量删除作家邀请码表", notes = "批量删除作家邀请码表")
@PostMapping("/batchRemove")
@ResponseBody
@RequiresPermissions("novel:authorCode:batchRemove")
public R remove(@RequestParam("ids[]") Long[] ids) {
authorCodeService.batchRemove(ids);
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.AuthorDO;
import com.java2nb.novel.service.AuthorService;
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 2020-05-13 11:16:51
*/
@Controller
@RequestMapping("/novel/author")
public class AuthorController {
@Autowired
private AuthorService authorService;
@GetMapping()
@RequiresPermissions("novel:author:author")
String Author() {
return "novel/author/author";
}
@ApiOperation(value = "获取作者表列表", notes = "获取作者表列表")
@ResponseBody
@GetMapping("/list")
@RequiresPermissions("novel:author:author")
public R list(@RequestParam Map<String, Object> params) {
//查询列表数据
Query query = new Query(params);
List<AuthorDO> authorList = authorService.list(query);
int total = authorService.count(query);
PageBean pageBean = new PageBean(authorList, total);
return R.ok().put("data", pageBean);
}
@ApiOperation(value = "新增作者表页面", notes = "新增作者表页面")
@GetMapping("/add")
@RequiresPermissions("novel:author:add")
String add() {
return "novel/author/add";
}
@ApiOperation(value = "修改作者表页面", notes = "修改作者表页面")
@GetMapping("/edit/{id}")
@RequiresPermissions("novel:author:edit")
String edit(@PathVariable("id") Long id, Model model) {
AuthorDO author = authorService.get(id);
model.addAttribute("author", author);
return "novel/author/edit";
}
@ApiOperation(value = "查看作者表页面", notes = "查看作者表页面")
@GetMapping("/detail/{id}")
@RequiresPermissions("novel:author:detail")
String detail(@PathVariable("id") Long id, Model model) {
AuthorDO author = authorService.get(id);
model.addAttribute("author", author);
return "novel/author/detail";
}
/**
* 保存
*/
@ApiOperation(value = "新增作者表", notes = "新增作者表")
@ResponseBody
@PostMapping("/save")
@RequiresPermissions("novel:author:add")
public R save( AuthorDO author) {
if (authorService.save(author) > 0) {
return R.ok();
}
return R.error();
}
/**
* 修改
*/
@ApiOperation(value = "修改作者表", notes = "修改作者表")
@ResponseBody
@RequestMapping("/update")
@RequiresPermissions("novel:author:edit")
public R update( AuthorDO author) {
authorService.update(author);
return R.ok();
}
/**
* 删除
*/
@ApiOperation(value = "删除作者表", notes = "删除作者表")
@PostMapping("/remove")
@ResponseBody
@RequiresPermissions("novel:author:remove")
public R remove( Long id) {
if (authorService.remove(id) > 0) {
return R.ok();
}
return R.error();
}
/**
* 删除
*/
@ApiOperation(value = "批量删除作者表", notes = "批量删除作者表")
@PostMapping("/batchRemove")
@ResponseBody
@RequiresPermissions("novel:author:batchRemove")
public R remove(@RequestParam("ids[]") Long[] ids) {
authorService.batchRemove(ids);
return R.ok();
}
}

View File

@ -0,0 +1,32 @@
package com.java2nb.novel.dao;
import com.java2nb.novel.domain.AuthorCodeDO;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
/**
* 作家邀请码表
* @author xiongxy
* @email 1179705413@qq.com
* @date 2020-05-13 11:29:15
*/
@Mapper
public interface AuthorCodeDao {
AuthorCodeDO get(Long id);
List<AuthorCodeDO> list(Map<String,Object> map);
int count(Map<String,Object> map);
int save(AuthorCodeDO authorCode);
int update(AuthorCodeDO authorCode);
int remove(Long id);
int batchRemove(Long[] ids);
}

View File

@ -0,0 +1,32 @@
package com.java2nb.novel.dao;
import com.java2nb.novel.domain.AuthorDO;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
/**
* 作者表
* @author xiongxy
* @email 1179705413@qq.com
* @date 2020-05-13 11:16:51
*/
@Mapper
public interface AuthorDao {
AuthorDO get(Long id);
List<AuthorDO> list(Map<String,Object> map);
int count(Map<String,Object> map);
int save(AuthorDO author);
int update(AuthorDO author);
int remove(Long id);
int batchRemove(Long[] ids);
}

View File

@ -0,0 +1,121 @@
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.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* 作家邀请码表
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2020-05-13 11:29:15
*/
public class AuthorCodeDO implements Serializable {
private static final long serialVersionUID = 1L;
//主键
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long id;
//邀请码
private String inviteCode;
//有效时间
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date validityTime;
//是否使用过0未使用1:使用过
private Integer isUse;
//创建时间
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
//创建人ID
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long createUserId;
/**
* 设置:主键
*/
public void setId(Long id) {
this.id = id;
}
/**
* 获取:主键
*/
public Long getId() {
return id;
}
/**
* 设置:邀请码
*/
public void setInviteCode(String inviteCode) {
this.inviteCode = inviteCode;
}
/**
* 获取:邀请码
*/
public String getInviteCode() {
return inviteCode;
}
/**
* 设置:有效时间
*/
public void setValidityTime(Date validityTime) {
this.validityTime = validityTime;
}
/**
* 获取:有效时间
*/
public Date getValidityTime() {
return validityTime;
}
/**
* 设置是否使用过0未使用1:使用过
*/
public void setIsUse(Integer isUse) {
this.isUse = isUse;
}
/**
* 获取是否使用过0未使用1:使用过
*/
public Integer getIsUse() {
return isUse;
}
/**
* 设置:创建时间
*/
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;
}
}

View File

@ -0,0 +1,176 @@
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.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* 作者表
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2020-05-13 11:16:51
*/
public class AuthorDO 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 userId;
//邀请码
private String inviteCode;
//笔名
private String penName;
//手机号码
private String telPhone;
//QQ或微信账号
private String chatAccount;
//电子邮箱
private String email;
//作品方向0男频1女频
private Integer workDirection;
//创建时间
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
//0正常1封禁
private Integer status;
/**
* 设置:主键
*/
public void setId(Long id) {
this.id = id;
}
/**
* 获取:主键
*/
public Long getId() {
return id;
}
/**
* 设置用户ID
*/
public void setUserId(Long userId) {
this.userId = userId;
}
/**
* 获取用户ID
*/
public Long getUserId() {
return userId;
}
/**
* 设置:邀请码
*/
public void setInviteCode(String inviteCode) {
this.inviteCode = inviteCode;
}
/**
* 获取:邀请码
*/
public String getInviteCode() {
return inviteCode;
}
/**
* 设置:笔名
*/
public void setPenName(String penName) {
this.penName = penName;
}
/**
* 获取:笔名
*/
public String getPenName() {
return penName;
}
/**
* 设置:手机号码
*/
public void setTelPhone(String telPhone) {
this.telPhone = telPhone;
}
/**
* 获取:手机号码
*/
public String getTelPhone() {
return telPhone;
}
/**
* 设置QQ或微信账号
*/
public void setChatAccount(String chatAccount) {
this.chatAccount = chatAccount;
}
/**
* 获取QQ或微信账号
*/
public String getChatAccount() {
return chatAccount;
}
/**
* 设置:电子邮箱
*/
public void setEmail(String email) {
this.email = email;
}
/**
* 获取:电子邮箱
*/
public String getEmail() {
return email;
}
/**
* 设置作品方向0男频1女频
*/
public void setWorkDirection(Integer workDirection) {
this.workDirection = workDirection;
}
/**
* 获取作品方向0男频1女频
*/
public Integer getWorkDirection() {
return workDirection;
}
/**
* 设置:创建时间
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* 获取:创建时间
*/
public Date getCreateTime() {
return createTime;
}
/**
* 设置0正常1封禁
*/
public void setStatus(Integer status) {
this.status = status;
}
/**
* 获取0正常1封禁
*/
public Integer getStatus() {
return status;
}
}

View File

@ -0,0 +1,30 @@
package com.java2nb.novel.service;
import com.java2nb.novel.domain.AuthorCodeDO;
import java.util.List;
import java.util.Map;
/**
* 作家邀请码表
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2020-05-13 11:29:15
*/
public interface AuthorCodeService {
AuthorCodeDO get(Long id);
List<AuthorCodeDO> list(Map<String, Object> map);
int count(Map<String, Object> map);
int save(AuthorCodeDO authorCode);
int update(AuthorCodeDO authorCode);
int remove(Long id);
int batchRemove(Long[] ids);
}

View File

@ -0,0 +1,30 @@
package com.java2nb.novel.service;
import com.java2nb.novel.domain.AuthorDO;
import java.util.List;
import java.util.Map;
/**
* 作者表
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2020-05-13 11:16:51
*/
public interface AuthorService {
AuthorDO get(Long id);
List<AuthorDO> list(Map<String, Object> map);
int count(Map<String, Object> map);
int save(AuthorDO author);
int update(AuthorDO author);
int remove(Long id);
int batchRemove(Long[] ids);
}

View File

@ -0,0 +1,60 @@
package com.java2nb.novel.service.impl;
import com.java2nb.common.utils.ShiroUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.java2nb.novel.dao.AuthorCodeDao;
import com.java2nb.novel.domain.AuthorCodeDO;
import com.java2nb.novel.service.AuthorCodeService;
@Service
public class AuthorCodeServiceImpl implements AuthorCodeService {
@Autowired
private AuthorCodeDao authorCodeDao;
@Override
public AuthorCodeDO get(Long id){
return authorCodeDao.get(id);
}
@Override
public List<AuthorCodeDO> list(Map<String, Object> map){
return authorCodeDao.list(map);
}
@Override
public int count(Map<String, Object> map){
return authorCodeDao.count(map);
}
@Override
public int save(AuthorCodeDO authorCode){
authorCode.setIsUse(0);
authorCode.setCreateTime(new Date());
authorCode.setCreateUserId(ShiroUtils.getUserId());
return authorCodeDao.save(authorCode);
}
@Override
public int update(AuthorCodeDO authorCode){
return authorCodeDao.update(authorCode);
}
@Override
public int remove(Long id){
return authorCodeDao.remove(id);
}
@Override
public int batchRemove(Long[] ids){
return authorCodeDao.batchRemove(ids);
}
}

View File

@ -0,0 +1,55 @@
package com.java2nb.novel.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import com.java2nb.novel.dao.AuthorDao;
import com.java2nb.novel.domain.AuthorDO;
import com.java2nb.novel.service.AuthorService;
@Service
public class AuthorServiceImpl implements AuthorService {
@Autowired
private AuthorDao authorDao;
@Override
public AuthorDO get(Long id){
return authorDao.get(id);
}
@Override
public List<AuthorDO> list(Map<String, Object> map){
return authorDao.list(map);
}
@Override
public int count(Map<String, Object> map){
return authorDao.count(map);
}
@Override
public int save(AuthorDO author){
return authorDao.save(author);
}
@Override
public int update(AuthorDO author){
return authorDao.update(author);
}
@Override
public int remove(Long id){
return authorDao.remove(id);
}
@Override
public int batchRemove(Long[] ids){
return authorDao.batchRemove(ids);
}
}

View File

@ -10,9 +10,9 @@ spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://128.0.0.1:3306/novel_biz?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: test123456
password:
#password:
initialSize: 1
minIdle: 3

View File

@ -3,7 +3,7 @@ server:
# tomcat:
# max-threads: 1000
# min-spare-threads: 30
port: 8082
port: 80
# uri-encoding: utf-8
#security:
# basic:

View File

@ -0,0 +1,108 @@
<?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.AuthorCodeDao">
<select id="get" resultType="com.java2nb.novel.domain.AuthorCodeDO">
select `id`,`invite_code`,`validity_time`,`is_use`,`create_time`,`create_user_id` from author_code where id = #{value}
</select>
<select id="list" resultType="com.java2nb.novel.domain.AuthorCodeDO">
select `id`,`invite_code`,`validity_time`,`is_use`,`create_time`,`create_user_id` from author_code
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="inviteCode != null and inviteCode != ''"> and invite_code = #{inviteCode} </if>
<if test="validityTime != null and validityTime != ''"> and validity_time = #{validityTime} </if>
<if test="isUse != null and isUse != ''"> and is_use = #{isUse} </if>
<if test="createTime != null and createTime != ''"> and create_time = #{createTime} </if>
<if test="createUserId != null and createUserId != ''"> and create_user_id = #{createUserId} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by create_time desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from author_code
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="inviteCode != null and inviteCode != ''"> and invite_code = #{inviteCode} </if>
<if test="validityTime != null and validityTime != ''"> and validity_time = #{validityTime} </if>
<if test="isUse != null and isUse != ''"> and is_use = #{isUse} </if>
<if test="createTime != null and createTime != ''"> and create_time = #{createTime} </if>
<if test="createUserId != null and createUserId != ''"> and create_user_id = #{createUserId} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.novel.domain.AuthorCodeDO" useGeneratedKeys="true" keyProperty="id">
insert into author_code
(
`invite_code`,
`validity_time`,
`is_use`,
`create_time`,
`create_user_id`
)
values
(
#{inviteCode},
#{validityTime},
#{isUse},
#{createTime},
#{createUserId}
)
</insert>
<insert id="saveSelective" parameterType="com.java2nb.novel.domain.AuthorCodeDO" useGeneratedKeys="true" keyProperty="id">
insert into author_code
(
<if test="id != null"> `id`, </if>
<if test="inviteCode != null"> `invite_code`, </if>
<if test="validityTime != null"> `validity_time`, </if>
<if test="isUse != null"> `is_use`, </if>
<if test="createTime != null"> `create_time`, </if>
<if test="createUserId != null"> `create_user_id` </if>
)
values
(
<if test="id != null"> #{id}, </if>
<if test="inviteCode != null"> #{inviteCode}, </if>
<if test="validityTime != null"> #{validityTime}, </if>
<if test="isUse != null"> #{isUse}, </if>
<if test="createTime != null"> #{createTime}, </if>
<if test="createUserId != null"> #{createUserId} </if>
)
</insert>
<update id="update" parameterType="com.java2nb.novel.domain.AuthorCodeDO">
update author_code
<set>
<if test="inviteCode != null">`invite_code` = #{inviteCode}, </if>
<if test="validityTime != null">`validity_time` = #{validityTime}, </if>
<if test="isUse != null">`is_use` = #{isUse}, </if>
<if test="createTime != null">`create_time` = #{createTime}, </if>
<if test="createUserId != null">`create_user_id` = #{createUserId}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from author_code where id = #{value}
</delete>
<delete id="batchRemove">
delete from author_code where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,136 @@
<?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.AuthorDao">
<select id="get" resultType="com.java2nb.novel.domain.AuthorDO">
select `id`,`user_id`,`invite_code`,`pen_name`,`tel_phone`,`chat_account`,`email`,`work_direction`,`create_time`,`status` from author where id = #{value}
</select>
<select id="list" resultType="com.java2nb.novel.domain.AuthorDO">
select `id`,`user_id`,`invite_code`,`pen_name`,`tel_phone`,`chat_account`,`email`,`work_direction`,`create_time`,`status` from author
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="userId != null and userId != ''"> and user_id = #{userId} </if>
<if test="inviteCode != null and inviteCode != ''"> and invite_code = #{inviteCode} </if>
<if test="penName != null and penName != ''"> and pen_name = #{penName} </if>
<if test="telPhone != null and telPhone != ''"> and tel_phone = #{telPhone} </if>
<if test="chatAccount != null and chatAccount != ''"> and chat_account = #{chatAccount} </if>
<if test="email != null and email != ''"> and email = #{email} </if>
<if test="workDirection != null and workDirection != ''"> and work_direction = #{workDirection} </if>
<if test="createTime != null and createTime != ''"> and create_time = #{createTime} </if>
<if test="status != null and status != ''"> and status = #{status} </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 author
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="userId != null and userId != ''"> and user_id = #{userId} </if>
<if test="inviteCode != null and inviteCode != ''"> and invite_code = #{inviteCode} </if>
<if test="penName != null and penName != ''"> and pen_name = #{penName} </if>
<if test="telPhone != null and telPhone != ''"> and tel_phone = #{telPhone} </if>
<if test="chatAccount != null and chatAccount != ''"> and chat_account = #{chatAccount} </if>
<if test="email != null and email != ''"> and email = #{email} </if>
<if test="workDirection != null and workDirection != ''"> and work_direction = #{workDirection} </if>
<if test="createTime != null and createTime != ''"> and create_time = #{createTime} </if>
<if test="status != null and status != ''"> and status = #{status} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.novel.domain.AuthorDO" useGeneratedKeys="true" keyProperty="id">
insert into author
(
`user_id`,
`invite_code`,
`pen_name`,
`tel_phone`,
`chat_account`,
`email`,
`work_direction`,
`create_time`,
`status`
)
values
(
#{userId},
#{inviteCode},
#{penName},
#{telPhone},
#{chatAccount},
#{email},
#{workDirection},
#{createTime},
#{status}
)
</insert>
<insert id="saveSelective" parameterType="com.java2nb.novel.domain.AuthorDO" useGeneratedKeys="true" keyProperty="id">
insert into author
(
<if test="id != null"> `id`, </if>
<if test="userId != null"> `user_id`, </if>
<if test="inviteCode != null"> `invite_code`, </if>
<if test="penName != null"> `pen_name`, </if>
<if test="telPhone != null"> `tel_phone`, </if>
<if test="chatAccount != null"> `chat_account`, </if>
<if test="email != null"> `email`, </if>
<if test="workDirection != null"> `work_direction`, </if>
<if test="createTime != null"> `create_time`, </if>
<if test="status != null"> `status` </if>
)
values
(
<if test="id != null"> #{id}, </if>
<if test="userId != null"> #{userId}, </if>
<if test="inviteCode != null"> #{inviteCode}, </if>
<if test="penName != null"> #{penName}, </if>
<if test="telPhone != null"> #{telPhone}, </if>
<if test="chatAccount != null"> #{chatAccount}, </if>
<if test="email != null"> #{email}, </if>
<if test="workDirection != null"> #{workDirection}, </if>
<if test="createTime != null"> #{createTime}, </if>
<if test="status != null"> #{status} </if>
)
</insert>
<update id="update" parameterType="com.java2nb.novel.domain.AuthorDO">
update author
<set>
<if test="userId != null">`user_id` = #{userId}, </if>
<if test="inviteCode != null">`invite_code` = #{inviteCode}, </if>
<if test="penName != null">`pen_name` = #{penName}, </if>
<if test="telPhone != null">`tel_phone` = #{telPhone}, </if>
<if test="chatAccount != null">`chat_account` = #{chatAccount}, </if>
<if test="email != null">`email` = #{email}, </if>
<if test="workDirection != null">`work_direction` = #{workDirection}, </if>
<if test="createTime != null">`create_time` = #{createTime}, </if>
<if test="status != null">`status` = #{status}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from author where id = #{value}
</delete>
<delete id="batchRemove">
delete from author where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

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/author/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,244 @@
var prefix = "/novel/author"
$(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: [
{
checkbox: true
},
{
title: '序号',
formatter: function () {
return arguments[2] + 1;
}
},
{
field: 'inviteCode',
title: '邀请码'
},
{
field: 'penName',
title: '笔名'
},
{
field: 'telPhone',
title: '手机号码'
},
{
field: 'chatAccount',
title: 'QQ或微信账号'
},
{
field: 'email',
title: '电子邮箱'
},
{
field: 'workDirection',
title: '作品方向',
formatter: function (value, row, index) {
return formatDict("work_direction", value);
}
},
{
field: 'createTime',
title: '入驻时间'
},
{
field: 'status',
title: '状态',
formatter: function (value, row, index) {
return value == 1 ? '封禁' : '正常';
}
},
{
title: '操作',
field: 'id',
align: 'center',
formatter: function (value, row, index) {
if(row.status==1) {
var e = '<a class="btn btn-primary btn-sm ' + s_edit_h + '" href="#" mce_href="#" title="恢复正常" onclick="edit(\''
+ row.id
+ '\',0)"><i >恢复正常</i></a> ';
}else{
var e = '<a class="btn btn-primary btn-sm ' + s_edit_h + '" href="#" mce_href="#" title="封禁" onclick="edit(\''
+ row.id
+ '\',1)"><i >封禁</i></a> ';
}
return 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,status) {
$.ajax({
cache: true,
type: "POST",
url: "/novel/author/update",
data: {'id':id,'status':status},// 你的formid
async: false,
error: function (request) {
parent.layer.alert("Connection error");
},
success: function (data) {
if (data.code == 0) {
parent.layer.msg("操作成功");
reLoad();
} else {
parent.layer.alert(data.msg)
}
}
});
}
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,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/author/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,115 @@
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/authorCode/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: {
inviteCode: {
required: true
}, validityTime: {
required: true
}, },
messages: {
inviteCode: {
required: icon + "请选择邀请码"
}, validityTime: {
required: icon + "请选择有效时间"
}, }
})
}

View File

@ -0,0 +1,212 @@
var prefix = "/novel/authorCode"
$(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: [
{
checkbox: true
},
{
title: '序号',
formatter: function () {
return arguments[2] + 1;
}
},
{
field: 'inviteCode',
title: '邀请码'
},
{
field: 'validityTime',
title: '有效时间'
},
{
field: 'isUse',
title: '是否使用过',
formatter: function (value, row, index) {
return value == 1 ? '使用过' : '未使用';
}
},
{
field: 'createTime',
title: '创建时间'
},
/* {
field: 'createUserId',
title: '创建人ID'
},*/
{
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> ';*/
var r = '<a class="btn btn-warning btn-sm ' + s_remove_h + '" href="#" title="删除" mce_href="#" onclick="remove(\''
+ row.id
+ '\')"><i class="fa fa-remove"></i></a> ';
return r;
}
}]
});
}
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,115 @@
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/authorCode/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: {
inviteCode:
{
required: true
}, validityTime:
{
required: true
}, },
messages: {
inviteCode:
{
required: icon + "请选择邀请码"
}, validityTime:
{
required: icon + "请选择有效时间"
}, }
})
}

View File

@ -0,0 +1,18 @@
-- 菜单SQL
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES ('1', '作者表', 'novel/author', 'novel:author:author', '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:author:detail', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '新增', null, 'novel:author:add', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '修改', null, 'novel:author:edit', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '删除', null, 'novel:author:remove', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '批量删除', null, 'novel:author: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/authorCode', 'novel:authorCode:authorCode', '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:authorCode:detail', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '新增', null, 'novel:authorCode:add', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '修改', null, 'novel:authorCode:edit', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '删除', null, 'novel:authorCode:remove', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '批量删除', null, 'novel:authorCode:batchRemove', '2', null, '6';

View File

@ -0,0 +1,114 @@
<!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="userId" name="userId"
class="form-control"
type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">邀请码:</label>
<div class="col-sm-8">
<input id="inviteCode" name="inviteCode"
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="penName" name="penName"
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="telPhone" name="telPhone"
class="form-control"
type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">QQ或微信账号</label>
<div class="col-sm-8">
<input id="chatAccount" name="chatAccount"
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="email" name="email"
class="form-control"
type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">作品方向0男频1女频</label>
<div class="col-sm-8">
<select data-placeholder="--选择--" id="workDirection"
name="workDirection"
class="form-control chosen-select" tabindex="2"
dict-type="work_direction">
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">入驻时间:</label>
<div class="col-sm-8">
<input type="text" class="laydate-icon layer-date form-control"
id="createTime"
name="createTime"
onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})"
style="background-color: #fff;" readonly="readonly"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">0正常1封禁</label>
<div class="col-sm-8">
<input id="status" name="status"
class="form-control"
type="text">
</div>
</div>
<div class="form-group">
<div class="col-sm-8 col-sm-offset-3">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div th:include="include::footer"></div>
<script type="text/javascript" src="/wangEditor/release/wangEditor.js"></script>
<script type="text/javascript" src="/js/appjs/novel/author/add.js">
</script>
</body>
</html>

View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
<div class="wrapper wrapper-content ">
<div class="col-sm-12">
<div class="ibox">
<div class="ibox-body">
<div class="fixed-table-toolbar">
<div class="columns pull-left">
</div>
<div class="columns pull-right">
<button class="btn btn-success" onclick="reLoad()">查询</button>
</div>
<form id="searchForm">
<div class="columns pull-right col-md-2">
<input id="penName" name="penName" type="text" class="form-control"
placeholder="笔名">
</div>
</form>
</div>
<table id="exampleTable" data-mobile-responsive="true">
</table>
</div>
</div>
</div>
</div>
<!--shiro控制bootstraptable行内按钮看见性 -->
<div>
<script type="text/javascript">
var s_detail_h = 'hidden';
var s_edit_h = 'hidden';
var s_remove_h = 'hidden';
</script>
</div>
<div shiro:hasPermission="test:order:detail">
<script type="text/javascript">
s_detail_h = '';
</script>
</div>
<div shiro:hasPermission="novel:author:edit">
<script type="text/javascript">
s_edit_h = '';
</script>
</div>
<div shiro:hasPermission="novel:author: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/author/author.js"></script>
</body>
</html>

View File

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
<div class="wrapper wrapper-content ">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-content">
<form class="form-horizontal m-t" id="signupForm">
<input id="id" name="id" th:value="${author.id}"
type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">用户ID</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${author.userId}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">邀请码:</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${author.inviteCode}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">笔名:</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${author.penName}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">手机号码:</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${author.telPhone}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">QQ或微信账号</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${author.chatAccount}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">电子邮箱:</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${author.email}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">作品方向0男频1女频</label>
<div style="padding-top:8px" class="col-sm-8 dict-type" dict-type="work_direction"
th:attr="dict-value=${author.workDirection}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">入驻时间:</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${author.createTime}==null?null:${#dates.format(author.createTime,'yyyy-MM-dd HH:mm:ss')}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">0正常1封禁</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${author.status}">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div th:include="include::footer"></div>
</body>
</html>

View File

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
<div class="wrapper wrapper-content ">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-content">
<form class="form-horizontal m-t" id="signupForm">
<input id="id" name="id" th:value="${author.id}"
type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">用户ID</label>
<div class="col-sm-8">
<input id="userId" name="userId"
th:value="${author.userId}"
class="form-control"
type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">邀请码:</label>
<div class="col-sm-8">
<input id="inviteCode" name="inviteCode"
th:value="${author.inviteCode}"
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="penName" name="penName"
th:value="${author.penName}"
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="telPhone" name="telPhone"
th:value="${author.telPhone}"
class="form-control"
type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">QQ或微信账号</label>
<div class="col-sm-8">
<input id="chatAccount" name="chatAccount"
th:value="${author.chatAccount}"
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="email" name="email"
th:value="${author.email}"
class="form-control"
type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">作品方向0男频1女频</label>
<div class="col-sm-8">
<select data-placeholder="--选择--" id="workDirection"
name="workDirection"
class="form-control chosen-select" tabindex="2"
dict-type="work_direction"
th:attr="dict-value=${author.workDirection}" >
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">入驻时间:</label>
<div class="col-sm-8">
<input type="text" class="laydate-icon layer-date form-control"
id="createTime"
name="createTime"
th:value="${author.createTime}==null?null:${#dates.format(author.createTime,'yyyy-MM-dd HH:mm:ss')}"
onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})"
style="background-color: #fff;" readonly="readonly"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">0正常1封禁</label>
<div class="col-sm-8">
<input id="status" name="status"
th:value="${author.status}"
class="form-control"
type="text">
</div>
</div>
<div class="form-group">
<div class="col-sm-8 col-sm-offset-3">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div th:include="include::footer"></div>
<script type="text/javascript" src="/wangEditor/release/wangEditor.js"></script>
<script type="text/javascript" src="/js/appjs/novel/author/edit.js">
</script>
</body>
</html>

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
<div class="wrapper wrapper-content ">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-content">
<form class="form-horizontal m-t" id="signupForm">
<div class="form-group">
<label class="col-sm-3 control-label">邀请码:</label>
<div class="col-sm-8">
<input id="inviteCode" name="inviteCode"
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 type="text" class="laydate-icon layer-date form-control"
id="validityTime"
name="validityTime"
onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})"
style="background-color: #fff;" readonly="readonly"/>
</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/authorCode/add.js">
</script>
</body>
</html>

View File

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
<div class="wrapper wrapper-content ">
<div class="col-sm-12">
<div class="ibox">
<div class="ibox-body">
<div class="fixed-table-toolbar">
<div class="columns pull-left">
<button shiro:hasPermission="novel:authorCode:add" type="button"
class="btn btn-primary" onclick="add()">
<i class="fa fa-plus" aria-hidden="true"></i>添加
</button>
<button shiro:hasPermission="novel:authorCode:batchRemove" type="button"
class="btn btn-danger"
onclick="batchRemove()">
<i class="fa fa-trash" aria-hidden="true"></i>删除
</button>
</div>
<div class="columns pull-right">
<button class="btn btn-success" onclick="reLoad()">查询</button>
</div>
<form id="searchForm">
<div class="columns pull-right col-md-2">
<input id="inviteCode" name="inviteCode" type="text" class="form-control"
placeholder="邀请码">
</div>
</form>
</div>
<table id="exampleTable" data-mobile-responsive="true">
</table>
</div>
</div>
</div>
</div>
<!--shiro控制bootstraptable行内按钮看见性 -->
<div>
<script type="text/javascript">
var s_detail_h = 'hidden';
var s_edit_h = 'hidden';
var s_remove_h = 'hidden';
</script>
</div>
<div shiro:hasPermission="test:order:detail">
<script type="text/javascript">
s_detail_h = '';
</script>
</div>
<div shiro:hasPermission="novel:authorCode:edit">
<script type="text/javascript">
s_edit_h = '';
</script>
</div>
<div shiro:hasPermission="novel:authorCode: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/authorCode/authorCode.js"></script>
</body>
</html>

View File

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
<div class="wrapper wrapper-content ">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-content">
<form class="form-horizontal m-t" id="signupForm">
<input id="id" name="id" th:value="${authorCode.id}"
type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">邀请码:</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${authorCode.inviteCode}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">有效时间:</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${authorCode.validityTime}==null?null:${#dates.format(authorCode.validityTime,'yyyy-MM-dd HH:mm:ss')}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">是否使用过0未使用1:使用过:</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${authorCode.isUse}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">创建时间:</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${authorCode.createTime}==null?null:${#dates.format(authorCode.createTime,'yyyy-MM-dd HH:mm:ss')}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">创建人ID</label>
<div style="padding-top:8px" class="col-sm-8"
th:text="${authorCode.createUserId}">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div th:include="include::footer"></div>
</body>
</html>

View File

@ -0,0 +1,79 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
<div class="wrapper wrapper-content ">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-content">
<form class="form-horizontal m-t" id="signupForm">
<input id="id" name="id" th:value="${authorCode.id}"
type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">邀请码:</label>
<div class="col-sm-8">
<input id="inviteCode" name="inviteCode"
th:value="${authorCode.inviteCode}"
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 type="text" class="laydate-icon layer-date form-control"
id="validityTime"
name="validityTime"
th:value="${authorCode.validityTime}==null?null:${#dates.format(authorCode.validityTime,'yyyy-MM-dd HH:mm:ss')}"
onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})"
style="background-color: #fff;" readonly="readonly"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">是否使用过0未使用1:使用过:</label>
<div class="col-sm-8">
<input id="isUse" name="isUse"
th:value="${authorCode.isUse}"
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 type="text" class="laydate-icon layer-date form-control"
id="createTime"
name="createTime"
th:value="${authorCode.createTime}==null?null:${#dates.format(authorCode.createTime,'yyyy-MM-dd HH:mm:ss')}"
onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})"
style="background-color: #fff;" readonly="readonly"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">创建人ID</label>
<div class="col-sm-8">
<input id="createUserId" name="createUserId"
th:value="${authorCode.createUserId}"
class="form-control"
type="text">
</div>
</div>
<div class="form-group">
<div class="col-sm-8 col-sm-offset-3">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div th:include="include::footer"></div>
<script type="text/javascript" src="/wangEditor/release/wangEditor.js"></script>
<script type="text/javascript" src="/js/appjs/novel/authorCode/edit.js">
</script>
</body>
</html>

View File

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

View File

@ -43,12 +43,22 @@ public enum ResponseStatus {
USERNAME_PASS_ERROR(1004,"手机号或密码错误!"),
TWO_PASSWORD_DIFF(1005, "两次输入的新密码不匹配!"),
OLD_PASSWORD_ERROR(1006, "旧密码不匹配!"),
USER_NO_BALANCE(1007, "用户余额不足"),
/**
* 评论相关错误
* */
HAS_COMMENTS(3001, "已评价过该书籍!"),
/**
* 作者相关错误
* */
INVITE_CODE_INVALID(4001, "邀请码无效!"),
AUTHOR_STATUS_FORBIDDEN(4002, "作者状态异常,暂不能管理小说!")
, BOOKNAME_EXISTS(4003,"已发布过同名小说!")
,
/**
* 其他通用错误

View File

@ -57,7 +57,7 @@ public class RestTemplateUtil {
requestFactory.setHttpClient(httpClient);
requestFactory.setConnectionRequestTimeout(3000);
requestFactory.setConnectTimeout(3000);
requestFactory.setReadTimeout(10000);
requestFactory.setReadTimeout(30000);
RestTemplate restTemplate = new RestTemplate(requestFactory);
List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters();
for (HttpMessageConverter<?> httpMessageConverter : list) {

View File

@ -0,0 +1,136 @@
package com.java2nb.novel.entity;
import java.util.Date;
import javax.annotation.Generated;
public class Author {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long userId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String inviteCode;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String penName;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String telPhone;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String chatAccount;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String email;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte workDirection;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte status;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Long id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getUserId() {
return userId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setUserId(Long userId) {
this.userId = userId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getInviteCode() {
return inviteCode;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setInviteCode(String inviteCode) {
this.inviteCode = inviteCode == null ? null : inviteCode.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getPenName() {
return penName;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setPenName(String penName) {
this.penName = penName == null ? null : penName.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getTelPhone() {
return telPhone;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setTelPhone(String telPhone) {
this.telPhone = telPhone == null ? null : telPhone.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getChatAccount() {
return chatAccount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setChatAccount(String chatAccount) {
this.chatAccount = chatAccount == null ? null : chatAccount.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getEmail() {
return email;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setEmail(String email) {
this.email = email == null ? null : email.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getWorkDirection() {
return workDirection;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setWorkDirection(Byte workDirection) {
this.workDirection = workDirection;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getStatus() {
return status;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setStatus(Byte status) {
this.status = status;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() {
return createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}

View File

@ -0,0 +1,84 @@
package com.java2nb.novel.entity;
import java.util.Date;
import javax.annotation.Generated;
public class AuthorCode {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String inviteCode;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date validityTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte isUse;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long createUserId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Long id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getInviteCode() {
return inviteCode;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setInviteCode(String inviteCode) {
this.inviteCode = inviteCode == null ? null : inviteCode.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getValidityTime() {
return validityTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setValidityTime(Date validityTime) {
this.validityTime = validityTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getIsUse() {
return isUse;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setIsUse(Byte isUse) {
this.isUse = isUse;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() {
return createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getCreateUserId() {
return createUserId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
}

View File

@ -0,0 +1,110 @@
package com.java2nb.novel.entity;
import java.util.Date;
import javax.annotation.Generated;
public class UserBuyRecord {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long userId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long bookId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String bookName;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long bookIndexId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String bookIndexName;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Integer buyAmount;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Long id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getUserId() {
return userId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setUserId(Long userId) {
this.userId = userId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getBookId() {
return bookId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setBookId(Long bookId) {
this.bookId = bookId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getBookName() {
return bookName;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setBookName(String bookName) {
this.bookName = bookName == null ? null : bookName.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getBookIndexId() {
return bookIndexId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setBookIndexId(Long bookIndexId) {
this.bookIndexId = bookIndexId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getBookIndexName() {
return bookIndexName;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setBookIndexName(String bookIndexName) {
this.bookIndexName = bookIndexName == null ? null : bookIndexName.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Integer getBuyAmount() {
return buyAmount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setBuyAmount(Integer buyAmount) {
this.buyAmount = buyAmount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() {
return createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}

View File

@ -0,0 +1,49 @@
package com.java2nb.novel.mapper;
import java.sql.JDBCType;
import java.util.Date;
import javax.annotation.Generated;
import org.mybatis.dynamic.sql.SqlColumn;
import org.mybatis.dynamic.sql.SqlTable;
public final class AuthorCodeDynamicSqlSupport {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final AuthorCode authorCode = new AuthorCode();
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> id = authorCode.id;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> inviteCode = authorCode.inviteCode;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Date> validityTime = authorCode.validityTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Byte> isUse = authorCode.isUse;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Date> createTime = authorCode.createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> createUserId = authorCode.createUserId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final class AuthorCode extends SqlTable {
public final SqlColumn<Long> id = column("id", JDBCType.BIGINT);
public final SqlColumn<String> inviteCode = column("invite_code", JDBCType.VARCHAR);
public final SqlColumn<Date> validityTime = column("validity_time", JDBCType.TIMESTAMP);
public final SqlColumn<Byte> isUse = column("is_use", JDBCType.TINYINT);
public final SqlColumn<Date> createTime = column("create_time", JDBCType.TIMESTAMP);
public final SqlColumn<Long> createUserId = column("create_user_id", JDBCType.BIGINT);
public AuthorCode() {
super("author_code");
}
}
}

View File

@ -0,0 +1,200 @@
package com.java2nb.novel.mapper;
import static com.java2nb.novel.mapper.AuthorCodeDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import com.java2nb.novel.entity.AuthorCode;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import javax.annotation.Generated;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.dynamic.sql.BasicColumn;
import org.mybatis.dynamic.sql.delete.DeleteDSLCompleter;
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider;
import org.mybatis.dynamic.sql.select.CountDSLCompleter;
import org.mybatis.dynamic.sql.select.SelectDSLCompleter;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.update.UpdateDSL;
import org.mybatis.dynamic.sql.update.UpdateDSLCompleter;
import org.mybatis.dynamic.sql.update.UpdateModel;
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
import org.mybatis.dynamic.sql.util.mybatis3.MyBatis3Utils;
@Mapper
public interface AuthorCodeMapper {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
BasicColumn[] selectList = BasicColumn.columnList(id, inviteCode, validityTime, isUse, createTime, createUserId);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
long count(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@DeleteProvider(type=SqlProviderAdapter.class, method="delete")
int delete(DeleteStatementProvider deleteStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insert")
int insert(InsertStatementProvider<AuthorCode> insertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insertMultiple")
int insertMultiple(MultiRowInsertStatementProvider<AuthorCode> multipleInsertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@ResultMap("AuthorCodeResult")
Optional<AuthorCode> selectOne(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@Results(id="AuthorCodeResult", value = {
@Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true),
@Result(column="invite_code", property="inviteCode", jdbcType=JdbcType.VARCHAR),
@Result(column="validity_time", property="validityTime", jdbcType=JdbcType.TIMESTAMP),
@Result(column="is_use", property="isUse", jdbcType=JdbcType.TINYINT),
@Result(column="create_time", property="createTime", jdbcType=JdbcType.TIMESTAMP),
@Result(column="create_user_id", property="createUserId", jdbcType=JdbcType.BIGINT)
})
List<AuthorCode> selectMany(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@UpdateProvider(type=SqlProviderAdapter.class, method="update")
int update(UpdateStatementProvider updateStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default long count(CountDSLCompleter completer) {
return MyBatis3Utils.countFrom(this::count, authorCode, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int delete(DeleteDSLCompleter completer) {
return MyBatis3Utils.deleteFrom(this::delete, authorCode, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int deleteByPrimaryKey(Long id_) {
return delete(c ->
c.where(id, isEqualTo(id_))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insert(AuthorCode record) {
return MyBatis3Utils.insert(this::insert, record, authorCode, c ->
c.map(id).toProperty("id")
.map(inviteCode).toProperty("inviteCode")
.map(validityTime).toProperty("validityTime")
.map(isUse).toProperty("isUse")
.map(createTime).toProperty("createTime")
.map(createUserId).toProperty("createUserId")
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertMultiple(Collection<AuthorCode> records) {
return MyBatis3Utils.insertMultiple(this::insertMultiple, records, authorCode, c ->
c.map(id).toProperty("id")
.map(inviteCode).toProperty("inviteCode")
.map(validityTime).toProperty("validityTime")
.map(isUse).toProperty("isUse")
.map(createTime).toProperty("createTime")
.map(createUserId).toProperty("createUserId")
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertSelective(AuthorCode record) {
return MyBatis3Utils.insert(this::insert, record, authorCode, c ->
c.map(id).toPropertyWhenPresent("id", record::getId)
.map(inviteCode).toPropertyWhenPresent("inviteCode", record::getInviteCode)
.map(validityTime).toPropertyWhenPresent("validityTime", record::getValidityTime)
.map(isUse).toPropertyWhenPresent("isUse", record::getIsUse)
.map(createTime).toPropertyWhenPresent("createTime", record::getCreateTime)
.map(createUserId).toPropertyWhenPresent("createUserId", record::getCreateUserId)
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default Optional<AuthorCode> selectOne(SelectDSLCompleter completer) {
return MyBatis3Utils.selectOne(this::selectOne, selectList, authorCode, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default List<AuthorCode> select(SelectDSLCompleter completer) {
return MyBatis3Utils.selectList(this::selectMany, selectList, authorCode, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default List<AuthorCode> selectDistinct(SelectDSLCompleter completer) {
return MyBatis3Utils.selectDistinct(this::selectMany, selectList, authorCode, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default Optional<AuthorCode> selectByPrimaryKey(Long id_) {
return selectOne(c ->
c.where(id, isEqualTo(id_))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int update(UpdateDSLCompleter completer) {
return MyBatis3Utils.update(this::update, authorCode, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
static UpdateDSL<UpdateModel> updateAllColumns(AuthorCode record, UpdateDSL<UpdateModel> dsl) {
return dsl.set(id).equalTo(record::getId)
.set(inviteCode).equalTo(record::getInviteCode)
.set(validityTime).equalTo(record::getValidityTime)
.set(isUse).equalTo(record::getIsUse)
.set(createTime).equalTo(record::getCreateTime)
.set(createUserId).equalTo(record::getCreateUserId);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
static UpdateDSL<UpdateModel> updateSelectiveColumns(AuthorCode record, UpdateDSL<UpdateModel> dsl) {
return dsl.set(id).equalToWhenPresent(record::getId)
.set(inviteCode).equalToWhenPresent(record::getInviteCode)
.set(validityTime).equalToWhenPresent(record::getValidityTime)
.set(isUse).equalToWhenPresent(record::getIsUse)
.set(createTime).equalToWhenPresent(record::getCreateTime)
.set(createUserId).equalToWhenPresent(record::getCreateUserId);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKey(AuthorCode record) {
return update(c ->
c.set(inviteCode).equalTo(record::getInviteCode)
.set(validityTime).equalTo(record::getValidityTime)
.set(isUse).equalTo(record::getIsUse)
.set(createTime).equalTo(record::getCreateTime)
.set(createUserId).equalTo(record::getCreateUserId)
.where(id, isEqualTo(record::getId))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKeySelective(AuthorCode record) {
return update(c ->
c.set(inviteCode).equalToWhenPresent(record::getInviteCode)
.set(validityTime).equalToWhenPresent(record::getValidityTime)
.set(isUse).equalToWhenPresent(record::getIsUse)
.set(createTime).equalToWhenPresent(record::getCreateTime)
.set(createUserId).equalToWhenPresent(record::getCreateUserId)
.where(id, isEqualTo(record::getId))
);
}
}

View File

@ -0,0 +1,69 @@
package com.java2nb.novel.mapper;
import java.sql.JDBCType;
import java.util.Date;
import javax.annotation.Generated;
import org.mybatis.dynamic.sql.SqlColumn;
import org.mybatis.dynamic.sql.SqlTable;
public final class AuthorDynamicSqlSupport {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final Author author = new Author();
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> id = author.id;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> userId = author.userId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> inviteCode = author.inviteCode;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> penName = author.penName;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> telPhone = author.telPhone;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> chatAccount = author.chatAccount;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> email = author.email;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Byte> workDirection = author.workDirection;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Byte> status = author.status;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Date> createTime = author.createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final class Author extends SqlTable {
public final SqlColumn<Long> id = column("id", JDBCType.BIGINT);
public final SqlColumn<Long> userId = column("user_id", JDBCType.BIGINT);
public final SqlColumn<String> inviteCode = column("invite_code", JDBCType.VARCHAR);
public final SqlColumn<String> penName = column("pen_name", JDBCType.VARCHAR);
public final SqlColumn<String> telPhone = column("tel_phone", JDBCType.VARCHAR);
public final SqlColumn<String> chatAccount = column("chat_account", JDBCType.VARCHAR);
public final SqlColumn<String> email = column("email", JDBCType.VARCHAR);
public final SqlColumn<Byte> workDirection = column("work_direction", JDBCType.TINYINT);
public final SqlColumn<Byte> status = column("status", JDBCType.TINYINT);
public final SqlColumn<Date> createTime = column("create_time", JDBCType.TIMESTAMP);
public Author() {
super("author");
}
}
}

View File

@ -0,0 +1,232 @@
package com.java2nb.novel.mapper;
import static com.java2nb.novel.mapper.AuthorDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import com.java2nb.novel.entity.Author;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import javax.annotation.Generated;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.dynamic.sql.BasicColumn;
import org.mybatis.dynamic.sql.delete.DeleteDSLCompleter;
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider;
import org.mybatis.dynamic.sql.select.CountDSLCompleter;
import org.mybatis.dynamic.sql.select.SelectDSLCompleter;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.update.UpdateDSL;
import org.mybatis.dynamic.sql.update.UpdateDSLCompleter;
import org.mybatis.dynamic.sql.update.UpdateModel;
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
import org.mybatis.dynamic.sql.util.mybatis3.MyBatis3Utils;
@Mapper
public interface AuthorMapper {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
BasicColumn[] selectList = BasicColumn.columnList(id, userId, inviteCode, penName, telPhone, chatAccount, email, workDirection, status, createTime);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
long count(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@DeleteProvider(type=SqlProviderAdapter.class, method="delete")
int delete(DeleteStatementProvider deleteStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insert")
int insert(InsertStatementProvider<Author> insertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insertMultiple")
int insertMultiple(MultiRowInsertStatementProvider<Author> multipleInsertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@ResultMap("AuthorResult")
Optional<Author> selectOne(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@Results(id="AuthorResult", value = {
@Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true),
@Result(column="user_id", property="userId", jdbcType=JdbcType.BIGINT),
@Result(column="invite_code", property="inviteCode", jdbcType=JdbcType.VARCHAR),
@Result(column="pen_name", property="penName", jdbcType=JdbcType.VARCHAR),
@Result(column="tel_phone", property="telPhone", jdbcType=JdbcType.VARCHAR),
@Result(column="chat_account", property="chatAccount", jdbcType=JdbcType.VARCHAR),
@Result(column="email", property="email", jdbcType=JdbcType.VARCHAR),
@Result(column="work_direction", property="workDirection", jdbcType=JdbcType.TINYINT),
@Result(column="status", property="status", jdbcType=JdbcType.TINYINT),
@Result(column="create_time", property="createTime", jdbcType=JdbcType.TIMESTAMP)
})
List<Author> selectMany(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@UpdateProvider(type=SqlProviderAdapter.class, method="update")
int update(UpdateStatementProvider updateStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default long count(CountDSLCompleter completer) {
return MyBatis3Utils.countFrom(this::count, author, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int delete(DeleteDSLCompleter completer) {
return MyBatis3Utils.deleteFrom(this::delete, author, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int deleteByPrimaryKey(Long id_) {
return delete(c ->
c.where(id, isEqualTo(id_))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insert(Author record) {
return MyBatis3Utils.insert(this::insert, record, author, c ->
c.map(id).toProperty("id")
.map(userId).toProperty("userId")
.map(inviteCode).toProperty("inviteCode")
.map(penName).toProperty("penName")
.map(telPhone).toProperty("telPhone")
.map(chatAccount).toProperty("chatAccount")
.map(email).toProperty("email")
.map(workDirection).toProperty("workDirection")
.map(status).toProperty("status")
.map(createTime).toProperty("createTime")
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertMultiple(Collection<Author> records) {
return MyBatis3Utils.insertMultiple(this::insertMultiple, records, author, c ->
c.map(id).toProperty("id")
.map(userId).toProperty("userId")
.map(inviteCode).toProperty("inviteCode")
.map(penName).toProperty("penName")
.map(telPhone).toProperty("telPhone")
.map(chatAccount).toProperty("chatAccount")
.map(email).toProperty("email")
.map(workDirection).toProperty("workDirection")
.map(status).toProperty("status")
.map(createTime).toProperty("createTime")
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertSelective(Author record) {
return MyBatis3Utils.insert(this::insert, record, author, c ->
c.map(id).toPropertyWhenPresent("id", record::getId)
.map(userId).toPropertyWhenPresent("userId", record::getUserId)
.map(inviteCode).toPropertyWhenPresent("inviteCode", record::getInviteCode)
.map(penName).toPropertyWhenPresent("penName", record::getPenName)
.map(telPhone).toPropertyWhenPresent("telPhone", record::getTelPhone)
.map(chatAccount).toPropertyWhenPresent("chatAccount", record::getChatAccount)
.map(email).toPropertyWhenPresent("email", record::getEmail)
.map(workDirection).toPropertyWhenPresent("workDirection", record::getWorkDirection)
.map(status).toPropertyWhenPresent("status", record::getStatus)
.map(createTime).toPropertyWhenPresent("createTime", record::getCreateTime)
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default Optional<Author> selectOne(SelectDSLCompleter completer) {
return MyBatis3Utils.selectOne(this::selectOne, selectList, author, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default List<Author> select(SelectDSLCompleter completer) {
return MyBatis3Utils.selectList(this::selectMany, selectList, author, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default List<Author> selectDistinct(SelectDSLCompleter completer) {
return MyBatis3Utils.selectDistinct(this::selectMany, selectList, author, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default Optional<Author> selectByPrimaryKey(Long id_) {
return selectOne(c ->
c.where(id, isEqualTo(id_))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int update(UpdateDSLCompleter completer) {
return MyBatis3Utils.update(this::update, author, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
static UpdateDSL<UpdateModel> updateAllColumns(Author record, UpdateDSL<UpdateModel> dsl) {
return dsl.set(id).equalTo(record::getId)
.set(userId).equalTo(record::getUserId)
.set(inviteCode).equalTo(record::getInviteCode)
.set(penName).equalTo(record::getPenName)
.set(telPhone).equalTo(record::getTelPhone)
.set(chatAccount).equalTo(record::getChatAccount)
.set(email).equalTo(record::getEmail)
.set(workDirection).equalTo(record::getWorkDirection)
.set(status).equalTo(record::getStatus)
.set(createTime).equalTo(record::getCreateTime);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
static UpdateDSL<UpdateModel> updateSelectiveColumns(Author record, UpdateDSL<UpdateModel> dsl) {
return dsl.set(id).equalToWhenPresent(record::getId)
.set(userId).equalToWhenPresent(record::getUserId)
.set(inviteCode).equalToWhenPresent(record::getInviteCode)
.set(penName).equalToWhenPresent(record::getPenName)
.set(telPhone).equalToWhenPresent(record::getTelPhone)
.set(chatAccount).equalToWhenPresent(record::getChatAccount)
.set(email).equalToWhenPresent(record::getEmail)
.set(workDirection).equalToWhenPresent(record::getWorkDirection)
.set(status).equalToWhenPresent(record::getStatus)
.set(createTime).equalToWhenPresent(record::getCreateTime);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKey(Author record) {
return update(c ->
c.set(userId).equalTo(record::getUserId)
.set(inviteCode).equalTo(record::getInviteCode)
.set(penName).equalTo(record::getPenName)
.set(telPhone).equalTo(record::getTelPhone)
.set(chatAccount).equalTo(record::getChatAccount)
.set(email).equalTo(record::getEmail)
.set(workDirection).equalTo(record::getWorkDirection)
.set(status).equalTo(record::getStatus)
.set(createTime).equalTo(record::getCreateTime)
.where(id, isEqualTo(record::getId))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKeySelective(Author record) {
return update(c ->
c.set(userId).equalToWhenPresent(record::getUserId)
.set(inviteCode).equalToWhenPresent(record::getInviteCode)
.set(penName).equalToWhenPresent(record::getPenName)
.set(telPhone).equalToWhenPresent(record::getTelPhone)
.set(chatAccount).equalToWhenPresent(record::getChatAccount)
.set(email).equalToWhenPresent(record::getEmail)
.set(workDirection).equalToWhenPresent(record::getWorkDirection)
.set(status).equalToWhenPresent(record::getStatus)
.set(createTime).equalToWhenPresent(record::getCreateTime)
.where(id, isEqualTo(record::getId))
);
}
}

View File

@ -0,0 +1,59 @@
package com.java2nb.novel.mapper;
import java.sql.JDBCType;
import java.util.Date;
import javax.annotation.Generated;
import org.mybatis.dynamic.sql.SqlColumn;
import org.mybatis.dynamic.sql.SqlTable;
public final class UserBuyRecordDynamicSqlSupport {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final UserBuyRecord userBuyRecord = new UserBuyRecord();
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> id = userBuyRecord.id;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> userId = userBuyRecord.userId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> bookId = userBuyRecord.bookId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> bookName = userBuyRecord.bookName;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> bookIndexId = userBuyRecord.bookIndexId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> bookIndexName = userBuyRecord.bookIndexName;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Integer> buyAmount = userBuyRecord.buyAmount;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Date> createTime = userBuyRecord.createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final class UserBuyRecord extends SqlTable {
public final SqlColumn<Long> id = column("id", JDBCType.BIGINT);
public final SqlColumn<Long> userId = column("user_id", JDBCType.BIGINT);
public final SqlColumn<Long> bookId = column("book_id", JDBCType.BIGINT);
public final SqlColumn<String> bookName = column("book_name", JDBCType.VARCHAR);
public final SqlColumn<Long> bookIndexId = column("book_index_id", JDBCType.BIGINT);
public final SqlColumn<String> bookIndexName = column("book_index_name", JDBCType.VARCHAR);
public final SqlColumn<Integer> buyAmount = column("buy_amount", JDBCType.INTEGER);
public final SqlColumn<Date> createTime = column("create_time", JDBCType.TIMESTAMP);
public UserBuyRecord() {
super("user_buy_record");
}
}
}

View File

@ -0,0 +1,216 @@
package com.java2nb.novel.mapper;
import static com.java2nb.novel.mapper.UserBuyRecordDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import com.java2nb.novel.entity.UserBuyRecord;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import javax.annotation.Generated;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.dynamic.sql.BasicColumn;
import org.mybatis.dynamic.sql.delete.DeleteDSLCompleter;
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider;
import org.mybatis.dynamic.sql.select.CountDSLCompleter;
import org.mybatis.dynamic.sql.select.SelectDSLCompleter;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.update.UpdateDSL;
import org.mybatis.dynamic.sql.update.UpdateDSLCompleter;
import org.mybatis.dynamic.sql.update.UpdateModel;
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
import org.mybatis.dynamic.sql.util.mybatis3.MyBatis3Utils;
@Mapper
public interface UserBuyRecordMapper {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
BasicColumn[] selectList = BasicColumn.columnList(id, userId, bookId, bookName, bookIndexId, bookIndexName, buyAmount, createTime);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
long count(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@DeleteProvider(type=SqlProviderAdapter.class, method="delete")
int delete(DeleteStatementProvider deleteStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insert")
int insert(InsertStatementProvider<UserBuyRecord> insertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insertMultiple")
int insertMultiple(MultiRowInsertStatementProvider<UserBuyRecord> multipleInsertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@ResultMap("UserBuyRecordResult")
Optional<UserBuyRecord> selectOne(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@Results(id="UserBuyRecordResult", value = {
@Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true),
@Result(column="user_id", property="userId", jdbcType=JdbcType.BIGINT),
@Result(column="book_id", property="bookId", jdbcType=JdbcType.BIGINT),
@Result(column="book_name", property="bookName", jdbcType=JdbcType.VARCHAR),
@Result(column="book_index_id", property="bookIndexId", jdbcType=JdbcType.BIGINT),
@Result(column="book_index_name", property="bookIndexName", jdbcType=JdbcType.VARCHAR),
@Result(column="buy_amount", property="buyAmount", jdbcType=JdbcType.INTEGER),
@Result(column="create_time", property="createTime", jdbcType=JdbcType.TIMESTAMP)
})
List<UserBuyRecord> selectMany(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@UpdateProvider(type=SqlProviderAdapter.class, method="update")
int update(UpdateStatementProvider updateStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default long count(CountDSLCompleter completer) {
return MyBatis3Utils.countFrom(this::count, userBuyRecord, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int delete(DeleteDSLCompleter completer) {
return MyBatis3Utils.deleteFrom(this::delete, userBuyRecord, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int deleteByPrimaryKey(Long id_) {
return delete(c ->
c.where(id, isEqualTo(id_))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insert(UserBuyRecord record) {
return MyBatis3Utils.insert(this::insert, record, userBuyRecord, c ->
c.map(id).toProperty("id")
.map(userId).toProperty("userId")
.map(bookId).toProperty("bookId")
.map(bookName).toProperty("bookName")
.map(bookIndexId).toProperty("bookIndexId")
.map(bookIndexName).toProperty("bookIndexName")
.map(buyAmount).toProperty("buyAmount")
.map(createTime).toProperty("createTime")
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertMultiple(Collection<UserBuyRecord> records) {
return MyBatis3Utils.insertMultiple(this::insertMultiple, records, userBuyRecord, c ->
c.map(id).toProperty("id")
.map(userId).toProperty("userId")
.map(bookId).toProperty("bookId")
.map(bookName).toProperty("bookName")
.map(bookIndexId).toProperty("bookIndexId")
.map(bookIndexName).toProperty("bookIndexName")
.map(buyAmount).toProperty("buyAmount")
.map(createTime).toProperty("createTime")
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertSelective(UserBuyRecord record) {
return MyBatis3Utils.insert(this::insert, record, userBuyRecord, c ->
c.map(id).toPropertyWhenPresent("id", record::getId)
.map(userId).toPropertyWhenPresent("userId", record::getUserId)
.map(bookId).toPropertyWhenPresent("bookId", record::getBookId)
.map(bookName).toPropertyWhenPresent("bookName", record::getBookName)
.map(bookIndexId).toPropertyWhenPresent("bookIndexId", record::getBookIndexId)
.map(bookIndexName).toPropertyWhenPresent("bookIndexName", record::getBookIndexName)
.map(buyAmount).toPropertyWhenPresent("buyAmount", record::getBuyAmount)
.map(createTime).toPropertyWhenPresent("createTime", record::getCreateTime)
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default Optional<UserBuyRecord> selectOne(SelectDSLCompleter completer) {
return MyBatis3Utils.selectOne(this::selectOne, selectList, userBuyRecord, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default List<UserBuyRecord> select(SelectDSLCompleter completer) {
return MyBatis3Utils.selectList(this::selectMany, selectList, userBuyRecord, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default List<UserBuyRecord> selectDistinct(SelectDSLCompleter completer) {
return MyBatis3Utils.selectDistinct(this::selectMany, selectList, userBuyRecord, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default Optional<UserBuyRecord> selectByPrimaryKey(Long id_) {
return selectOne(c ->
c.where(id, isEqualTo(id_))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int update(UpdateDSLCompleter completer) {
return MyBatis3Utils.update(this::update, userBuyRecord, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
static UpdateDSL<UpdateModel> updateAllColumns(UserBuyRecord record, UpdateDSL<UpdateModel> dsl) {
return dsl.set(id).equalTo(record::getId)
.set(userId).equalTo(record::getUserId)
.set(bookId).equalTo(record::getBookId)
.set(bookName).equalTo(record::getBookName)
.set(bookIndexId).equalTo(record::getBookIndexId)
.set(bookIndexName).equalTo(record::getBookIndexName)
.set(buyAmount).equalTo(record::getBuyAmount)
.set(createTime).equalTo(record::getCreateTime);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
static UpdateDSL<UpdateModel> updateSelectiveColumns(UserBuyRecord record, UpdateDSL<UpdateModel> dsl) {
return dsl.set(id).equalToWhenPresent(record::getId)
.set(userId).equalToWhenPresent(record::getUserId)
.set(bookId).equalToWhenPresent(record::getBookId)
.set(bookName).equalToWhenPresent(record::getBookName)
.set(bookIndexId).equalToWhenPresent(record::getBookIndexId)
.set(bookIndexName).equalToWhenPresent(record::getBookIndexName)
.set(buyAmount).equalToWhenPresent(record::getBuyAmount)
.set(createTime).equalToWhenPresent(record::getCreateTime);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKey(UserBuyRecord record) {
return update(c ->
c.set(userId).equalTo(record::getUserId)
.set(bookId).equalTo(record::getBookId)
.set(bookName).equalTo(record::getBookName)
.set(bookIndexId).equalTo(record::getBookIndexId)
.set(bookIndexName).equalTo(record::getBookIndexName)
.set(buyAmount).equalTo(record::getBuyAmount)
.set(createTime).equalTo(record::getCreateTime)
.where(id, isEqualTo(record::getId))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKeySelective(UserBuyRecord record) {
return update(c ->
c.set(userId).equalToWhenPresent(record::getUserId)
.set(bookId).equalToWhenPresent(record::getBookId)
.set(bookName).equalToWhenPresent(record::getBookName)
.set(bookIndexId).equalToWhenPresent(record::getBookIndexId)
.set(bookIndexName).equalToWhenPresent(record::getBookIndexName)
.set(buyAmount).equalToWhenPresent(record::getBuyAmount)
.set(createTime).equalToWhenPresent(record::getCreateTime)
.where(id, isEqualTo(record::getId))
);
}
}

View File

@ -9,7 +9,7 @@
</commentGenerator>
<jdbcConnection
connectionURL="jdbc:mysql://127.0.0.1:3306/novel_plus?tinyInt1isBit=false&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=Asia/Shanghai&amp;nullCatalogMeansCurrent=true"
driverClass="com.mysql.jdbc.Driver" password="test123456"
driverClass="com.mysql.jdbc.Driver" password=""
userId="root" />
<!-- 默认false把JDBC DECIMAL NUMERIC 类型解析为 Integer true时把JDBC DECIMAL
@ -44,7 +44,7 @@
</javaClientGenerator>
<!--生成全部表tableName设为%-->
<table tableName="order_pay" domainObjectName="OrderPay"/>
<table tableName="user_buy_record" domainObjectName="UserBuyRecord"/>
<!-- 指定数据库表 -->
<!--<table schema="jly" tableName="job_position" domainObjectName="JobPositionTest"/>-->

View File

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

View File

@ -3,12 +3,17 @@ 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.entity.Book;
import com.java2nb.novel.entity.BookContent;
import com.java2nb.novel.entity.BookIndex;
import com.java2nb.novel.utils.Constants;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.text.SimpleDateFormat;
import java.util.*;
@ -22,17 +27,22 @@ import static java.util.regex.Pattern.compile;
*
* @author Administrator
*/
@Slf4j
public class CrawlParser {
public static final Integer BOOK_INDEX_LIST_KEY = 1;
public static final Integer BOOK_CONTENT_LIST_KEY = 2;
private static RestTemplate restTemplate = RestTemplateUtil.getInstance("utf-8");
private static ThreadLocal <Integer> retryCount = new ThreadLocal<>();
@SneakyThrows
public static Book parseBook(RuleBean ruleBean, String bookId) {
Book book = new Book();
String bookDetailUrl = ruleBean.getBookDetailUrl().replace("{bookId}", bookId);
String bookDetailHtml = HttpUtil.getByHttpClient(bookDetailUrl);
String bookDetailHtml = getByHttpClient(bookDetailUrl);
if (bookDetailHtml != null) {
Pattern bookNamePatten = compile(ruleBean.getBookNamePatten());
Matcher bookNameMatch = bookNamePatten.matcher(bookDetailHtml);
@ -54,6 +64,9 @@ public class CrawlParser {
boolean isFindPicUrl = picUrlMatch.find();
if (isFindPicUrl) {
String picUrl = picUrlMatch.group(1);
if(StringUtils.isNotBlank(picUrl) && StringUtils.isNotBlank(ruleBean.getPicUrlPrefix())) {
picUrl = ruleBean.getPicUrlPrefix() + picUrl;
}
//设置封面图片路径
book.setPicUrl(picUrl);
}
@ -136,8 +149,13 @@ public class CrawlParser {
List<BookContent> contentList = new ArrayList<>();
//读取目录
String indexListUrl = ruleBean.getBookIndexUrl().replace("{bookId}", sourceBookId);
String indexListHtml = HttpUtil.getByHttpClient(indexListUrl);
String indexListHtml = getByHttpClient(indexListUrl);
if (indexListHtml != null) {
if(StringUtils.isNotBlank(ruleBean.getBookIndexStart())){
indexListHtml = indexListHtml.substring(indexListHtml.indexOf(ruleBean.getBookIndexStart()) + ruleBean.getBookIndexStart().length());
}
Pattern indexIdPatten = compile(ruleBean.getIndexIdPatten());
Matcher indexIdMatch = indexIdPatten.matcher(indexListHtml);
@ -162,8 +180,8 @@ public class CrawlParser {
String contentUrl = ruleBean.getBookContentUrl().replace("{bookId}", sourceBookId).replace("{indexId}", indexIdMatch.group(1));
//查询章节内容
String contentHtml = HttpUtil.getByHttpClient(contentUrl);
if (contentHtml != null) {
String contentHtml = getByHttpClient(contentUrl);
if (contentHtml != null && !contentHtml.contains("正在手打中")) {
String content = contentHtml.substring(contentHtml.indexOf(ruleBean.getContentStart()) + ruleBean.getContentStart().length());
content = content.substring(0, content.indexOf(ruleBean.getContentEnd()));
//TODO插入章节目录和章节内容
@ -237,4 +255,37 @@ public class CrawlParser {
}
private static String getByHttpClient(String url) {
try {
ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
if (forEntity.getStatusCode() == HttpStatus.OK) {
String body = forEntity.getBody();
if(body.length() < Constants.INVALID_HTML_LENGTH){
return processErrorHttpResult(url);
}
//成功获得html内容
return body;
}
} catch (Exception e) {
e.printStackTrace();
}
return processErrorHttpResult(url);
}
@SneakyThrows
private static String processErrorHttpResult(String url){
Integer count = retryCount.get();
if(count == null){
count = 0;
}
if(count < Constants.HTTP_FAIL_RETRY_COUNT){
Thread.sleep( new Random().nextInt(10*1000));
retryCount.set(++count);
return getByHttpClient(url);
}
return null;
}
}

View File

@ -11,6 +11,14 @@ import java.util.Map;
@Data
public class RuleBean {
/**
* 小说更新列表url
* */
private String updateBookListUrl;
/**
* 分类列表页URL规则
* */
private String bookListUrl;
private Map<String,String> catIdRule;
@ -39,4 +47,9 @@ public class RuleBean {
private String contentEnd;
private String picUrlPrefix;
private String bookIndexStart;
}

View File

@ -14,4 +14,14 @@ public class Constants {
* 访问量默认值
*/
public static final Long VISIT_COUNT_DEFAULT = 100L;
/**
* 爬取小说http请求中无效的内容长度
*/
public static final int INVALID_HTML_LENGTH = 1500;
/**
* 爬取小说http请求失败重试次数
*/
public static final Integer HTTP_FAIL_RETRY_COUNT = 5;
}

View File

@ -57,6 +57,9 @@
<li><span id="LabErr"></span></li>
示例:<b>新顶点小说网</b>
<li><input type="text" id="sourceName" class="s_input icon_name" placeholder="源站名"></li>
<!--示例:<b>https://m.xdingdiann.com/sort/0/1.html</b>
<li><input type="text" id="updateBookListUrl" class="s_input icon_key"
placeholder="小说更新列表url"></li>-->
示例:<b>http://m.xdingdiann.com/sort/{catId}/{page}.html</b> ({catId}代表分类ID{page}代表分页页码)
<li><input type="text" id="bookListUrl" class="s_input icon_key"
placeholder="分类列表页URL规则"></li>
@ -95,6 +98,9 @@
示例:<b>&lt;img src="([^>]+)"\s+onerror="this.src=</b>
<li><input type="text" id="picUrlPatten" class="s_input icon_key"
placeholder="小说图片路径的正则表达式"></li>
<b>可空,适用于图片路径为相对路径的源站,加上小说图片路径,则为完整的可访问的图片路径</b>
<li><input type="text" id="picUrlPrefix" class="s_input icon_key"
placeholder="小说图片访问路径前缀"></li>
示例:<b>状态:([^/]+)&lt;/li&gt;</b>
<li><input type="text" id="statusPatten" class="s_input icon_key"
placeholder="小说状态的正则表达式"></li>
@ -125,6 +131,9 @@
示例:<b>http://m.xdingdiann.com/ddk{bookId}/all.html</b> (bookId代表小说ID)
<li><input type="text" id="bookIndexUrl" class="s_input icon_key"
placeholder="小说目录页的URL规则"></li>
<b>可空,适用于最新章节列表和全部章节列表在同一个页面的源站</b>
<li><input type="text" id="bookIndexStart" class="s_input icon_key"
placeholder="小说目录页内容开始截取字符串"></li>
示例:<b>&lt;a\s+style=""\s+href="/ddk\d+/(\d+)\.html"&gt;[^/]+&lt;/a&gt;</b>
<li><input type="text" id="indexIdPatten" class="s_input icon_key"
placeholder="目录页目录ID正则表达式"></li>
@ -278,6 +287,12 @@
crawlRule.picUrlPatten = picUrlPatten;
}
var picUrlPrefix = $("#picUrlPrefix").val();
if (picUrlPrefix.length > 0) {
crawlRule.picUrlPrefix = picUrlPrefix;
}
var statusPatten = $("#statusPatten").val();
if (statusPatten.length > 0) {
crawlRule.statusPatten = statusPatten;
@ -345,6 +360,13 @@
crawlRule.bookIndexUrl = bookIndexUrl;
var bookIndexStart = $("#bookIndexStart").val();
if (bookIndexStart.length > 0) {
crawlRule.bookIndexStart = bookIndexStart;
}
var indexIdPatten = $("#indexIdPatten").val();
if (indexIdPatten.length == 0) {

View File

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

View File

@ -0,0 +1,121 @@
package com.java2nb.novel.controller;
import com.github.pagehelper.PageInfo;
import com.java2nb.novel.core.bean.ResultBean;
import com.java2nb.novel.core.enums.ResponseStatus;
import com.java2nb.novel.core.utils.BeanUtil;
import com.java2nb.novel.entity.Author;
import com.java2nb.novel.entity.Book;
import com.java2nb.novel.service.AuthorService;
import com.java2nb.novel.service.BookService;
import com.java2nb.novel.service.FriendLinkService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author 11797
*/
@RequestMapping("author")
@RestController
@Slf4j
@RequiredArgsConstructor
public class AuthorController extends BaseController{
private final AuthorService authorService;
private final BookService bookService;
/**
* 校验笔名是否存在
* */
@PostMapping("checkPenName")
public ResultBean checkPenName(String penName){
return ResultBean.ok(authorService.checkPenName(penName));
}
/**
* 作家发布小说分页列表查询
* */
@PostMapping("listBookByPage")
public ResultBean listBookByPage(@RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "10") int pageSize ,HttpServletRequest request){
return ResultBean.ok(new PageInfo<>(bookService.listBookPageByUserId(getUserDetails(request).getId(),page,pageSize)
));
}
/**
* 发布小说
* */
@PostMapping("addBook")
public ResultBean addBook(Book book,HttpServletRequest request){
//查询作家信息
Author author = authorService.queryAuthor(getUserDetails(request).getId());
//判断作者状态是否正常
if(author.getStatus()==1){
//封禁状态,不能发布小说
return ResultBean.fail(ResponseStatus.AUTHOR_STATUS_FORBIDDEN);
}
//发布小说
bookService.addBook(book,author.getId(),author.getPenName());
return ResultBean.ok();
}
/**
* 更新小说状态,上架或下架
* */
@PostMapping("updateBookStatus")
public ResultBean updateBookStatus(Long bookId,Byte status,HttpServletRequest request){
//查询作家信息
Author author = authorService.queryAuthor(getUserDetails(request).getId());
//判断作者状态是否正常
if(author.getStatus()==1){
//封禁状态,不能发布小说
return ResultBean.fail(ResponseStatus.AUTHOR_STATUS_FORBIDDEN);
}
//更新小说状态,上架或下架
bookService.updateBookStatus(bookId,status,author.getId());
return ResultBean.ok();
}
/**
* 发布章节内容
* */
@PostMapping("addBookContent")
public ResultBean addBookContent(Long bookId,String indexName,String content,HttpServletRequest request){
//查询作家信息
Author author = authorService.queryAuthor(getUserDetails(request).getId());
//判断作者状态是否正常
if(author.getStatus()==1){
//封禁状态,不能发布小说
return ResultBean.fail(ResponseStatus.AUTHOR_STATUS_FORBIDDEN);
}
//发布章节内容
bookService.addBookContent(bookId,indexName,content,author.getId());
return ResultBean.ok();
}
}

View File

@ -116,7 +116,11 @@ public class BookController extends BaseController{
public ResultBean queryBookIndexAbout(Long bookId,Long lastBookIndexId) {
Map<String,Object> data = new HashMap<>(2);
data.put("bookIndexCount",bookService.queryIndexCount(bookId));
data.put("lastBookContent",bookService.queryBookContent(lastBookIndexId).getContent().substring(0,42));
String lastBookContent = bookService.queryBookContent(lastBookIndexId).getContent();
if(lastBookContent.length()>42){
lastBookContent=lastBookContent.substring(0,42);
}
data.put("lastBookContent",lastBookContent);
return ResultBean.ok(data);
}
@ -161,4 +165,6 @@ public class BookController extends BaseController{
}

View File

@ -1,19 +1,24 @@
package com.java2nb.novel.controller;
import com.java2nb.novel.core.bean.ResultBean;
import com.java2nb.novel.core.bean.UserDetails;
import com.java2nb.novel.core.utils.ThreadLocalUtil;
import com.java2nb.novel.entity.Book;
import com.java2nb.novel.entity.BookContent;
import com.java2nb.novel.entity.BookIndex;
import com.java2nb.novel.entity.News;
import com.java2nb.novel.entity.*;
import com.java2nb.novel.service.AuthorService;
import com.java2nb.novel.service.BookService;
import com.java2nb.novel.service.NewsService;
import com.java2nb.novel.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.util.List;
/**
@ -22,12 +27,16 @@ import java.util.List;
@Slf4j
@RequiredArgsConstructor
@Controller
public class PageController{
public class PageController extends BaseController{
private final BookService bookService;
private final NewsService newsService;
private final AuthorService authorService;
private final UserService userService;
@RequestMapping("{url}.html")
public String module(@PathVariable("url") String url) {
@ -35,7 +44,22 @@ public class PageController{
}
@RequestMapping("{module}/{url}.html")
public String module2(@PathVariable("module") String module, @PathVariable("url") String url) {
public String module2(@PathVariable("module") String module, @PathVariable("url") String url,HttpServletRequest request) {
if(request.getRequestURI().startsWith("/author")) {
//访问作者专区
UserDetails user = getUserDetails(request);
if (user == null) {
//未登录
return "redirect:/user/login.html?originUrl=" + request.getRequestURI();
}
boolean isAuthor = authorService.isAuthor(user.getId());
if (!isAuthor) {
return "redirect:/author/register.html" ;
}
}
return module + "/" + url;
}
@ -100,7 +124,7 @@ public class PageController{
* 内容页
* */
@RequestMapping("/book/{bookId}/{bookIndexId}.html")
public String indexList(@PathVariable("bookId") Long bookId,@PathVariable("bookIndexId") Long bookIndexId, 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);
@ -116,6 +140,23 @@ public class PageController{
//查询内容
BookContent bookContent = bookService.queryBookContent(bookIndex.getId());
model.addAttribute("bookContent",bookContent);
//判断该目录是否收费
if(bookIndex.getIsVip()!=null && bookIndex.getIsVip() == 1 ){
UserDetails user = getUserDetails(request);
if(user == null){
//未登录
return "redirect:/user/login.html?originUrl="+request.getRequestURI();
}
//收费,判断用户是否购买过该目录
boolean isBuy = userService.queryIsBuyBookIndex(user.getId(),bookIndexId);
if(!isBuy){
//没有购买过,需要购买
bookContent.setContent(null);
model.addAttribute("needBuy",true);
return "book/book_content";
}
}
model.addAttribute("needBuy",false);
return ThreadLocalUtil.getTemplateDir()+"book/book_content";
}
@ -141,4 +182,30 @@ public class PageController{
return "about/news_info";
}
/**
* 作者注册页面
* */
@RequestMapping("author/register.html")
public String authorRegister(Author author, HttpServletRequest request, Model model){
UserDetails user = getUserDetails(request);
if(user == null){
//未登录
return "redirect:/user/login.html?originUrl=/author/register.html";
}
if(StringUtils.isNotBlank(author.getInviteCode())) {
//提交作者注册信息
String errorInfo = authorService.register(user.getId(), author);
if(StringUtils.isBlank(errorInfo)){
//注册成功
return "redirect:/author/index.html";
}
model.addAttribute("LabErr",errorInfo);
model.addAttribute("author",author);
}
return "author/register";
}
}

View File

@ -7,6 +7,7 @@ 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.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;
@ -100,7 +101,9 @@ public class UserController extends BaseController {
token = jwtTokenUtil.refreshToken(token);
Map<String, Object> data = new HashMap<>(2);
data.put("token", token);
data.put("username", jwtTokenUtil.getUserDetailsFromToken(token).getUsername());
UserDetails userDetail = jwtTokenUtil.getUserDetailsFromToken(token);
data.put("username", userDetail.getUsername());
data.put("nickName", userDetail.getNickName());
return ResultBean.ok(data);
} else {
@ -231,6 +234,12 @@ public class UserController extends BaseController {
return ResultBean.fail(ResponseStatus.NO_LOGIN);
}
userService.updateUserInfo(userDetails.getId(),user);
if(user.getNickName() != null){
userDetails.setNickName(user.getNickName());
Map<String, Object> data = new HashMap<>(1);
data.put("token", jwtTokenUtil.generateToken(userDetails));
return ResultBean.ok(data);
}
return ResultBean.ok();
}
@ -264,6 +273,21 @@ public class UserController extends BaseController {
}
/**
* 购买小说章节
* */
@PostMapping("buyBookIndex")
public ResultBean buyBookIndex(UserBuyRecord buyRecord, HttpServletRequest request) {
UserDetails userDetails = getUserDetails(request);
if (userDetails == null) {
return ResultBean.fail(ResponseStatus.NO_LOGIN);
}
userService.buyBookIndex(userDetails.getId(),buyRecord);
return ResultBean.ok();
}
}

View File

@ -11,4 +11,6 @@ public class UserDetails {
private Long id;
private String username;
private String nickName;
}

View File

@ -1,37 +1,42 @@
package com.java2nb.novel.core.wrapper;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.Arrays;
import java.util.List;
/**
* XSS过滤处理
*
* @author Administrator
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
{
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
/**
* 假如有有html 代码是自己传来的 需要设定对应的name 不过滤
*/
private static final List<String> noFilterNames = Arrays.asList("content");
/**
* @param request
*/
public XssHttpServletRequestWrapper(HttpServletRequest request)
{
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String[] getParameterValues(String name)
{
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values != null)
{
if (!noFilterNames.contains(name) && values != null) {
int length = values.length;
String[] escapseValues = new String[length];
for (int i = 0; i < length; i++)
{
// 防xss攻击和过滤前后空格
escapseValues[i] = values[i].replaceAll("<","&lt;").replaceAll(">","&gt;");
for (int i = 0; i < length; i++) {
escapseValues[i] = values[i].replaceAll("<", "&lt;").replaceAll(">", "&gt;");
}
return escapseValues;
}
return super.getParameterValues(name);
return values;
}
}

View File

@ -0,0 +1,42 @@
package com.java2nb.novel.service;
import com.java2nb.novel.entity.Author;
import com.java2nb.novel.entity.FriendLink;
import java.util.List;
/**
* @author 11797
*/
public interface AuthorService {
/**
* 校验笔名是否存在
* @param penName 校验的笔名
* @return true存在该笔名false: 不存在该笔名
* */
Boolean checkPenName(String penName);
/**
* 作家注册
* @param userId 注册用户ID
*@param author 注册信息
* @return 返回错误信息
* */
String register(Long userId, Author author);
/**
* 判断是否是作家
* @param userId 用户ID
* @return true是作家false: 不是作家
* */
Boolean isAuthor(Long userId);
/**
* 查询作家信息
* @param userId 用户ID
* @return 作家对象
* */
Author queryAuthor(Long userId);
}

View File

@ -191,4 +191,37 @@ public interface BookService {
* @param bookId 小说ID
*/
void updateBookPicToLocal(String picUrl, Long bookId);
/**
* 通过作者ID查询小说分页列表
* @param userId 用户ID
* @param page 页码
* @param pageSize 分页大小
* */
List<Book> listBookPageByUserId(Long userId, int page, int pageSize);
/**
* 发布小说
* @param book 小说信息
* @param authorId 作家ID
* @param penName 作家笔名
* */
void addBook(Book book, Long authorId, String penName);
/**
* 更新小说状态,上架或下架
* @param bookId 小说ID
* @param status 更新的状态
* @param authorId 作者ID
* */
void updateBookStatus(Long bookId, Byte status, Long authorId);
/**
* 发布章节内容
* @param bookId 小说ID
* @param indexName 章节名
* @param content 章节内容
* @param authorId 作者ID
* */
void addBookContent(Long bookId, String indexName, String content, Long authorId);
}

View File

@ -2,6 +2,7 @@ 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;
@ -122,4 +123,19 @@ public interface UserService {
* @param userId 用户ID
* @param amount 增加的余额 */
void addAmount(Long userId, int amount);
/**
* 判断用户是否购买过该小说章节
* @param userId 用户ID
* @param bookIndexId 章节目录ID
* @return true:购买过false:没购买
* */
boolean queryIsBuyBookIndex(Long userId, Long bookIndexId);
/**
* 购买小说章节
* @param userId 用户ID
* @param buyRecord 购买信息
* */
void buyBookIndex(Long userId, UserBuyRecord buyRecord);
}

View File

@ -0,0 +1,92 @@
package com.java2nb.novel.service.impl;
import com.java2nb.novel.core.cache.CacheKey;
import com.java2nb.novel.core.cache.CacheService;
import com.java2nb.novel.core.enums.ResponseStatus;
import com.java2nb.novel.core.exception.BusinessException;
import com.java2nb.novel.entity.Author;
import com.java2nb.novel.entity.FriendLink;
import com.java2nb.novel.mapper.*;
import com.java2nb.novel.service.AuthorService;
import com.java2nb.novel.service.FriendLinkService;
import lombok.RequiredArgsConstructor;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.mybatis.dynamic.sql.select.CountDSLCompleter;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import static com.java2nb.novel.mapper.AuthorCodeDynamicSqlSupport.authorCode;
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.book;
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.id;
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.updateTime;
import static com.java2nb.novel.mapper.FriendLinkDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import static org.mybatis.dynamic.sql.select.SelectDSL.select;
/**
* @author 11797
*/
@Service
@RequiredArgsConstructor
public class AuthorServiceImpl implements AuthorService {
private final AuthorMapper authorMapper;
private final AuthorCodeMapper authorCodeMapper;
@Override
public Boolean checkPenName(String penName) {
return authorMapper.count(c ->
c.where(AuthorDynamicSqlSupport.penName, isEqualTo(penName))) > 0;
}
@Transactional(rollbackFor = Exception.class)
@Override
public String register(Long userId, Author author) {
Date currentDate = new Date();
//判断邀请码是否有效
if (authorCodeMapper.count(c ->
c.where(AuthorCodeDynamicSqlSupport.inviteCode, isEqualTo(author.getInviteCode()))
.and(AuthorCodeDynamicSqlSupport.isUse, isEqualTo((byte) 0))
.and(AuthorCodeDynamicSqlSupport.validityTime, isGreaterThan(currentDate))) > 0) {
//邀请码有效
//保存作家信息
author.setUserId(userId);
author.setCreateTime(currentDate);
authorMapper.insertSelective(author);
//设置邀请码状态为已使用
authorCodeMapper.update(update(authorCode)
.set(AuthorCodeDynamicSqlSupport.isUse)
.equalTo((byte) 1)
.where(AuthorCodeDynamicSqlSupport.inviteCode,isEqualTo(author.getInviteCode()))
.build()
.render(RenderingStrategies.MYBATIS3));
return "";
} else {
//邀请码无效
return "邀请码无效!";
}
}
@Override
public Boolean isAuthor(Long userId) {
return authorMapper.count(c ->
c.where(AuthorDynamicSqlSupport.userId, isEqualTo(userId))) > 0;
}
@Override
public Author queryAuthor(Long userId) {
return authorMapper.selectMany(
select(AuthorDynamicSqlSupport.id,AuthorDynamicSqlSupport.penName,AuthorDynamicSqlSupport.status)
.from(AuthorDynamicSqlSupport.author)
.where(AuthorDynamicSqlSupport.userId,isEqualTo(userId))
.build()
.render(RenderingStrategies.MYBATIS3)).get(0);
}
}

View File

@ -14,6 +14,7 @@ import com.java2nb.novel.entity.*;
import com.java2nb.novel.entity.Book;
import com.java2nb.novel.mapper.*;
import com.java2nb.novel.search.BookSP;
import com.java2nb.novel.service.AuthorService;
import com.java2nb.novel.service.BookService;
import com.java2nb.novel.vo.BookCommentVO;
import com.java2nb.novel.vo.BookSettingVO;
@ -73,6 +74,8 @@ public class BookServiceImpl implements BookService {
private final CacheService cacheService;
private final AuthorService authorService;
@SneakyThrows
@Override
@ -194,7 +197,7 @@ public class BookServiceImpl implements BookService {
@Override
public Book queryBookDetail(Long bookId) {
SelectStatementProvider selectStatement = select(id, catName, catId, picUrl, bookName, authorId, authorName, bookDesc, bookStatus, visitCount, wordCount, lastIndexId, lastIndexName, lastIndexUpdateTime,score)
SelectStatementProvider selectStatement = select(id, catName, catId, picUrl, bookName, authorId, authorName, bookDesc, bookStatus, visitCount, wordCount, lastIndexId, lastIndexName, lastIndexUpdateTime,score,status)
.from(book)
.where(id, isEqualTo(bookId))
.build()
@ -211,7 +214,7 @@ public class BookServiceImpl implements BookService {
PageHelper.startPage(1,limit);
}
SelectStatementProvider selectStatement = select(BookIndexDynamicSqlSupport.id, BookIndexDynamicSqlSupport.bookId, BookIndexDynamicSqlSupport.indexNum, BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.updateTime)
SelectStatementProvider selectStatement = select(BookIndexDynamicSqlSupport.id, BookIndexDynamicSqlSupport.bookId, BookIndexDynamicSqlSupport.indexNum, BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.updateTime,BookIndexDynamicSqlSupport.isVip)
.from(bookIndex)
.where(BookIndexDynamicSqlSupport.bookId, isEqualTo(bookId))
.build()
@ -222,7 +225,7 @@ public class BookServiceImpl implements BookService {
@Override
public BookIndex queryBookIndex(Long bookIndexId) {
SelectStatementProvider selectStatement = select(BookIndexDynamicSqlSupport.id, BookIndexDynamicSqlSupport.bookId, BookIndexDynamicSqlSupport.indexNum, BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.wordCount, BookIndexDynamicSqlSupport.updateTime)
SelectStatementProvider selectStatement = select(BookIndexDynamicSqlSupport.id, BookIndexDynamicSqlSupport.bookId, BookIndexDynamicSqlSupport.indexNum, BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.wordCount, BookIndexDynamicSqlSupport.updateTime,BookIndexDynamicSqlSupport.isVip)
.from(bookIndex)
.where(BookIndexDynamicSqlSupport.id, isEqualTo(bookIndexId))
.build()
@ -302,6 +305,7 @@ public class BookServiceImpl implements BookService {
}
SelectStatementProvider selectStatement = select(id, catId, catName, bookName, lastIndexId, lastIndexName, authorId, authorName, picUrl, bookDesc, wordCount, lastIndexUpdateTime)
.from(book)
.where(wordCount,isGreaterThan(0))
.orderBy(sortSpecification)
.limit(limit)
.build()
@ -454,5 +458,103 @@ public class BookServiceImpl implements BookService {
}
@Override
public List<Book> listBookPageByUserId(Long userId, int page, int pageSize) {
PageHelper.startPage(page,pageSize);
SelectStatementProvider selectStatement = select(id, bookName, visitCount, lastIndexName, status)
.from(book)
.where(authorId, isEqualTo(authorService.queryAuthor(userId).getId()))
.orderBy(BookDynamicSqlSupport.createTime.descending())
.build()
.render(RenderingStrategies.MYBATIS3);
return bookMapper.selectMany(selectStatement);
}
@Override
public void addBook(Book book, Long authorId, String penName) {
//判断小说名是否存在
if(queryIdByNameAndAuthor(book.getBookName(),penName)!=null){
//该作者发布过此书名的小说
throw new BusinessException(ResponseStatus.BOOKNAME_EXISTS);
};
book.setAuthorName(penName);
book.setAuthorId(authorId);
book.setVisitCount(0L);
book.setWordCount(0);
book.setScore(6.5f);
book.setLastIndexName("");
book.setCreateTime(new Date());
book.setUpdateTime(book.getCreateTime());
bookMapper.insertSelective(book);
}
@Override
public void updateBookStatus(Long bookId, Byte status, Long authorId) {
bookMapper.update(update(book)
.set(BookDynamicSqlSupport.status)
.equalTo(status)
.where(id,isEqualTo(bookId))
.and(BookDynamicSqlSupport.authorId,isEqualTo(authorId))
.build()
.render(RenderingStrategies.MYBATIS3));
}
@Transactional
@Override
public void addBookContent(Long bookId, String indexName, String content, Long authorId) {
Book book = queryBookDetail(bookId);
if(!authorId.equals(book.getAuthorId())){
//并不是更新自己的小说
return;
}
Long lastIndexId = new IdWorker().nextId();
Date currentDate = new Date();
int wordCount = content.length();
//更新小说主表信息
bookMapper.update(update(BookDynamicSqlSupport.book)
.set(BookDynamicSqlSupport.lastIndexId)
.equalTo(lastIndexId)
.set(BookDynamicSqlSupport.lastIndexName)
.equalTo(indexName)
.set(BookDynamicSqlSupport.lastIndexUpdateTime)
.equalTo(currentDate)
.set(BookDynamicSqlSupport.wordCount)
.equalTo(book.getWordCount()+wordCount)
.where(id,isEqualTo(bookId))
.and(BookDynamicSqlSupport.authorId,isEqualTo(authorId))
.build()
.render(RenderingStrategies.MYBATIS3));
//更新小说目录表
int indexNum = 0;
if(book.getLastIndexId() != null){
indexNum = queryBookIndex(book.getLastIndexId()).getIndexNum()+1;
}
BookIndex lastBookIndex = new BookIndex();
lastBookIndex.setId(lastIndexId);
lastBookIndex.setWordCount(wordCount);
lastBookIndex.setIndexName(indexName);
lastBookIndex.setIndexNum(indexNum);
lastBookIndex.setBookId(bookId);
lastBookIndex.setIsVip(book.getStatus());
lastBookIndex.setCreateTime(currentDate);
lastBookIndex.setUpdateTime(currentDate);
bookIndexMapper.insertSelective(lastBookIndex);
//更新小说内容表
BookContent bookContent = new BookContent();
bookContent.setIndexId(lastIndexId);
bookContent.setContent(content);
bookContentMapper.insertSelective(bookContent);
}
}

View File

@ -3,14 +3,12 @@ package com.java2nb.novel.service.impl;
import com.github.pagehelper.PageHelper;
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;
import com.java2nb.novel.entity.User;
import com.java2nb.novel.entity.UserBookshelf;
import com.java2nb.novel.entity.UserFeedback;
import com.java2nb.novel.entity.UserReadHistory;
import com.java2nb.novel.mapper.*;
import com.java2nb.novel.vo.BookReadHistoryVO;
import com.java2nb.novel.vo.BookShelfVO;
@ -31,6 +29,8 @@ 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.*;
import static com.java2nb.novel.mapper.UserFeedbackDynamicSqlSupport.userFeedback;
@ -54,6 +54,8 @@ public class UserServiceImpl implements UserService {
private final UserFeedbackMapper userFeedbackMapper;
private final UserBuyRecordMapper userBuyRecordMapper;
@Override
@ -84,13 +86,14 @@ public class UserServiceImpl implements UserService {
UserDetails userDetails = new UserDetails();
userDetails.setId(id);
userDetails.setUsername(entity.getUsername());
userDetails.setNickName(entity.getNickName());
return userDetails;
}
@Override
public UserDetails login(UserForm form) {
//根据用户名密码查询记录
SelectStatementProvider selectStatement = select(id, username)
SelectStatementProvider selectStatement = select(id, username,nickName)
.from(user)
.where(username, isEqualTo(form.getUsername()))
.and(password, isEqualTo(MD5Util.MD5Encode(form.getPassword(), Charsets.UTF_8.name())))
@ -102,7 +105,9 @@ public class UserServiceImpl implements UserService {
}
//生成UserDetail对象并返回
UserDetails userDetails = new UserDetails();
userDetails.setId(users.get(0).getId());
User user = users.get(0);
userDetails.setId(user.getId());
userDetails.setNickName(user.getNickName());
userDetails.setUsername(form.getUsername());
return userDetails;
}
@ -266,5 +271,40 @@ public class UserServiceImpl implements UserService {
}
@Override
public boolean queryIsBuyBookIndex(Long userId, Long bookIndexId) {
return userBuyRecordMapper.count(c ->
c.where(UserBuyRecordDynamicSqlSupport.userId, isEqualTo(userId))
.and(UserBuyRecordDynamicSqlSupport.bookIndexId,isEqualTo(bookIndexId))) > 0;
}
@Transactional(rollbackFor = Exception.class)
@Override
public void buyBookIndex(Long userId, UserBuyRecord buyRecord) {
//查询用户余额
long balance = userInfo(userId).getAccountBalance();
if(balance<10){
//余额不足
throw new BusinessException(ResponseStatus.USER_NO_BALANCE);
}
buyRecord.setUserId(userId);
buyRecord.setCreateTime(new Date());
buyRecord.setBuyAmount(10);
//生成购买记录
userBuyRecordMapper.insertSelective(buyRecord);
//减少用户余额
userMapper.update(update(user)
.set(UserDynamicSqlSupport.accountBalance)
.equalTo(balance-10)
.where(id,isEqualTo(userId))
.build()
.render(RenderingStrategies.MYBATIS3));
}
}

View File

@ -23,7 +23,7 @@ xss:
# 排除链接多个用逗号分隔
excludes: /system/notice/*
# 匹配链接 多个用逗号分隔
urlPatterns: /book/addBookComment,/user/addFeedBack
urlPatterns: /book/addBookComment,/user/addFeedBack,/author/addBook,/author/addBookContent,/author/register.html

View File

@ -4,34 +4,33 @@
<mapper namespace="com.java2nb.novel.mapper.FrontBookMapper">
<select id="searchByPage" parameterType="com.java2nb.novel.search.BookSP" resultType="com.java2nb.novel.vo.BookVO">
select id,cat_id,cat_name,book_name,author_id,author_name,word_count,last_index_id,last_index_name,score,pic_url,book_status,last_index_update_time,book_desc
from book
<where>
<if test="keyword != null and keyword != ''">
and (book_name like concat('%',#{keyword},'%') or author_name like concat('%',#{keyword},'%'))
</if>
<if test="workDirection != null">
and work_direction = #{workDirection}
</if>
<if test="catId != null">
and cat_id = #{catId}
</if>
<if test="isVip != null">
and is_vip = #{isVip}
</if>
<if test="bookStatus != null">
and book_status = #{bookStatus}
</if>
<if test="wordCountMin != null">
and word_count >= #{wordCountMin}
</if>
<if test="wordCountMax != null">
and word_count <![CDATA[ < ]]> #{wordCountMax}
</if>
<if test="updateTimeMin != null">
and last_index_update_time >= #{updateTimeMin}
</if>
</where>
select
id,cat_id,cat_name,book_name,author_id,author_name,word_count,last_index_id,last_index_name,score,pic_url,book_status,last_index_update_time,book_desc
from book where word_count > 0
<if test="keyword != null and keyword != ''">
and (book_name like concat('%',#{keyword},'%') or author_name like concat('%',#{keyword},'%'))
</if>
<if test="workDirection != null">
and work_direction = #{workDirection}
</if>
<if test="catId != null">
and cat_id = #{catId}
</if>
<if test="isVip != null">
and is_vip = #{isVip}
</if>
<if test="bookStatus != null">
and book_status = #{bookStatus}
</if>
<if test="wordCountMin != null">
and word_count >= #{wordCountMin}
</if>
<if test="wordCountMax != null">
and word_count <![CDATA[ < ]]> #{wordCountMax}
</if>
<if test="updateTimeMin != null">
and last_index_update_time >= #{updateTimeMin}
</if>
</select>
@ -59,7 +58,7 @@
limit #{offset},#{limit}
</select>
<select id="selectIdsByScoreAndRandom" parameterType="int" resultType="com.java2nb.novel.entity.Book">
<select id="selectIdsByScoreAndRandom" parameterType="int" resultType="com.java2nb.novel.entity.Book">
select id,book_name,author_name,pic_url,book_desc,score from book ORDER BY score,RAND() LIMIT #{limit};
</select>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,617 @@
var $C = function (objName) {
if (typeof (document.getElementById(objName)) != "object")
{ return null; }
else
{ return document.getElementById(objName); }
}
var YT = {
BaseCommon: {
gL: function (x) { var l = 0; while (x) { l += x.offsetLeft; x = x.offsetParent; } return l },
gT: function (x) { var t = 0; while (x) { t += x.offsetTop; x = x.offsetParent; } return t }
},
BaseData: {
WaitImg: "/images/loading.gif"
},
Fun: {
GetWordLength: function (str) {
str = str.replace(/(\n)+|(\r\n)+/g, "");
str = str.replace(" ", "");
str = str.replace(" ", "");
return str.length;
},
ConvertToMoney: function (btanch) {
if (btanch != undefined) {
return parseFloat(btanch) / 100;
}
else {
return 0;
}
},
LoadShow: function () {
if ($C("LayerShowPic") == null) {
var sp = document.createElement("div");
sp.innerHTML = "<div id=\"LayerShowPic\" style=\"position:absolute;width:180px;height:70px;z-index:100;background-color: #fdfce9;border: 1px solid #666666;font-size:12px;\"><div align=\"center\" style=\"z-index:91;\"><br><img src=\"" + YT.BaseData.WaitImg + "\" align=\"absmiddle\" /> 请稍后…</div></div><iframe id=\"LayerCover\" style=\"position:absolute;width:100%;height:100%;z-index:10;left: 0px;top: 0px;background-color:#eeeeee;FILTER: alpha(opacity=1);opacity: 0.3 !important; \"></iframe>";
document.body.appendChild(sp);
}
$C("LayerShowPic").style.display = '';
$C("LayerCover").style.display = '';
$C("LayerCover").style.height = String(document.documentElement.scrollHeight) + 'px';
YT.Fun.ScreenCenter($C("LayerShowPic"), 266, 200);
},
LoadHide: function () {
if ($C("LayerShowPic") != null) {
$C("LayerShowPic").style.display = 'none';
$C("LayerCover").style.display = 'none';
}
},
ScreenCenter: function (obj, width, height) {
if (obj.style.display == 'none') {
obj.style.display = '';
}
var scrolltop = document.documentElement.scrollTop;
if (width <= 0) {
width = obj.offsetWidth;
}
if (height <= 0) {
height = obj.offsetHeight;
}
if (scrolltop == null || scrolltop == 0) {
scrolltop = document.body.scrollTop;
}
var offsetHT = document.body.clientHeight / 2 - height / 2;
if (offsetHT <= 0) { offsetHT = 10; }
var offsetWT = document.body.clientWidth / 2 - width / 2;
if (offsetWT <= 0) { offsetWT = 10; }
obj.style.top = String(scrolltop + offsetHT) + 'px';
obj.style.left = String(offsetWT) + 'px';
},
NewPanel: function (url, title, width, height, needFits) {
if (typeof (width) == 'undefind' || width == null) { width = 750; }
if (typeof (height) == 'undefind' || height == null) { height = 550; }
var fits = false;
if (typeof (needFits) != "undefined" && needFits) {
if (document.body.clientWidth < 650 || document.body.clientHeight < 450 || document.body.clientHeight - 50 < height)
{ fits = true; }
}
if ($C("YT_Panel") == null) {
var sp = document.createElement("div");
sp.innerHTML = "<div id=\"YT_Panel\" class=\"easyui-panel\"><iframe frameborder=\"0\" id=\"YT_Panel_i\" name=\"YT_Panel_i\" scrolling=\"auto\" src=\"" + url + "\" style=\"height:100%;visibility:inherit; width:100%;z-index:1;\"></iframe></div>";
document.body.appendChild(sp);
}
if (url.indexOf("?") > 0) {
url = url + "&";
}
else {
url = url + "?";
}
url = url + "randomkeys=" + Math.random();
$C("YT_Panel_i").src = url;
var sTop = null, sLeft = null;
if (window.screen.height < 800) {
sTop = 0;
}
if (fits) {
sLeft = 0;
}
$('#YT_Panel').window({
width: width,
height: height,
title: title,
collapsible: true,
minimizable: false,
maximizable: true,
closable: true,
modal: true,
fit: fits,
top: sTop,
left: sLeft
});
},
NewPanelNoClose: function (url, title, width, height) {
if (typeof (width) == 'undefind' || width == null) { width = 750; }
if (typeof (height) == 'undefind' || height == null) { height = 550; }
if ($C("YT_Panel") == null) {
var sp = document.createElement("div");
sp.innerHTML = "<div id=\"YT_Panel\" class=\"easyui-panel\" ><iframe frameborder=\"0\" id=\"YT_Panel_i\" name=\"YT_Panel_i\" scrolling=\"auto\" src=\"" + url + "\" style=\"height:100%;visibility:inherit; width:100%;z-index:1;\"></iframe></div>";
document.body.appendChild(sp);
}
if (url.indexOf("?") > 0) {
url = url + "&";
}
else {
url = url + "?";
}
url = url + "randomkeys=" + Math.random();
$C("YT_Panel_i").src = url;
$('#YT_Panel').window({
width: width,
height: height,
title: title,
collapsible: false,
minimizable: false,
maximizable: true,
closable: false,
modal: true
});
},
ClosePanel: function (id) {
if (typeof (id) == 'undefind' || id == null) {
$('#YT_Panel').panel('close');
/*CreateGrid();*/
CreateGridReload();
}
else { $('#' + id).panel('close'); }
},
/*格式化时间字符串*/
formatDate: function (now, types) {
if (now != null && now != "") {
var dateN = new Date(+/\d+/.exec(now)[0]);
var year = dateN.getFullYear();
var month = dateN.getMonth() + 1;
var date = dateN.getDate();
var hour = dateN.getHours();
var minute = dateN.getMinutes();
var second = dateN.getSeconds();
if (typeof (types) != "undefined" && types != null) {
return year + "-" + month + "-" + date;
}
else if (hour == 0 && minute == 0 && second == 0) {
return year + "-" + month + "-" + date;
}
else {
return year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + second;
}
}
else {
return "";
}
},
/** 获取当前时间月份*/
formatMonth: function (now) {
if (now != null && now != "") {
var dateN = new Date(+/\d+/.exec(now)[0]);
var month = dateN.getMonth() + 1;
return month;
}
else {
return "";
}
},
/** 获取当前时间具体的某一天*/
formatDay: function (now) {
if (now != null && now != "") {
var dateN = new Date(+/\d+/.exec(now)[0]);
var month = dateN.getMonth() + 1;
var date = dateN.getDate();
return month + "-" + date;
}
else {
return "";
}
},
/** 获取所属时间的季度*/
formatSeasonal: function (now) {
if (now != null && now != "") {
var dateN = new Date(+/\d+/.exec(now)[0]);
var year = dateN.getFullYear();
var month = dateN.getMonth() + 1;
if (month == 1) {
return year + "年第1季度";
}
else if (month == 4) {
return year + "年第2季度";
}
else if (month == 7) {
return year + "年第三季度";
}
else {
return year + "年第四季度";
}
}
else {
return "";
}
},
formatStatus: function (id) {
if (id == 0) {
return "无效";
}
else {
return "有效";
}
},
ShowPanel: function (obj, divName, xlong, ylong) {
var showobj = $C(divName);
if (showobj) {
if (showobj.style.display == 'none') {
showobj.style.display = '';
}
if (xlong)
{ showobj.style.top = YT.BaseCommon.gT(obj) + 20 + xlong + "px"; }
else
{ showobj.style.top = YT.BaseCommon.gT(obj) + 20 + "px"; }
if (ylong)
{ showobj.style.left = YT.BaseCommon.gL(obj) + ylong + "px"; }
else
{ showobj.style.left = YT.BaseCommon.gL(obj) + "px"; }
}
},
GetDateDiff:function(startTime,endTime, diffType) {
startTime = startTime.replace(/\-/g, "/");
endTime= endTime.replace(/\-/g, "/");
diffType = diffType.toLowerCase();
var sTime = new Date(startTime);
var eTime = new Date(endTime);
var timeType = 1;
switch (diffType) {
case "second":
timeType = 1000;
break;
case "minute":
timeType = 1000 * 60;
break;
case "hour":
timeType = 1000 * 3600;
break;
case "day":
timeType = 1000 * 3600 * 24;
break;
default:
break;
}
return parseInt((eTime.getTime() - sTime.getTime()) / parseInt(timeType));
}
},
Dirt: {
/*绑定到列表*/
BindList: function (listId, dirtName, needBlock) {
var obj = $C(listId);
if (obj != undefined) {
obj.length = 0;
var objV = eval("DirtInfo." + dirtName);
if (objV != undefined && objV != null) {
for (var i = 0; i < objV.length; i++) {
obj.options.add(new Option(objV[i][1], objV[i][0]));
}
}
if (needBlock) {
obj.options.add(new Option("请选择", "0"));
obj.value = "";
}
}
},
/*获取值表示的意义*/
GetName: function (dirtName, dValue) {
var obj = eval("DirtInfo." + dirtName);
if (obj != undefined && obj != null) {
for (var i = 0; i < obj.length; i++) {
if (obj[i][0] == dValue) {
return obj[i][1];
}
}
}
return "";
}
},
Cookie: function (name, value, options) {
if (typeof value != 'undefined') { /* name and value given, set cookie*/
options = options || {};
if (value === null) {
value = '';
options.expires = -1;
}
var expires = '';
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
var date;
if (typeof options.expires == 'number') {
date = new Date();
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString(); /* use expires attribute, max-age is not supported by IE */
}
var path = options.path ? '; path=' + options.path : '';
var domain = options.domain ? '; domain=' + options.domain : '';
var secure = options.secure ? '; secure' : '';
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
} else { /* only name given, get cookie */
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
}
}
/*重新定义录入框校验规则*/
$.extend($.fn.validatebox.defaults.rules, {
chinaMobile: {/*手机号码*/
validator: function (value, param) {
var reg = /^(13|14|15|17|18)\d{9}$/;
var reglt = /^(\d{3}|\d{4})-\d{8}$/;
/*var reg = /^\d{11,12}$/;*/
if (value.indexOf('-') > 0) {
return reglt.test(value);
}
else {
return reg.test(value);
}
}, message: '手机号码有误'
},
chinaName: {/*中文名称*/
validator: function (value, param) {
// var reg = /^[\u4e00-\u9fa5a-zA-Z0-9]{2,6}$/;
var reg = /^[a-zA-Z\u4e00-\u9fa5][a-zA-Z0-9\u4e00-\u9fa5]{1,5}$/;
// var reg = /^[\u4e00-\u9fa5,a-zA-Z0-9]{2,5}$/;
return reg.test(value);
}, message: '在笔名中数字不能开头,且昵称的长度应在2-6之间'
},
realName: {/*真实姓名*/
validator: function (value, param) {
// var reg = /^[a-zA-Z\u4e00-\u9fa5][a-zA-Z0-9\u4e00-\u9fa5]{1,5}$/;
var reg = /^[\u4e00-\u9fa5,a-zA-Z0-9]{2,5}$/;
return reg.test(value);
}, message: '真实姓名的长度为2-5位中文字符'
},
maxLength: {
validator: function (value, param) {
$.fn.validatebox.defaults.rules.maxLength.message = '只能少于' + param + '字符串';
return value.length < param;
}
},
isNumber: {
validator: function (value, param) {
var reg = /^(-|[0-9])(|\d{1,9})$/;
return reg.test(value);
}, message: '必须是数字'
},
isBankNumber: {
validator: function (value, param) {
var reg = /^([0-9]{16}|[0-9]{19})$/;
return reg.test(value);
}, message: '银行卡号错误'
},
isEmail: {
validator: function (value, param) {
var reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/;
return reg.test(value);
}, message: '邮箱格式错误'
},
isPosInt: {
validator: function (value, param) {
var reg = /^(\d{1,9})$/;
if (reg.test(value) && value > 0) {
return true;
}
else {
return false;
}
}, message: '必须是大于0的正整数'
},
isPosIntTen: {
validator: function (value, param) {
var reg = /^(\d{1,9})$/;
if (reg.test(value) && value > 10) {
return true;
}
else {
return false;
}
}, message: '必须是大于10的正整数'
},
isDate: {
validator: function (value, param) {
var reg = /^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29))$/;
return reg.test(value);
}, message: 'yyyy-MM-dd'
},
isIdCard: {
validator: function (value, param) {
var reg = /^(^\d{15}$|^\d{18}$|^\d{17}(\d|X|x))$/;
return isCardID(value);
}, message: '身份证号码错误'
},
isFloat: {
validator: function (value, param) {
var reg = /^(^\+?[1-9][0-9]*$)$|^(\d{1,9}\.\d{1,9})$/;
return reg.test(value);
}, message: '必须是大于零的数字'
},
isFloatMin0:
{
validator: function (value, param) {
var reg = /^(^\d{1,9})$|^(\d{1,9}\.\d{1,9})$/;
return reg.test(value);
}, message: '必须是大于零的数字'
},
isPassWord: {
validator: function (value, param) {
var reg = /^[a-zA-Z0-9_]{5,15}$/;
return reg.test(value);
}, message: '密码格式错误'
},
isConfirmPassword: {
validator: function (value, param) {
return $(param[0]).val() == value;
}, message: '两次录入的密码不同'
},
phoneCheck: {
validator: function (value, param) {
var reg = /^(((\()?\d{2,4}(\))?[-(\s)*]){0,2})?(\d{8})$/;
return reg.test(value);
}, message: '输入的电话不正确'
},
isUserName: {
validator: function (value, param) {
var reg = /^[a-zA-Z0-9_]{3,15}$/;
return reg.test(value);
}, message: '用户名格式错误'
},
equalTo: {
validator: function (value, param) {
return $(param[0]).val() == value;
},
message: '字段不匹配'
}
});
/*空函数*/
function CreateGrid() { }
function CreateGridReload() { }
/*身份证校验正确性*/
var NumbCardCity = { 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 21: "辽宁", 22: "吉林", 23: "黑龙江", 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西", 37: "山东", 41: "河南", 42: "湖北", 43: "湖南", 44: "广东", 45: "广西", 46: "海南", 50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏", 61: "陕西", 62: "甘肃", 63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外" };
function isCardID(sId) {
var iSum = 0;
var info = "";
if (!/^\d{17}(\d|x)$/i.test(sId)) return false; /* "你输入的身份证长度或格式错误"; */
sId = sId.replace(/x$/i, "a");
if (NumbCardCity[parseInt(sId.substr(0, 2))] == null) return false; /*"你的身份证地区非法";*/
sBirthday = sId.substr(6, 4) + "-" + Number(sId.substr(10, 2)) + "-" + Number(sId.substr(12, 2));
var d = new Date(sBirthday.replace(/-/g, "/"));
if (sBirthday != (d.getFullYear() + "-" + (d.getMonth() + 1) + "-" + d.getDate())) return false; /* "身份证上的出生日期非法";*/
for (var i = 17; i >= 0; i--) iSum += (Math.pow(2, i) % 11) * parseInt(sId.charAt(17 - i), 11);
if (iSum % 11 != 1) return false; /*"你输入的身份证号非法";*/
return true;
}
function getSex(val) {
if (parseInt(val.charAt(16) / 2) * 2 != val.charAt(16))
return '1';
else
return '0';
}
function showBirthday(val) {
var mm;
if (18 == val.length) {/*18位身份证号码*/
mm = val.charAt(6) + val.charAt(7) + val.charAt(8) + val.charAt(9) + '-' + val.charAt(10) + val.charAt(11) + '-' + val.charAt(12) + val.charAt(13);
}
return mm;
}
var DirtInfo = {
TrueOrFalse: [[0, ""], [1, ""]],
EnumUserCommendStatus: [[0, ""], [1, "已处理"], [2, "已查看"]],
AvailablesStatus: [[0, "禁用"], [1, "可用"]],
SettleClass: [[0, "现金"], [1, "预付扣款"]],
EnumSexClass: [[0, "不限"], [1, ""], [2, ""]],
EnumUserType: [[1, "手机端app"], [2, "手机wap端"]],
EnumPayClass: [[1, "支付宝"], [2, "微信"], [3, "微信扫码"], [100, "绑定手机奖励"]],
EnumPayStatus: [[0, "新申请"], [2, "充值失败"], [3, "成功"]],
EnumMoneyClass: [[0, "购买"], [1, "赠送"]],
EnumUserFrom: [[1, "其他"], [2, "微博"], [3, "qq"], [4, "微信"], [10, "app注册"], [11, "wap注册"], [12, "微博绑定"], [13, "qq绑定"], [14, "微信绑定"]],
EnumSignType: [[0, "未签约"], [1, "分成"], [2, "买断"], [3, "保底"], [4, "买断整本"], [9, "保底"], [15, "道具结算"], [30, "全勤奖励"]],
EnumLogType: [[0, "app登录"], [1, "wap登录"]],
EnumAuditStatus: [[-10, "下线"], [-1, "审核失败"], [0, "编辑中"], [1, "提交申请"], [2, "通过审核"], [3, "已发布"]],
EnumHandleStatus: [[-1, "处理失败"], [0, "新申请"], [1, "待处理"], [2, "处理成功"]],
EnumAuthorLevel: [[1, "一级"], [2, "二级"], [3, "三级"], [4, "四级"], [5, "五级"]],
EnumChannelClass: [[0, "特级"], [1, "一级"], [2, "二级"], [3, "三级"], [4, "四级"], [5, "五级"], [6, "六级"], [7, "七级"], [8, "八级"], [9, "九级"], [1100, "千级"]],
EnumVipChapter: [[0, "公众"], [1, "VIP"]],
EnumBookLeveType: [[1, "A级"], [2, "B级"], [3, "C级"], [4, "普通"], [5, "S级"]],
EnumBookLeveTypeL: [[1, "A"], [2, "B"], [3, "C"]],
EnumAdmActClass: [[50, "签约等级修改"], [51, "封面修改"], [52, "渠道添加"], [53, "渠道修改"], [54, "渠道删除"], [55, "章节删除"]],
EnumSettlementType: [[0, "未结算"], [1, "已结算"], [2, "结算失败"]],
EnumBookProcess: [[0, "连载"], [1, "完结"]],
EnumAuthStatus: [[1 ,"独家"], [2, "非独家"]]
};
function dateToDate(date) {
var sDate = new Date();
if (typeof date == 'object'
&& typeof new Date().getMonth == "function"
) {
sDate = date;
}
else if (typeof date == "string") {
var arr = date.split('-')
if (arr.length == 3) {
sDate = new Date(arr[0] + '-' + arr[1] + '-' + arr[2]);
}
}
return sDate;
}
function addMonth(date, num) {
num = parseInt(num);
var sDate = dateToDate(date);
var sYear = sDate.getFullYear();
var sMonth = sDate.getMonth() + 1;
var sDay = sDate.getDate();
var eYear = sYear;
var eMonth = sMonth + num;
var eDay = sDay;
while (eMonth > 12) {
eYear++;
eMonth -= 12;
}
var eDate = new Date(eYear, eMonth - 1, eDay);
while (eDate.getMonth() != eMonth - 1) {
eDay--;
eDate = new Date(eYear, eMonth - 1, eDay);
}
return eDate;
}
function checkAll() {
if ($("#selAll").attr("checked")) {
$("input[name='selBox']").each(function () {
$(this).attr("checked", true);
});
}
else {
$("input[name='selBox']").each(function () {
$(this).removeAttr("checked");
});
}
}
$(function () {
initSubmitButton(3);
});
//停留时间
function initSubmitButton(wait) {
$("input[type='submit']").each(function () {
$(this).click(function () {
if ($(this).attr("submited") == "1") {
return false;
}
var oldVal = $(this).val();
$(this).val("正在处理,请稍等(" + wait + ")");
$(this).attr("submited", "1");
setTimeout('ButtonLimit("' + $(this).attr("id") + '",' + wait + ',"' + oldVal + '")', 1000);
});
});
}
function ButtonLimit(objId, wait, oldVal) {
wait--;
if (wait > 0) {
$("#" + objId).val("正在处理,请稍等(" + wait + ")");
setTimeout('ButtonLimit("' + objId + '",' + wait + ',"' + oldVal + '");', 1000);
}
else {
$("#" + objId).removeAttr("submited");
$("#" + objId).val(oldVal);
}
}

View File

@ -1,6 +1,8 @@
var needLoginPath = ['/user/favorites.html','/user/comment.html','/user/feedback.html',
'/user/feedback_list.html','/user/read_history.html','/user/set_name.html',
'/user/set_password.html','/user/set_sex.html','/user/setup.html','/user/userinfo.html',"/pay/index.html"];
'/user/set_password.html','/user/set_sex.html','/user/setup.html','/user/userinfo.html',
"/pay/index.html," +
"/author/register.html","/author/index.html"];
var isLogin = false;
var url = window.location.search;
//key(需要检索的键)
@ -63,7 +65,7 @@ if(!token){
success: function(data){
if(data.code == 200){
$(".user_link").html("<i class=\"line mr20\">|</i>" +
"<a href=\"/user/userinfo.html\" class=\"mr15\">"+data.data.username+"</a>" +
"<a href=\"/user/userinfo.html\" class=\"mr15\">"+data.data.nickName+"</a>" +
"<a href=\"javascript:logout()\" >退出</a>");
;
if("/user/login.html" == window.location.pathname){

View File

@ -0,0 +1,70 @@
if ($.fn.pagination){
$.fn.pagination.defaults.beforePageText = '第';
$.fn.pagination.defaults.afterPageText = '{pages}';
$.fn.pagination.defaults.displayMsg = '显示{from}{to},{total}记录';
}
if ($.fn.datagrid){
$.fn.datagrid.defaults.loadMsg = '请稍后';
}
if ($.fn.treegrid && $.fn.datagrid){
$.fn.treegrid.defaults.loadMsg = $.fn.datagrid.defaults.loadMsg;
}
if ($.messager){
$.messager.defaults.ok = '确定';
$.messager.defaults.cancel = '取消';
}
if ($.fn.validatebox){
$.fn.validatebox.defaults.missingMessage = '该输入项为必输项';
$.fn.validatebox.defaults.rules.email.message = '请输入有效的电子邮件地址';
$.fn.validatebox.defaults.rules.url.message = '请输入有效的URL地址';
$.fn.validatebox.defaults.rules.length.message = '输入内容长度必须介于{0}{1}之间';
$.fn.validatebox.defaults.rules.remote.message = '请修正该字段';
}
if ($.fn.numberbox){
$.fn.numberbox.defaults.missingMessage = '该输入项为必输项';
}
if ($.fn.combobox){
$.fn.combobox.defaults.missingMessage = '该输入项为必输项';
}
if ($.fn.combotree){
$.fn.combotree.defaults.missingMessage = '该输入项为必输项';
}
if ($.fn.combogrid){
$.fn.combogrid.defaults.missingMessage = '该输入项为必输项';
}
if ($.fn.calendar){
$.fn.calendar.defaults.weeks = ['日','一','二','三','四','五','六'];
$.fn.calendar.defaults.months = ['一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'];
}
if ($.fn.datebox){
$.fn.datebox.defaults.currentText = '今天';
$.fn.datebox.defaults.closeText = '关闭';
$.fn.datebox.defaults.okText = '确定';
$.fn.datebox.defaults.missingMessage = '该输入项为必输项';
$.fn.datebox.defaults.formatter = function(date){
var y = date.getFullYear();
var m = date.getMonth()+1;
var d = date.getDate();
return y+'-'+(m<10?('0'+m):m)+'-'+(d<10?('0'+d):d);
};
$.fn.datebox.defaults.parser = function(s){
if (!s) return new Date();
var ss = s.split('-');
var y = parseInt(ss[0],10);
var m = parseInt(ss[1],10);
var d = parseInt(ss[2],10);
if (!isNaN(y) && !isNaN(m) && !isNaN(d)){
return new Date(y,m-1,d);
} else {
return new Date();
}
};
}
if ($.fn.datetimebox && $.fn.datebox){
$.extend($.fn.datetimebox.defaults,{
currentText: $.fn.datebox.defaults.currentText,
closeText: $.fn.datebox.defaults.closeText,
okText: $.fn.datebox.defaults.okText,
missingMessage: $.fn.datebox.defaults.missingMessage
});
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -0,0 +1,2 @@
src/js/util/ierange.js
src/js/util/poly-fill.js

View File

@ -0,0 +1,38 @@
{
"env": {
"browser": true,
"commonjs": true,
"es6": true
},
"globals": {
"ENV": true
},
"extends": "eslint:recommended",
"parserOptions": {
"sourceType": "module"
},
"rules": {
"no-console":0,
"indent": [
"error",
4
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single",
{
"allowTemplateLiterals": true
}
],
"semi": [
"error",
"never"
],
"no-unused-vars": 0,
"no-debugger": 0
}
}

View File

@ -0,0 +1,22 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

View File

@ -0,0 +1,51 @@
#忽略
**/node_modules/*
node_modules/*
npm-debug.log
example/upload-files
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

View File

@ -0,0 +1,5 @@
node_modules/*
npm-debug.log
docs/*
src/*
example/*

View File

@ -0,0 +1,157 @@
# 问题记录
## 版本修复
### v3.0.1
- [done] 如何设置自动增加高度补充文档
- [done] src/js/editor/Bar 改为 Progress仅供上传图片使用
- [done] Panel 在右上角增加一个关闭按钮
- [done] 显示页面 tablequotecode 等样式说明一下
- [done] 增加自定义上传回调函数用以自定义返回图片的格式
- [done] 上传附带的参数也加入到 form-data 中一份
- [done] 编辑器默认情况下菜单栏不能点击必须focus了编辑器求之后才能点击
- [done] 点击菜单弹出panel之后再点击编辑器区域其他地方panel不消失
- [done] 自定义filenamev2版本就有
- [done] ff 中的 bug
- [done] ff 中粘贴图片和文字出现问题 https://github.com/wangfupeng1988/wangEditor/issues/609
- [done] 火狐浏览器下创建表格编辑表格内容时会出现两个控制点有人提供了解决方案
- [done] 配置最多上传的文件个数
- [done] 连续给两段内容 添加有/无序列表时样式会出问题且其他内容找不到了并且编辑器不处于编辑状态
- [done] onchange
- [done] IE11下面一直报错并且表格无法正常使用
### v3.0.2
- [done] onchange 完善 vue react demo
- [done] 插入图片之后光标移动到图片的前面然后回车图片消失并且不能撤销
- [done] 修复上传图片 customInsert 无效的bug
- [done] 编辑区域 z-index 可配置
- [done] 上传图片不应该把状态码限制在 200而是 2xx
- [done] editor.txt.html() 之后没有定位光标位置
### v3.0.3
- [done] 粘贴图片在低版本的谷歌浏览器中无法使用提示验证图片未通过undefined不是图片
- [done] 动态赋值内容会自动换行因为给自动加了`<p><br></p>`
- [done] 不选中任何内容点击加粗报错Failed to execute 'setEnd' on 'Range'
- [done] toolbar 小图标的 z-index 可配置
### v3.0.4
- [done] 允许使用者通过`replace`实现多语言
- [done] `_alert()`可自定义配置提示框
- [done] 支持用户自定义上传图片的事件如用户要上传到七牛云阿里云
### v3.0.5
- [done] 图片上传中insertLinkImg 方法中去掉 img.onload 之后再插入的逻辑吧这样会打乱多个图片的顺序
- [done] `<h>` 标签重叠问题两行文字都是`h2`然后将第一行选中设置为`h1`结果是 `<h2><h1>测试1</h1>测试2</h2>`
- [done] 补充 ng 集成的示例 https://github.com/wangfupeng1988/wangEditor/issues/859
- [done] 菜单不能折叠的说明加入到文档中
- [done] 上传图片 before 函数中增加一个判断可以让用户终止图片的上传
### v3.0.6
- [done] src/fonts 中的字体文件名改一下 icomoon 容易发生冲突
- [done] 将禁用编辑器的操作完善到文档中 https://www.kancloud.cn/wangfupeng/wangeditor3/368562
- [done] 开放表格中的粘贴功能之前因不明问题而封闭
- [done] 代码块中光标定位到最后位置时连续两次回车要跳出代码块
### v3.0.7
- [done] 紧急修复上一个版本导致的菜单图标不显示的 bug
### v3.0.8
- [done] 修复 backColor foreColor 代码文件名混淆的问题
- [done] 修改 IE 引用 的功能
- [done] 增加粘贴过滤样式的可配置
- [done] 修复 IE 粘贴文字的问题
### v3.0.9
- [done] config 上传图片的 token 注视掉
- [done] 将一些常见 API 开放写到文档中 https://www.kancloud.cn/wangfupeng/wangeditor3/404586
- [done] IE 火狐 插入多行代码有问题
- [done] 粘贴时`<p>`不能只粘贴纯文本还得要图片
- [done] 粘贴内容中过滤掉`<!--xxx-->`注释
- [done] **支持上传七牛云存储**
### v3.0.10
- [done] 支持插入网络图片的回调函数
- [done] 插入链接时候的格式校验
- [done] 支持拖拽上传
### v3.0.11
- [done] 如何用 textarea 创建编辑器完善到文档中许多人提问
- [done] 修复`editor.customConfig.customUploadImg`不触发的 bug
- [done] 修复有序列表和无序列表切换时 onchange 不触发的 bug
### v3.0.12
- [done] 增加 onfocus onblur 感谢 [hold-baby](https://github.com/hold-baby) 提交的 [PR](https://github.com/wangfupeng1988/wangEditor/pull/1076)
- [done] 上传的自定义参数`editor.customConfig.uploadImgParams`是否拼接到 url 支持可配置
- [done] onchange 触发的延迟时间支持可配置
### v3.0.13
- [done] 修复图片 选中/取消选中 触发 onchange 的问题
- [done] 修复只通过 length 判断 onchange 是否触发的问题
- [done] 增加插入网络图片的校验函数
- [done] 增加自定义处理粘贴文本的事件
- [done] 修复选中一个图片时点击删除键会误删除其他内容的 bug
- [done] 修复 window chrome 复制图片然后粘贴图片会粘贴为两张的 bug
- [done] 修复无法撤销引用的问题
### v3.0.14
- [done] 可以配置前景色背景色
- [done] 回车时无法从`<p><code>....</code></p>`中跳出
- [done] 增加获取 JSON 格式内容的 API
### v3.0.15
- [done] 表情兼容图片和 emoji 都可自定义配置
### v3.0.16
- [done] 修复粘贴图片的 bug
- [done] 修复`pasteTextHandle`执行两次的问题
- [done] 修复插入链接时文字和链接为空时`linkCheck`不执行的 bug
- [done] 粘贴 html 过滤掉其中的`data-xxx`属性
- [done] 修复中文输入法输入过程中出发 onchange 的问题感谢 [github.com/CongAn](https://github.com/CongAn) PR
- [done] `editor.txt.html``editor.txt.text`替换`&#8203`字符为空字符串
- [done] 精确图片大小计算`maxSize / 1000 / 1000`改为`maxSize / 1024 / 1024`
- [done] 修复 droplist 类型菜单颜色背景色等点击不准确的问题
### v3.0.17
- [done] 合并 pr [菜单和编辑区域分离 onfocus onblur 失效bug](https://github.com/wangfupeng1988/wangEditor/pull/1174) ,感谢 [hold-baby](https://github.com/hold-baby) 提供 pr
- [done] 使用`document.execCommand("styleWithCSS", null, true)`这样设置字体颜色就会用 css 而不是用`<font color=xxx>`
### 近期计划解决
- 撤销的兼容性问题会误伤其他编辑器或者 input textarea 考虑用 onchange 记录 undo redo 的内容但是得考虑直接修改 dom 的情况 quote code img list table 菜单
- 列表撤销会删除一行https://github.com/wangfupeng1988/wangEditor/issues/1131
- 页面中有 input 等输入标签时undo redo 会误伤 https://github.com/wangfupeng1988/wangEditor/issues/1024
- 两个编辑器 undo 的问题 https://github.com/wangfupeng1988/wangEditor/issues/1010
- list undo redo 有问题选中几行先设置有序列表再设置无序列表然后撤销就能复现问题
- 粘贴文字的样式问题可暂时配置 `pasteTextHandle` 自行处理
- 先输入文字再粘贴 excel 表格样式丢失 https://github.com/wangfupeng1988/wangEditor/issues/1000
- IE 11 直接输入文字会空一行在第二行出现内容 https://github.com/wangfupeng1988/wangEditor/issues/919
- windows word excel 的粘贴存在垃圾数据
## 待排期
- 调研 safariIE 和ff中粘贴图片 https://github.com/wangfupeng1988/wangEditor/issues/831
- 图片调整大小表格调整的方式是否用 toolbar 的方式
- 删除掉`./release`之后执行`npm run release`会报错原因是`fonts`文件没拷贝全就要去替换`css`中的字体文件为`base64`格式导致找不到文件
- 先点击'B'再输入内容这种形式前期先支持 webkit IE火狐的支持后面再加上
- 图片压缩 canvas https://github.com/think2011/localResizeIMG
- github 徽章 https://github.com/EyreFree/GitHubBadgeIntroduction
- 将代码在进行拆分做到每个程序只做一件事不要出现过长的代码文件例如 `src/js/command/index.js` `src/js/selection/index.js`

View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2017 王福朋
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,70 @@
# wangEditor
## 介绍
**wangEditor** 轻量级 web 富文本编辑器配置方便使用简单支持 IE10+ 浏览器
- 官网[www.wangEditor.com](http://www.wangeditor.com/)
- 文档[www.kancloud.cn/wangfupeng/wangeditor3/332599](http://www.kancloud.cn/wangfupeng/wangeditor3/332599)
- 源码[github.com/wangfupeng1988/wangEditor](https://github.com/wangfupeng1988/wangEditor) (欢迎 star
![图片](http://images2015.cnblogs.com/blog/138012/201705/138012-20170530202905633-1840158981.png)
*查看 v2 版本的代码和文档点击[这里](https://github.com/wangfupeng1988/wangEditor/tree/v2)*
## 下载
- 直接下载[https://github.com/wangfupeng1988/wangEditor/releases](https://github.com/wangfupeng1988/wangEditor/releases)
- 使用`npm`下载`npm install wangeditor` 注意 `wangeditor` 全部是**小写字母**
- 使用`bower`下载`bower install wangEditor` 前提保证电脑已安装了`bower`
- 使用CDN[//unpkg.com/wangeditor/release/wangEditor.min.js](https://unpkg.com/wangeditor/release/wangEditor.min.js)
## 使用
```javascript
var E = window.wangEditor
var editor = new E('#div1')
editor.create()
```
## 运行 demo
- 下载源码 `git clone git@github.com:wangfupeng1988/wangEditor.git`
- 安装或者升级最新版本 node最低`v6.x.x`
- 进入目录安装依赖包 `cd wangEditor && npm i`
- 安装包完成之后windows 用户运行`npm run win-example`Mac 用户运行`npm run example`
- 打开浏览器访问[localhost:3000/index.html](http://localhost:3000/index.html)
- 用于 Reactvue 或者 angular 可查阅[文档](http://www.kancloud.cn/wangfupeng/wangeditor3/332599)中[其他](https://www.kancloud.cn/wangfupeng/wangeditor3/335783)章节中的相关介绍
## 交流
### QQ
以下 QQ 群欢迎加入交流问题可能有些群已经满员
- 164999061
- 281268320
### 提问
注意作者只受理以下几种提问方式其他方式直接忽略
- 直接在 [github issues](https://github.com/wangfupeng1988/wangEditor/issues) 提交问题
- [知乎](https://www.zhihu.com/)提问,并邀请[作者](https://www.zhihu.com/people/wang-fu-peng-54/activities)来回答
- [segmentfault](https://segmentfault.com)提问,并邀请[作者](https://segmentfault.com/u/wangfupeng1988)来回答
每次升级版本修复的问题记录在[这里](./ISSUE.md)
## 关于作者
- 关注作者的博客 - [深入理解javascript原型和闭包系列](http://www.cnblogs.com/wangfupeng1988/p/4001284.html)》《[深入理解javascript异步系列](https://github.com/wangfupeng1988/js-async-tutorial)》《[CSS知多少](http://www.cnblogs.com/wangfupeng1988/p/4325007.html)》
- 学习作者的教程 - [前端JS基础面试题](http://coding.imooc.com/class/115.html)》《[React.js模拟大众点评webapp](http://coding.imooc.com/class/99.html)》《[zepto设计与源码分析](http://www.imooc.com/learn/745)》《[用grunt搭建自动化的web前端开发环境](http://study.163.com/course/courseMain.htm?courseId=1103003)》《[json2.js源码解读](http://study.163.com/course/courseMain.htm?courseId=691008)》
如果你感觉有收获欢迎给我打赏 以激励我更多输出优质开源内容
![图片](https://camo.githubusercontent.com/e1558b631931e0a1606c769a61f48770cc0ccb56/687474703a2f2f696d61676573323031352e636e626c6f67732e636f6d2f626c6f672f3133383031322f3230313730322f3133383031322d32303137303232383131323233373739382d313530373139363634332e706e67)

View File

@ -0,0 +1,20 @@
{
"name": "wangEditor",
"description": "wangEditor - 基于javascript和css开发的 web 富文本编辑器, 轻量、简洁、易用、开源免费",
"main": "release/wangEditor.js",
"authors": [
"wangfupeng <wangfupeng1988@163.com>"
],
"license": "MIT",
"keywords": [
"wangEditor",
"web 富文本编辑器"
],
"homepage": "https://github.com/wangfupeng1988/wangEditor",
"moduleType": [
"amd",
"cmd",
"node"
],
"private": true
}

View File

@ -0,0 +1,25 @@
面向开发者的文档
框架介绍
- 下载和运行
- 目录结构介绍
- `example`目录
- `src`目录`js`目录`less`目录
- `package.json`
- `gulpfile.js`
如何提交 PR
上线
- 修改`package.json`版本
- 提交到github并创建tag
- 提交到 npm
- 更新 .md 文档
- 文档同步到 kancloud
-

View File

@ -0,0 +1,41 @@
# 简单的 demo
## 下载
- 点击 [https://github.com/wangfupeng1988/wangEditor/releases](https://github.com/wangfupeng1988/wangEditor/releases) 下载最新版。进入`release`文件夹下找到`wangEditor.js`或者`wangEditor.min.js`即可
- 使用CDN[//unpkg.com/wangeditor/release/wangEditor.min.js](https://unpkg.com/wangeditor/release/wangEditor.min.js)
- 使用`bower`下载`bower install wangEditor` 前提保证电脑已安装了`bower`
*PS支持`npm`安装请参见后面的章节*
## 制作 demo
编辑器效果如下
![图片](https://camo.githubusercontent.com/f3d072718d8fcbbacf8cc80465a34cceffcf5b4a/687474703a2f2f696d61676573323031352e636e626c6f67732e636f6d2f626c6f672f3133383031322f3230313730352f3133383031322d32303137303533303230323930353633332d313834303135383938312e706e67)
代码示例如下**注意以下代码中无需引用任何 CSS 文件**
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>wangEditor demo</title>
</head>
<body>
<div id="editor">
<p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
</div>
<!-- 注意 只需要引用 JS无需引用任何 CSS -->
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#editor')
// 或者 var editor = new E( document.getElementById('#editor') )
editor.create()
</script>
</body>
</html>
```

View File

@ -0,0 +1,49 @@
# 使用模块定义
wangEditor 除了直接使用`<script>`引用之外还支持`AMD``CommonJS`的引用方式
## AMD
`require.js`为例演示
先创建`main.js`代码为
```javascript
require(['/wangEditor.min.js'], function (E) {
var editor = new E('#editor')
editor.create()
})
```
然后创建页面代码为
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>wangEditor demo</title>
</head>
<body>
<div id="editor">
<p>欢迎使用 wangEditor 富文本编辑器</p>
</div>
<script data-main="./main.js" src="//cdn.bootcss.com/require.js/2.3.3/require.js"></script>
</body>
</html>
```
## CommonJS
可以使用`npm install wangeditor`安装注意这里`wangeditor`全是**小写字母**
```javascript
// 引用
var E = require('wangeditor') // 使用 npm 安装
var E = require('/wangEditor.min.js') // 使用下载的源码
// 创建编辑器
var editor = new E('#editor')
editor.create()
```

View File

@ -0,0 +1,48 @@
# 菜单和编辑区域分离
如果你想要像 知乎专栏简书石墨网易云笔记 这些编辑页面一样将编辑区域和菜单分离也可以实现
这样菜单和编辑器区域就是使用者可自己控制的元素可自定义样式例如将菜单`fixed`编辑器区域高度自动增加等
## 代码示例
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>wangEditor 菜单和编辑器区域分离</title>
<style type="text/css">
.toolbar {
border: 1px solid #ccc;
}
.text {
border: 1px solid #ccc;
height: 400px;
}
</style>
</head>
<body>
<div id="div1" class="toolbar">
</div>
<div style="padding: 5px 0; color: #ccc">中间隔离带</div>
<div id="div2" class="text"> <!--可使用 min-height 实现编辑区域自动增加高度-->
<p>请输入内容</p>
</div>
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor1 = new E('#div1', '#div2') // 两个参数也可以传入 elem 对象class 选择器
editor1.create()
</script>
</body>
</html>
```
## 显示效果
从上面代码可以看出,菜单和编辑区域其实就是两个单独的`<div>`,位置、尺寸都可以随便定义。
![](http://images2015.cnblogs.com/blog/138012/201705/138012-20170531224756289-7442240.png)

View File

@ -0,0 +1,50 @@
# 同一个页面创建多个编辑器
wangEditor 支持一个页面创建多个编辑器
## 代码示例
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>wangEditor 一个页面多个编辑器</title>
<style type="text/css">
.toolbar {
background-color: #f1f1f1;
border: 1px solid #ccc;
}
.text {
border: 1px solid #ccc;
height: 200px;
}
</style>
</head>
<body>
<div id="div1" class="toolbar">
</div>
<div style="padding: 5px 0; color: #ccc">中间隔离带</div>
<div id="div2" class="text">
<p>第一个 demo菜单和编辑器区域分开</p>
</div>
<div id="div3">
<p>第二个 demo常规</p>
</div>
<!-- 引用js -->
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor1 = new E('#div1', '#div2')
editor1.create()
var editor2 = new E('#div3')
editor2.create()
</script>
</body>
</html>
```

View File

@ -0,0 +1,46 @@
# 设置内容
以下方式中如果条件允许尽量使用第一种方式效率最高
## html 初始化内容
直接将内容写到要创建编辑器的`<div>`标签中
```html
<div id="div1">
<p>初始化的内容</p>
<p>初始化的内容</p>
</div>
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#div1')
editor.create()
</script>
```
## js 设置内容
创建编辑器之后使用`editor.txt.html(...)`设置编辑器内容
```html
<div id="div1">
</div>
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#div1')
editor.create()
editor.txt.html('<p> JS 设置的内容</p>')
</script>
```
## 追加内容
创建编辑器之后可使用`editor.txt.append('<p>追加的内容</p>')`继续追加内容
## 清空内容
可使用`editor.txt.clear()`清空编辑器内容

View File

@ -0,0 +1,80 @@
# 读取内容
可以`html``text`的方式读取编辑器的内容
```html
<div id="div1">
<p>欢迎使用 wangEditor 编辑器</p>
</div>
<button id="btn1">获取html</button>
<button id="btn2">获取text</button>
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#div1')
editor.create()
document.getElementById('btn1').addEventListener('click', function () {
// 读取 html
alert(editor.txt.html())
}, false)
document.getElementById('btn2').addEventListener('click', function () {
// 读取 text
alert(editor.txt.text())
}, false)
</script>
```
需要注意的是**从编辑器中获取的 html 代码是不包含任何样式的纯 html**如果显示的时候需要对其中的`<table>` `<code>` `<blockquote>`等标签进行自定义样式这样既可实现多皮肤功能下面提供了编辑器中使用的样式供参考
```css
/* table 样式 */
table {
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
}
table td,
table th {
border-bottom: 1px solid #ccc;
border-right: 1px solid #ccc;
padding: 3px 5px;
}
table th {
border-bottom: 2px solid #ccc;
text-align: center;
}
/* blockquote 样式 */
blockquote {
display: block;
border-left: 8px solid #d0e5f2;
padding: 5px 10px;
margin: 10px 0;
line-height: 1.4;
font-size: 100%;
background-color: #f1f1f1;
}
/* code 样式 */
code {
display: inline-block;
*display: inline;
*zoom: 1;
background-color: #f1f1f1;
border-radius: 3px;
padding: 3px 5px;
margin: 0 3px;
}
pre code {
display: block;
}
/* ul ol 样式 */
ul, ol {
margin: 10px 0 10px 20px;
}
```

View File

@ -0,0 +1,25 @@
# 使用 textarea
wangEditor `v3`版本开始不支持 textarea 但是可以通过`onchange`来实现 textarea 中提交富文本内容
```html
<div id="div1">
<p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
</div>
<textarea id="text1" style="width:100%; height:200px;"></textarea>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="../wangEditor.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#div1')
var $text1 = $('#text1')
editor.customConfig.onchange = function (html) {
// 监控变化,同步更新到 textarea
$text1.val(html)
}
editor.create()
// 初始化 textarea 的值
$text1.val(editor.txt.html())
</script>
```

View File

@ -0,0 +1,82 @@
# 获取 JSON 格式的内容
可以通过`editor.txt.getJSON`获取 JSON 格式的编辑器的内容`v3.0.14`开始支持示例如下
```html
<div id="div1">
<p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
<img src="https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top_ca79a146.png" style="max-width:100%;"/>
</div>
<button id="btn1">getJSON</button>
<script type="text/javascript" src="/wangEditor.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#div1')
editor.create()
document.getElementById('btn1').addEventListener('click', function () {
var json = editor.txt.getJSON() // 获取 JSON 格式的内容
var jsonStr = JSON.stringify(json)
console.log(json)
console.log(jsonStr)
})
</script>
```
-----
如果编辑器区域的 html 内容是如下
```html
<p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
<img src="https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top_ca79a146.png" style="max-width:100%;"/>
```
那么获取的 JSON 格式就如下
```json
[
{
"tag": "p",
"attrs": [],
"children": [
"欢迎使用 ",
{
"tag": "b",
"attrs": [],
"children": [
"wangEditor"
]
},
" 富文本编辑器"
]
},
{
"tag": "img",
"attrs": [
{
"name": "src",
"value": "https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top_ca79a146.png"
},
{
"name": "style",
"value": "max-width:100%;"
}
],
"children": []
},
{
"tag": "p",
"attrs": [],
"children": [
{
"tag": "br",
"attrs": [],
"children": []
}
]
}
]
```

View File

@ -0,0 +1,52 @@
# 自定义菜单
编辑器创建之前可使用`editor.customConfig.menus`定义显示哪些菜单和菜单的顺序**注意v3 版本的菜单不支持换行折叠了因为换行之后菜单栏是在太难看如果菜单栏宽度不够建议精简菜单项**
## 代码示例
```html
<div id="div1">
<p>欢迎使用 wangEditor 富文本编辑器</p>
</div>
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#div1')
// 自定义菜单配置
editor.customConfig.menus = [
'head',
'bold',
'italic',
'underline'
]
editor.create()
</script>
```
## 默认菜单
编辑默认的菜单配置如下
```javascript
[
'head', // 标题
'bold', // 粗体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
'foreColor', // 文字颜色
'backColor', // 背景颜色
'link', // 插入链接
'list', // 列表
'justify', // 对齐方式
'quote', // 引用
'emoticon', // 表情
'image', // 插入图片
'table', // 表格
'video', // 插入视频
'code', // 插入代码
'undo', // 撤销
'redo' // 重复
]
```

View File

@ -0,0 +1,21 @@
# 定义 debug 模式
可通过`editor.customConfig.debug = true`配置`debug`模式`debug`模式下 JS 错误会以`throw Error`方式提示出来默认值为`false`即不会抛出异常
但是在实际开发中不建议直接定义为`true`或者`false`可通过 url 参数进行干预示例如下
```html
<div id="div1">
<p>欢迎使用 wangEditor 富文本编辑器</p>
</div>
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#div1')
// 通过 url 参数配置 debug 模式。url 中带有 wangeditor_debug_mode=1 才会开启 debug 模式
editor.customConfig.debug = location.href.indexOf('wangeditor_debug_mode=1') > 0
editor.create()
</script>
```

View File

@ -0,0 +1,40 @@
# 配置 onchange 函数
配置`onchange`函数之后用户操作鼠标点击键盘打字等导致的内容变化之后会自动触发`onchange`函数执行
但是**用户自己使用 JS 修改了`div1``innerHTML`不会自动触发`onchange`函数**此时你可以通过执行`editor.change()`来手动触发`onchange`函数的执行
```html
<div id="div1">
<p>欢迎使用 wangEditor 富文本编辑器</p>
</div>
<p>手动触发 onchange 函数执行</p>
<button id="btn1">change</button>
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#div1')
editor.customConfig.onchange = function (html) {
// html 即变化之后的内容
console.log(html)
}
editor.create()
document.getElementById('btn1').addEventListener('click', function () {
// 如果未配置 editor.customConfig.onchange则 editor.change 为 undefined
editor.change && editor.change()
})
</script>
```
-----
另外如果需要修改 onchange 触发的延迟时间onchange 会在用户无任何操作的 xxx 毫秒之后被触发可通过如下配置
```js
// 自定义 onchange 触发的延迟时间,默认为 200 ms
editor.customConfig.onchangeTimeout = 1000 // 单位 ms
```

View File

@ -0,0 +1,19 @@
# 配置编辑区域的 z-index
编辑区域的`z-index`默认为`10000`可自定义修改代码配置如下需改之后编辑区域和菜单的`z-index`会同时生效
```html
<div id="div1">
<p>欢迎使用 wangEditor 富文本编辑器</p>
</div>
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#div1')
editor.customConfig.zIndex = 100
editor.create()
</script>
```

View File

@ -0,0 +1,30 @@
# 多语言
可以通过`lang`配置项配置多语言其实就是通过该配置项中的配置将编辑器显示的文字替换成你需要的文字
```html
<div id="div1">
<p>欢迎使用 wangEditor 富文本编辑器</p>
</div>
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#div1')
editor.customConfig.lang = {
'设置标题': 'title',
'正文': 'p',
'链接文字': 'link text',
'链接': 'link',
'上传图片': 'upload image',
'上传': 'upload',
'创建': 'init'
// 还可自定添加更多
}
editor.create()
</script>
```
**注意以上代码中的`链接文字`要写在`链接`前面`上传图片`要写在`上传`前面因为前者包含后者如果不这样做可能会出现替换不全的问题切记切记**

View File

@ -0,0 +1,33 @@
# 粘贴文本
**注意以下配置暂时对 IE 无效IE 暂时使用系统自带的粘贴功能没有样式过滤**
## 关闭粘贴样式的过滤
当从其他网页复制文本内容粘贴到编辑器中编辑器会默认过滤掉复制文本中自带的样式目的是让粘贴后的文本变得更加简洁和轻量用户可通过`editor.customConfig.pasteFilterStyle = false`手动关闭掉粘贴样式的过滤
## 自定义处理粘贴的文本内容
使用者可通过`editor.customConfig.pasteTextHandle`对粘贴的文本内容进行自定义的过滤处理等操作然后返回处理之后的文本内容编辑器最终会粘贴用户处理之后并且返回的的内容
## 示例代码
```html
<div id="div1">
<p>欢迎使用 wangEditor 富文本编辑器</p>
</div>
<script type="text/javascript" src="/wangEditor.min.js"></script>
<script type="text/javascript">
var E = window.wangEditor
var editor = new E('#div1')
// 关闭粘贴样式的过滤
editor.customConfig.pasteFilterStyle = false
// 自定义处理粘贴的文本内容
editor.customConfig.pasteTextHandle = function (content) {
// content 即粘贴过来的内容html 或 纯文本),可进行自定义处理然后返回
return content + '<p>在粘贴内容后面追加一行</p>'
}
editor.create()
</script>
```

View File

@ -0,0 +1,12 @@
# 插入网络图片的回调
插入网络图片时可通过如下配置获取到图片的信息`v3.0.10`开始支持
```js
var E = window.wangEditor
var editor = new E('#div1')
editor.customConfig.linkImgCallback = function (url) {
console.log(url) // url 即插入图片的地址
}
editor.create()
```

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