Compare commits

...

7 Commits

Author SHA1 Message Date
68a1ece57c update 2020-11-27 21:14:45 +08:00
77645da2bd update readme 2020-11-23 08:48:11 +08:00
36376aa623 update readme 2020-11-23 08:44:27 +08:00
9e98665cca v2.9.0发布 2020-11-23 08:29:50 +08:00
9a19a33406 章节字数计算规则优化 2020-11-23 08:21:58 +08:00
a4f7042b87 更新sql 2020-11-22 18:06:01 +08:00
31aa3192fd 小说章节定价规则自定义 2020-11-22 17:15:20 +08:00
19 changed files with 240 additions and 72 deletions

View File

@ -44,6 +44,7 @@ GitHub仓库地址 https://github.com/201206030/novel-cloud
- [x] 阅读主题模块 - [x] 阅读主题模块
- [x] 作家专区 - [x] 作家专区
- [x] 充值 - [x] 充值
- [x] 订阅
- [x] 后台管理系统 - [x] 后台管理系统
- [x] 爬虫管理系统 - [x] 爬虫管理系统
@ -219,6 +220,11 @@ docker安装教程[点击前往](https://my.oschina.net/java2nb/blog/4271989)
![mini-code](https://s1.ax1x.com/2020/10/31/BUQJwq.png) ![mini-code](https://s1.ax1x.com/2020/10/31/BUQJwq.png)
### 免责声明
本项目提供的爬虫工具仅用于采集项目初期的测试数据请勿用于商业盈利
用户使用本系统从事任何违法违规的事情一切后果由用户自行承担作者不承担任何责任
#### 备注 #### 备注
精品小说屋所有相关项目均已在开源中国公开感兴趣的可进入[开源中国](https://www.oschina.net/p/fiction_house)按关键字`精品小说屋`搜索。 精品小说屋所有相关项目均已在开源中国公开感兴趣的可进入[开源中国](https://www.oschina.net/p/fiction_house)按关键字`精品小说屋`搜索。

View File

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

View File

@ -3,6 +3,10 @@ package com.java2nb.novel.core.utils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.Arrays; import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.util.regex.Pattern.*;
/** /**
* @author xiongxiaoyang * @author xiongxiaoyang
@ -70,4 +74,83 @@ public class StringUtil {
return result.toString(); return result.toString();
} }
/**
* 获取字符串有效汉字
* */
public static String getChineseValidWord(String origStr){
//可以替换大部分空白字符, 不限于空格 . 说明:\s 可以匹配空格、制表符、换页符等空白字符的其中任意一个
origStr = origStr.replaceAll("\\s*","");
/* //完全清除标点
origStr = origStr.replaceAll("\\pP","");*/
//清除所有符号,只留下字母 数字 汉字 共3类.
origStr = origStr.replaceAll("[\\pP\\p{Punct}]","");
//去除字母和数字
origStr = origStr.replaceAll("[A-Za-z0-9]*","");
return origStr;
}
/**
* 获取字符串英文单词数量
* */
public static int getEnglishWordCount(String origStr){
Pattern pattern = compile("\\b\\w+\\b");
Matcher matcher = pattern.matcher(origStr);
int count = 0;
while (matcher.find()) {
count++;
}
return count;
}
/**
* 获取字符串中文汉字数量
* */
public static int getChineseWordCount(String origStr){
Pattern pattern = compile("[\u4e00-\u9fa5]");
Matcher matcher = pattern.matcher(origStr);
int count = 0;
while (matcher.find()) {
count++;
}
return count;
}
/**
* 获取字符串有效数字数量
* */
public static int getNumberWordCount(String origStr){
Pattern pattern = compile("\\d+");
Matcher matcher = pattern.matcher(origStr);
int count = 0;
while (matcher.find()) {
count++;
}
return count;
}
/**
* 获取字符串有效字数
* */
public static int getStrValidWordCount(String origStr){
return getChineseWordCount(origStr) + getEnglishWordCount(origStr) + getNumberWordCount(origStr);
}
public static void main(String[] args) {
String str = "Welcome to China. 你好呀中国人我是1123号程序员 来给你服务23天. Hello Word";
System.out.println(getChineseWordCount(str));
System.out.println(getEnglishWordCount(str));
System.out.println(getNumberWordCount(str));
}
} }

View File

@ -22,6 +22,9 @@ public class BookIndex {
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte isVip; private Byte isVip;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Integer bookPrice;
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime; private Date createTime;
@ -88,6 +91,16 @@ public class BookIndex {
this.isVip = isVip; this.isVip = isVip;
} }
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Integer getBookPrice() {
return bookPrice;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setBookPrice(Integer bookPrice) {
this.bookPrice = bookPrice;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() { public Date getCreateTime() {
return createTime; return createTime;

View File

@ -28,6 +28,9 @@ public final class BookIndexDynamicSqlSupport {
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Byte> isVip = bookIndex.isVip; public static final SqlColumn<Byte> isVip = bookIndex.isVip;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Integer> bookPrice = bookIndex.bookPrice;
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Date> createTime = bookIndex.createTime; public static final SqlColumn<Date> createTime = bookIndex.createTime;
@ -48,6 +51,8 @@ public final class BookIndexDynamicSqlSupport {
public final SqlColumn<Byte> isVip = column("is_vip", JDBCType.TINYINT); public final SqlColumn<Byte> isVip = column("is_vip", JDBCType.TINYINT);
public final SqlColumn<Integer> bookPrice = column("book_price", JDBCType.INTEGER);
public final SqlColumn<Date> createTime = column("create_time", JDBCType.TIMESTAMP); public final SqlColumn<Date> createTime = column("create_time", JDBCType.TIMESTAMP);
public final SqlColumn<Date> updateTime = column("update_time", JDBCType.TIMESTAMP); public final SqlColumn<Date> updateTime = column("update_time", JDBCType.TIMESTAMP);

View File

@ -4,10 +4,12 @@ import static com.java2nb.novel.mapper.BookIndexDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.*; import static org.mybatis.dynamic.sql.SqlBuilder.*;
import com.java2nb.novel.entity.BookIndex; import com.java2nb.novel.entity.BookIndex;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Generated; import javax.annotation.Generated;
import org.apache.ibatis.annotations.DeleteProvider; import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider; import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@ -35,45 +37,46 @@ import org.mybatis.dynamic.sql.util.mybatis3.MyBatis3Utils;
@Mapper @Mapper
public interface BookIndexMapper { public interface BookIndexMapper {
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
BasicColumn[] selectList = BasicColumn.columnList(id, bookId, indexNum, indexName, wordCount, isVip, createTime, updateTime); BasicColumn[] selectList = BasicColumn.columnList(id, bookId, indexNum, indexName, wordCount, isVip, bookPrice, createTime, updateTime);
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select") @SelectProvider(type = SqlProviderAdapter.class, method = "select")
long count(SelectStatementProvider selectStatement); long count(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
@DeleteProvider(type=SqlProviderAdapter.class, method="delete") @DeleteProvider(type = SqlProviderAdapter.class, method = "delete")
int delete(DeleteStatementProvider deleteStatement); int delete(DeleteStatementProvider deleteStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insert") @InsertProvider(type = SqlProviderAdapter.class, method = "insert")
int insert(InsertStatementProvider<BookIndex> insertStatement); int insert(InsertStatementProvider<BookIndex> insertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insertMultiple") @InsertProvider(type = SqlProviderAdapter.class, method = "insertMultiple")
int insertMultiple(MultiRowInsertStatementProvider<BookIndex> multipleInsertStatement); int insertMultiple(MultiRowInsertStatementProvider<BookIndex> multipleInsertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select") @SelectProvider(type = SqlProviderAdapter.class, method = "select")
@ResultMap("BookIndexResult") @ResultMap("BookIndexResult")
Optional<BookIndex> selectOne(SelectStatementProvider selectStatement); Optional<BookIndex> selectOne(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select") @SelectProvider(type = SqlProviderAdapter.class, method = "select")
@Results(id="BookIndexResult", value = { @Results(id = "BookIndexResult", value = {
@Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true), @Result(column = "id", property = "id", jdbcType = JdbcType.BIGINT, id = true),
@Result(column="book_id", property="bookId", jdbcType=JdbcType.BIGINT), @Result(column = "book_id", property = "bookId", jdbcType = JdbcType.BIGINT),
@Result(column="index_num", property="indexNum", jdbcType=JdbcType.INTEGER), @Result(column = "index_num", property = "indexNum", jdbcType = JdbcType.INTEGER),
@Result(column="index_name", property="indexName", jdbcType=JdbcType.VARCHAR), @Result(column = "index_name", property = "indexName", jdbcType = JdbcType.VARCHAR),
@Result(column="word_count", property="wordCount", jdbcType=JdbcType.INTEGER), @Result(column = "word_count", property = "wordCount", jdbcType = JdbcType.INTEGER),
@Result(column="is_vip", property="isVip", jdbcType=JdbcType.TINYINT), @Result(column = "is_vip", property = "isVip", jdbcType = JdbcType.TINYINT),
@Result(column="create_time", property="createTime", jdbcType=JdbcType.TIMESTAMP), @Result(column = "book_price", property = "bookPrice", jdbcType = JdbcType.INTEGER),
@Result(column="update_time", property="updateTime", jdbcType=JdbcType.TIMESTAMP) @Result(column = "create_time", property = "createTime", jdbcType = JdbcType.TIMESTAMP),
@Result(column = "update_time", property = "updateTime", jdbcType = JdbcType.TIMESTAMP)
}) })
List<BookIndex> selectMany(SelectStatementProvider selectStatement); List<BookIndex> selectMany(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
@UpdateProvider(type=SqlProviderAdapter.class, method="update") @UpdateProvider(type = SqlProviderAdapter.class, method = "update")
int update(UpdateStatementProvider updateStatement); int update(UpdateStatementProvider updateStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
@ -88,50 +91,53 @@ public interface BookIndexMapper {
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
default int deleteByPrimaryKey(Long id_) { default int deleteByPrimaryKey(Long id_) {
return delete(c -> return delete(c ->
c.where(id, isEqualTo(id_)) c.where(id, isEqualTo(id_))
); );
} }
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insert(BookIndex record) { default int insert(BookIndex record) {
return MyBatis3Utils.insert(this::insert, record, bookIndex, c -> return MyBatis3Utils.insert(this::insert, record, bookIndex, c ->
c.map(id).toProperty("id") c.map(id).toProperty("id")
.map(bookId).toProperty("bookId") .map(bookId).toProperty("bookId")
.map(indexNum).toProperty("indexNum") .map(indexNum).toProperty("indexNum")
.map(indexName).toProperty("indexName") .map(indexName).toProperty("indexName")
.map(wordCount).toProperty("wordCount") .map(wordCount).toProperty("wordCount")
.map(isVip).toProperty("isVip") .map(isVip).toProperty("isVip")
.map(createTime).toProperty("createTime") .map(bookPrice).toProperty("bookPrice")
.map(updateTime).toProperty("updateTime") .map(createTime).toProperty("createTime")
.map(updateTime).toProperty("updateTime")
); );
} }
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertMultiple(Collection<BookIndex> records) { default int insertMultiple(Collection<BookIndex> records) {
return MyBatis3Utils.insertMultiple(this::insertMultiple, records, bookIndex, c -> return MyBatis3Utils.insertMultiple(this::insertMultiple, records, bookIndex, c ->
c.map(id).toProperty("id") c.map(id).toProperty("id")
.map(bookId).toProperty("bookId") .map(bookId).toProperty("bookId")
.map(indexNum).toProperty("indexNum") .map(indexNum).toProperty("indexNum")
.map(indexName).toProperty("indexName") .map(indexName).toProperty("indexName")
.map(wordCount).toProperty("wordCount") .map(wordCount).toProperty("wordCount")
.map(isVip).toProperty("isVip") .map(isVip).toProperty("isVip")
.map(createTime).toProperty("createTime") .map(bookPrice).toProperty("bookPrice")
.map(updateTime).toProperty("updateTime") .map(createTime).toProperty("createTime")
.map(updateTime).toProperty("updateTime")
); );
} }
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertSelective(BookIndex record) { default int insertSelective(BookIndex record) {
return MyBatis3Utils.insert(this::insert, record, bookIndex, c -> return MyBatis3Utils.insert(this::insert, record, bookIndex, c ->
c.map(id).toPropertyWhenPresent("id", record::getId) c.map(id).toPropertyWhenPresent("id", record::getId)
.map(bookId).toPropertyWhenPresent("bookId", record::getBookId) .map(bookId).toPropertyWhenPresent("bookId", record::getBookId)
.map(indexNum).toPropertyWhenPresent("indexNum", record::getIndexNum) .map(indexNum).toPropertyWhenPresent("indexNum", record::getIndexNum)
.map(indexName).toPropertyWhenPresent("indexName", record::getIndexName) .map(indexName).toPropertyWhenPresent("indexName", record::getIndexName)
.map(wordCount).toPropertyWhenPresent("wordCount", record::getWordCount) .map(wordCount).toPropertyWhenPresent("wordCount", record::getWordCount)
.map(isVip).toPropertyWhenPresent("isVip", record::getIsVip) .map(isVip).toPropertyWhenPresent("isVip", record::getIsVip)
.map(createTime).toPropertyWhenPresent("createTime", record::getCreateTime) .map(bookPrice).toPropertyWhenPresent("bookPrice", record::getBookPrice)
.map(updateTime).toPropertyWhenPresent("updateTime", record::getUpdateTime) .map(createTime).toPropertyWhenPresent("createTime", record::getCreateTime)
.map(updateTime).toPropertyWhenPresent("updateTime", record::getUpdateTime)
); );
} }
@ -153,7 +159,7 @@ public interface BookIndexMapper {
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
default Optional<BookIndex> selectByPrimaryKey(Long id_) { default Optional<BookIndex> selectByPrimaryKey(Long id_) {
return selectOne(c -> return selectOne(c ->
c.where(id, isEqualTo(id_)) c.where(id, isEqualTo(id_))
); );
} }
@ -170,6 +176,7 @@ public interface BookIndexMapper {
.set(indexName).equalTo(record::getIndexName) .set(indexName).equalTo(record::getIndexName)
.set(wordCount).equalTo(record::getWordCount) .set(wordCount).equalTo(record::getWordCount)
.set(isVip).equalTo(record::getIsVip) .set(isVip).equalTo(record::getIsVip)
.set(bookPrice).equalTo(record::getBookPrice)
.set(createTime).equalTo(record::getCreateTime) .set(createTime).equalTo(record::getCreateTime)
.set(updateTime).equalTo(record::getUpdateTime); .set(updateTime).equalTo(record::getUpdateTime);
} }
@ -182,6 +189,7 @@ public interface BookIndexMapper {
.set(indexName).equalToWhenPresent(record::getIndexName) .set(indexName).equalToWhenPresent(record::getIndexName)
.set(wordCount).equalToWhenPresent(record::getWordCount) .set(wordCount).equalToWhenPresent(record::getWordCount)
.set(isVip).equalToWhenPresent(record::getIsVip) .set(isVip).equalToWhenPresent(record::getIsVip)
.set(bookPrice).equalToWhenPresent(record::getBookPrice)
.set(createTime).equalToWhenPresent(record::getCreateTime) .set(createTime).equalToWhenPresent(record::getCreateTime)
.set(updateTime).equalToWhenPresent(record::getUpdateTime); .set(updateTime).equalToWhenPresent(record::getUpdateTime);
} }
@ -189,28 +197,30 @@ public interface BookIndexMapper {
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKey(BookIndex record) { default int updateByPrimaryKey(BookIndex record) {
return update(c -> return update(c ->
c.set(bookId).equalTo(record::getBookId) c.set(bookId).equalTo(record::getBookId)
.set(indexNum).equalTo(record::getIndexNum) .set(indexNum).equalTo(record::getIndexNum)
.set(indexName).equalTo(record::getIndexName) .set(indexName).equalTo(record::getIndexName)
.set(wordCount).equalTo(record::getWordCount) .set(wordCount).equalTo(record::getWordCount)
.set(isVip).equalTo(record::getIsVip) .set(isVip).equalTo(record::getIsVip)
.set(createTime).equalTo(record::getCreateTime) .set(bookPrice).equalTo(record::getBookPrice)
.set(updateTime).equalTo(record::getUpdateTime) .set(createTime).equalTo(record::getCreateTime)
.where(id, isEqualTo(record::getId)) .set(updateTime).equalTo(record::getUpdateTime)
.where(id, isEqualTo(record::getId))
); );
} }
@Generated("org.mybatis.generator.api.MyBatisGenerator") @Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKeySelective(BookIndex record) { default int updateByPrimaryKeySelective(BookIndex record) {
return update(c -> return update(c ->
c.set(bookId).equalToWhenPresent(record::getBookId) c.set(bookId).equalToWhenPresent(record::getBookId)
.set(indexNum).equalToWhenPresent(record::getIndexNum) .set(indexNum).equalToWhenPresent(record::getIndexNum)
.set(indexName).equalToWhenPresent(record::getIndexName) .set(indexName).equalToWhenPresent(record::getIndexName)
.set(wordCount).equalToWhenPresent(record::getWordCount) .set(wordCount).equalToWhenPresent(record::getWordCount)
.set(isVip).equalToWhenPresent(record::getIsVip) .set(isVip).equalToWhenPresent(record::getIsVip)
.set(createTime).equalToWhenPresent(record::getCreateTime) .set(bookPrice).equalToWhenPresent(record::getBookPrice)
.set(updateTime).equalToWhenPresent(record::getUpdateTime) .set(createTime).equalToWhenPresent(record::getCreateTime)
.where(id, isEqualTo(record::getId)) .set(updateTime).equalToWhenPresent(record::getUpdateTime)
.where(id, isEqualTo(record::getId))
); );
} }
} }

View File

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

View File

@ -224,6 +224,9 @@ public class CrawlServiceImpl implements CrawlService {
boolean isFindBookId = bookIdMatcher.find(); boolean isFindBookId = bookIdMatcher.find();
while (isFindBookId) { while (isFindBookId) {
try { try {
//1.阻塞过程(使用了 sleep,同步锁的 wait,socket 中的 receiver,accept 等方法时)
//捕获中断异常InterruptedException来退出线程。
//2.非阻塞过程中通过判断中断标志来退出线程。
if(Thread.currentThread().isInterrupted()){ if(Thread.currentThread().isInterrupted()){
return; return;
} }

View File

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

View File

@ -282,6 +282,7 @@ public class UserController extends BaseController {
if (userDetails == null) { if (userDetails == null) {
return ResultBean.fail(ResponseStatus.NO_LOGIN); return ResultBean.fail(ResponseStatus.NO_LOGIN);
} }
buyRecord.setBuyAmount(bookService.queryBookIndex(buyRecord.getBookIndexId()).getBookPrice());
userService.buyBookIndex(userDetails.getId(),buyRecord); userService.buyBookIndex(userDetails.getId(),buyRecord);
return ResultBean.ok(); return ResultBean.ok();
} }

View File

@ -0,0 +1,23 @@
package com.java2nb.novel.core.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
/**
* 章节费用配置
* @author cd
*/
@Component
@Data
@ConfigurationProperties(prefix = "book.price")
public class BookPriceConfig {
private BigDecimal wordCount;
private BigDecimal value;
}

View File

@ -5,6 +5,7 @@ import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.java2nb.novel.core.cache.CacheKey; import com.java2nb.novel.core.cache.CacheKey;
import com.java2nb.novel.core.cache.CacheService; import com.java2nb.novel.core.cache.CacheService;
import com.java2nb.novel.core.config.BookPriceConfig;
import com.java2nb.novel.core.enums.ResponseStatus; import com.java2nb.novel.core.enums.ResponseStatus;
import com.java2nb.novel.core.exception.BusinessException; import com.java2nb.novel.core.exception.BusinessException;
import com.java2nb.novel.core.utils.*; import com.java2nb.novel.core.utils.*;
@ -88,6 +89,8 @@ public class BookServiceImpl implements BookService {
private final FileService fileService; private final FileService fileService;
private final BookPriceConfig bookPriceConfig;
@SneakyThrows @SneakyThrows
@Override @Override
@ -256,7 +259,7 @@ public class BookServiceImpl implements BookService {
@Override @Override
public BookIndex queryBookIndex(Long bookIndexId) { public BookIndex queryBookIndex(Long bookIndexId) {
SelectStatementProvider selectStatement = select(BookIndexDynamicSqlSupport.id, BookIndexDynamicSqlSupport.bookId, BookIndexDynamicSqlSupport.indexNum, BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.wordCount, BookIndexDynamicSqlSupport.updateTime, BookIndexDynamicSqlSupport.isVip) SelectStatementProvider selectStatement = select(BookIndexDynamicSqlSupport.id, BookIndexDynamicSqlSupport.bookId, BookIndexDynamicSqlSupport.indexNum, BookIndexDynamicSqlSupport.indexName, BookIndexDynamicSqlSupport.wordCount,BookIndexDynamicSqlSupport.bookPrice, BookIndexDynamicSqlSupport.updateTime, BookIndexDynamicSqlSupport.isVip)
.from(bookIndex) .from(bookIndex)
.where(BookIndexDynamicSqlSupport.id, isEqualTo(bookIndexId)) .where(BookIndexDynamicSqlSupport.id, isEqualTo(bookIndexId))
.build() .build()
@ -544,7 +547,7 @@ public class BookServiceImpl implements BookService {
} }
Long lastIndexId = new IdWorker().nextId(); Long lastIndexId = new IdWorker().nextId();
Date currentDate = new Date(); Date currentDate = new Date();
int wordCount = content.length(); int wordCount = StringUtil.getStrValidWordCount(content);
//更新小说主表信息 //更新小说主表信息
bookMapper.update(update(BookDynamicSqlSupport.book) bookMapper.update(update(BookDynamicSqlSupport.book)
@ -560,6 +563,10 @@ public class BookServiceImpl implements BookService {
.and(BookDynamicSqlSupport.authorId, isEqualTo(authorId)) .and(BookDynamicSqlSupport.authorId, isEqualTo(authorId))
.build() .build()
.render(RenderingStrategies.MYBATIS3)); .render(RenderingStrategies.MYBATIS3));
//计算价格
int bookPrice = new BigDecimal(wordCount).divide(bookPriceConfig.getWordCount()).multiply(bookPriceConfig.getValue()).intValue();
//更新小说目录表 //更新小说目录表
int indexNum = 0; int indexNum = 0;
if (book.getLastIndexId() != null) { if (book.getLastIndexId() != null) {
@ -572,6 +579,7 @@ public class BookServiceImpl implements BookService {
lastBookIndex.setIndexNum(indexNum); lastBookIndex.setIndexNum(indexNum);
lastBookIndex.setBookId(bookId); lastBookIndex.setBookId(bookId);
lastBookIndex.setIsVip(isVip); lastBookIndex.setIsVip(isVip);
lastBookIndex.setBookPrice(bookPrice);
lastBookIndex.setCreateTime(currentDate); lastBookIndex.setCreateTime(currentDate);
lastBookIndex.setUpdateTime(currentDate); lastBookIndex.setUpdateTime(currentDate);
bookIndexMapper.insertSelective(lastBookIndex); bookIndexMapper.insertSelective(lastBookIndex);
@ -786,7 +794,11 @@ public class BookServiceImpl implements BookService {
//作者ID相同表明该小说是登录用户发布可以修改 //作者ID相同表明该小说是登录用户发布可以修改
if (book.getAuthorId().equals(authorId)) { if (book.getAuthorId().equals(authorId)) {
Date currentDate = new Date(); Date currentDate = new Date();
int wordCount = content.length(); int wordCount = StringUtil.getStrValidWordCount(content);
//计算价格
int bookPrice = new BigDecimal(wordCount).divide(bookPriceConfig.getWordCount()).multiply(bookPriceConfig.getValue()).intValue();
//更新小说目录表 //更新小说目录表
int update = bookIndexMapper.update( int update = bookIndexMapper.update(
@ -795,6 +807,8 @@ public class BookServiceImpl implements BookService {
.equalTo(indexName) .equalTo(indexName)
.set(BookIndexDynamicSqlSupport.wordCount) .set(BookIndexDynamicSqlSupport.wordCount)
.equalTo(wordCount) .equalTo(wordCount)
.set(BookIndexDynamicSqlSupport.bookPrice)
.equalTo(bookPrice)
.set(BookIndexDynamicSqlSupport.updateTime) .set(BookIndexDynamicSqlSupport.updateTime)
.equalTo(currentDate) .equalTo(currentDate)
.where(BookIndexDynamicSqlSupport.id, isEqualTo(indexId)) .where(BookIndexDynamicSqlSupport.id, isEqualTo(indexId))

View File

@ -284,20 +284,19 @@ public class UserServiceImpl implements UserService {
public void buyBookIndex(Long userId, UserBuyRecord buyRecord) { public void buyBookIndex(Long userId, UserBuyRecord buyRecord) {
//查询用户余额 //查询用户余额
long balance = userInfo(userId).getAccountBalance(); long balance = userInfo(userId).getAccountBalance();
if(balance<10){ if(balance<buyRecord.getBuyAmount()){
//余额不足 //余额不足
throw new BusinessException(ResponseStatus.USER_NO_BALANCE); throw new BusinessException(ResponseStatus.USER_NO_BALANCE);
} }
buyRecord.setUserId(userId); buyRecord.setUserId(userId);
buyRecord.setCreateTime(new Date()); buyRecord.setCreateTime(new Date());
buyRecord.setBuyAmount(10);
//生成购买记录 //生成购买记录
userBuyRecordMapper.insertSelective(buyRecord); userBuyRecordMapper.insertSelective(buyRecord);
//减少用户余额 //减少用户余额
userMapper.update(update(user) userMapper.update(update(user)
.set(UserDynamicSqlSupport.accountBalance) .set(UserDynamicSqlSupport.accountBalance)
.equalTo(balance-10) .equalTo(balance-buyRecord.getBuyAmount())
.where(id,isEqualTo(userId)) .where(id,isEqualTo(userId))
.build() .build()
.render(RenderingStrategies.MYBATIS3)); .render(RenderingStrategies.MYBATIS3));

View File

@ -57,3 +57,11 @@ author:
share-proportion: 0.7 share-proportion: 0.7
#兑换比率(人民币) #兑换比率(人民币)
exchange-proportion: 0.01 exchange-proportion: 0.01
#小说章节定价规则
book:
price:
#字数
word-count: 1000
#价值(屋币)
value: 5

View File

@ -116,7 +116,7 @@
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEdAAX4WEeZOhVYVmRzc9paH9JSy/08L4LdXX0bnEtd0tA2crFh4MPja1O/9L0Y0B5Q7Mkw2OnJlkYmOh3/iyqfPkkn99UiP/cCDJ38/2cPKg8P57VHEmkKJr8/tJbwExBtkfhGxxoA1kMIQUaw59BH5iPe"> <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEdAAX4WEeZOhVYVmRzc9paH9JSy/08L4LdXX0bnEtd0tA2crFh4MPja1O/9L0Y0B5Q7Mkw2OnJlkYmOh3/iyqfPkkn99UiP/cCDJ38/2cPKg8P57VHEmkKJr8/tJbwExBtkfhGxxoA1kMIQUaw59BH5iPe">
</div> </div>
<ul class="order_list"> <ul class="order_list">
<li>价格:<span class="red">10屋币(1元=100屋币)</span></li> <li>价格:<span class="red" th:text="${bookIndex.bookPrice}+'屋币(1元=100屋币)'"></span></li>
<li id="panelPay" class="btns"><a class="btn_red" href="javascript:buyBookIndex()" >购买</a></li> <li id="panelPay" class="btns"><a class="btn_red" href="javascript:buyBookIndex()" >购买</a></li>
</ul> </ul>

View File

@ -238,7 +238,7 @@
<div class="Readarea ReadAjax_content screen_container" <div class="Readarea ReadAjax_content screen_container"
style="color: rgb(0, 0, 0); font-size: 10px;background-color: #fff" th:if="${needBuy}"> style="color: rgb(0, 0, 0); font-size: 10px;background-color: #fff" th:if="${needBuy}">
<h5>此章为VIP章节需要订阅后才能继续阅读</h5> <h5>此章为VIP章节需要订阅后才能继续阅读</h5>
价格:<span style="color: red">10屋币(1元=100屋币)</span><br/> 价格:<span style="color: red" th:text="${bookIndex.bookPrice}+'屋币(1元=100屋币)'"></span><br/>
<a href="javascript:buyBookIndex()" type="button" class="layui-btn layui-btn-sm layui-btn-radius">购买</a> <a href="javascript:buyBookIndex()" type="button" class="layui-btn layui-btn-sm layui-btn-radius">购买</a>
</div> </div>

View File

@ -5,7 +5,7 @@
<groupId>com.java2nb</groupId> <groupId>com.java2nb</groupId>
<artifactId>novel</artifactId> <artifactId>novel</artifactId>
<version>2.8.0</version> <version>2.9.0</version>
<modules> <modules>
<module>novel-common</module> <module>novel-common</module>
<module>novel-front</module> <module>novel-front</module>

1
sql/20201122.sql Normal file
View File

@ -0,0 +1 @@
alter table book_index add column `book_price` int(3) DEFAULT 0 COMMENT '章节费用屋币' after `is_vip`;

View File

@ -1868,3 +1868,5 @@ CREATE TABLE `author_income` (
alter table book add column `yesterday_buy` int(11) DEFAULT '0' COMMENT '昨日订阅数' after comment_count; alter table book add column `yesterday_buy` int(11) DEFAULT '0' COMMENT '昨日订阅数' after comment_count;
alter table book_index add column `book_price` int(3) DEFAULT 0 COMMENT '章节费用(屋币)' after `is_vip`;