mirror of
https://github.com/201206030/novel-plus.git
synced 2025-04-26 09:20:50 +00:00
chore: 模版/配置/SQL/文档更新
This commit is contained in:
parent
84a06a7037
commit
8781cc54d4
@ -42,6 +42,7 @@ novel-plus -- 父工程
|
|||||||
| 技术 | 说明
|
| 技术 | 说明
|
||||||
|---------------------| ---------------------------
|
|---------------------| ---------------------------
|
||||||
| Spring Boot | Spring 应用快速开发脚手架
|
| Spring Boot | Spring 应用快速开发脚手架
|
||||||
|
| Spring AI | Spring 官方 AI 框架
|
||||||
| MyBatis | 持久层 ORM 框架
|
| MyBatis | 持久层 ORM 框架
|
||||||
| MyBatis Dynamic SQL | Mybatis 动态 sql
|
| MyBatis Dynamic SQL | Mybatis 动态 sql
|
||||||
| PageHelper | MyBatis 分页插件
|
| PageHelper | MyBatis 分页插件
|
||||||
|
44
doc/sql/20250317.sql
Normal file
44
doc/sql/20250317.sql
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
INSERT INTO crawl_source (source_name, crawl_rule, source_status, create_time, update_time)
|
||||||
|
VALUES ('香书小说网', '{
|
||||||
|
"bookListUrl": "http://www.xbiqugu.la/fenlei/{catId}_{page}.html",
|
||||||
|
"catIdRule": {
|
||||||
|
"catId1": "1",
|
||||||
|
"catId2": "2",
|
||||||
|
"catId3": "3",
|
||||||
|
"catId4": "4",
|
||||||
|
"catId5": "6",
|
||||||
|
"catId6": "5"
|
||||||
|
},
|
||||||
|
"bookIdPatten": "<a\\\\s+href=\\"http://www.xbiqugu.la/(\\\\d+/\\\\d+)/\\"\\\\s+target=\\"_blank\\">",
|
||||||
|
"pagePatten": "<em\\\\s+id=\\"pagestats\\">(\\\\d+)/\\\\d+</em>",
|
||||||
|
"totalPagePatten": "<em\\\\s+id=\\"pagestats\\">\\\\d+/(\\\\d+)</em>",
|
||||||
|
"bookDetailUrl": "http://www.xbiqugu.la/{bookId}/",
|
||||||
|
"bookNamePatten": "<h1>([^/]+)</h1>",
|
||||||
|
"authorNamePatten": "者:([^/]+)</p>",
|
||||||
|
"picUrlPatten": "src=\\"(http://www.xbiqugu.la/files/article/image/\\\\d+/\\\\d+/\\\\d+s\\\\.jpg)\\"",
|
||||||
|
"bookStatusRule": {},
|
||||||
|
"descStart": "<div id=\\"intro\\">",
|
||||||
|
"descEnd": "</div>",
|
||||||
|
"upadateTimePatten": "<p>最后更新:(\\\\d+-\\\\d+-\\\\d+\\\\s\\\\d+:\\\\d+:\\\\d+)</p>",
|
||||||
|
"upadateTimeFormatPatten": "yyyy-MM-dd HH:mm:ss",
|
||||||
|
"bookIndexUrl": "http://www.xbiqugu.la/{bookId}/",
|
||||||
|
"indexIdPatten": "<a\\\\s+href=''/\\\\d+/\\\\d+/(\\\\d+)\\\\.html''\\\\s+>[^/]+</a>",
|
||||||
|
"indexNamePatten": "<a\\\\s+href=''/\\\\d+/\\\\d+/\\\\d+\\\\.html''\\\\s+>([^/]+)</a>",
|
||||||
|
"bookContentUrl": "http://www.xbiqugu.la/{bookId}/{indexId}.html",
|
||||||
|
"contentStart": "<div id=\\"content\\">",
|
||||||
|
"contentEnd": "<p>",
|
||||||
|
"filterContent":"<div\\\\s+id=\\"content_tip\\">\\\\s*<b>([^/]+)</b>\\\\s*</div>"
|
||||||
|
}', 0, '2024-06-01 10:11:39', '2024-06-01 10:11:39');
|
||||||
|
|
||||||
|
|
||||||
|
update crawl_source
|
||||||
|
set crawl_rule = replace(crawl_rule, 'ibiquzw.org', 'biquxs.info')
|
||||||
|
where id = 16;
|
||||||
|
|
||||||
|
delete
|
||||||
|
from sys_menu
|
||||||
|
where menu_id = 104;
|
||||||
|
|
||||||
|
delete
|
||||||
|
from sys_menu
|
||||||
|
where menu_id = 57;
|
@ -49,3 +49,13 @@ http:
|
|||||||
# 代理密码
|
# 代理密码
|
||||||
password: swiftproxy_p
|
password: swiftproxy_p
|
||||||
|
|
||||||
|
|
||||||
|
--- #--------------------- Spring AI 配置----------------------
|
||||||
|
spring:
|
||||||
|
ai:
|
||||||
|
openai:
|
||||||
|
api-key: sk-nnhjmxuljagcuubbovjztbhkiawqaabzziazeurppinxtgva
|
||||||
|
base-url: https://api.siliconflow.cn
|
||||||
|
chat:
|
||||||
|
options:
|
||||||
|
model: deepseek-ai/DeepSeek-R1-Distill-Llama-8B
|
@ -8,6 +8,79 @@
|
|||||||
<title>作家管理系统-小说精品屋</title>
|
<title>作家管理系统-小说精品屋</title>
|
||||||
<link rel="stylesheet" href="/css/base.css?v=1"/>
|
<link rel="stylesheet" href="/css/base.css?v=1"/>
|
||||||
<link rel="stylesheet" href="/css/user.css"/>
|
<link rel="stylesheet" href="/css/user.css"/>
|
||||||
|
<style>
|
||||||
|
/* 编辑器容器样式 */
|
||||||
|
.editor-container {
|
||||||
|
margin: 10px 0px;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 文本域样式 */
|
||||||
|
#bookContent {
|
||||||
|
width: 93%;
|
||||||
|
height: 400px;
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #e6e6e6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 工具栏样式 */
|
||||||
|
.ai-toolbar {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px; /* 按钮间距 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 自定义链接按钮样式 */
|
||||||
|
.ai-link {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
background: linear-gradient(135deg, #6a11cb, #2575fc);
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 链接按钮悬停效果 */
|
||||||
|
.ai-link:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 链接按钮点击效果 */
|
||||||
|
.ai-link:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 不同按钮的颜色 */
|
||||||
|
.ai-link.expand {
|
||||||
|
background: linear-gradient(135deg, #ff9a9e, #fad0c4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-link.condense {
|
||||||
|
background: linear-gradient(135deg, #a18cd1, #fbc2eb);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-link.continue {
|
||||||
|
background: linear-gradient(135deg, #f6d365, #fda085);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-link.polish {
|
||||||
|
background: linear-gradient(135deg, #ff6f61, #ffcc00);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
</head>
|
</head>
|
||||||
<body class="">
|
<body class="">
|
||||||
@ -46,18 +119,29 @@
|
|||||||
<ul class="log_list">
|
<ul class="log_list">
|
||||||
<li><span id="LabErr"></span></li>
|
<li><span id="LabErr"></span></li>
|
||||||
<b>章节名:</b>
|
<b>章节名:</b>
|
||||||
<li><input type="text" id="bookIndex" name="bookIndex" class="s_input" ></li>
|
<li><input type="text" id="bookIndex" name="bookIndex" class="s_input"></li>
|
||||||
<b>章节内容:</b><li id="contentLi">
|
<b>章节内容:</b>
|
||||||
<textarea name="bookContent" rows="30" cols="80" id="bookContent"
|
<li id="contentLi" style="width: 500px">
|
||||||
class="textarea"></textarea></li><br/>
|
<div class="editor-container">
|
||||||
|
<div class="ai-toolbar">
|
||||||
|
<a class="ai-link expand" data-type="expand">AI扩写</a>
|
||||||
|
<a class="ai-link condense" data-type="condense">AI缩写</a>
|
||||||
|
<a class="ai-link continue" data-type="continue">AI续写</a>
|
||||||
|
<a class="ai-link polish" data-type="polish">AI润色</a>
|
||||||
|
</div>
|
||||||
|
<textarea id="bookContent" name="bookContent"
|
||||||
|
placeholder="请输入文本内容..."></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
<b>是否收费:</b>
|
<b>是否收费:</b>
|
||||||
<li><input type="radio" name="isVip" value="0" checked >免费
|
<li><input type="radio" name="isVip" value="0" checked>免费
|
||||||
<input type="radio" name="isVip" value="1" >收费</li>
|
<input type="radio" name="isVip" value="1">收费
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
<li style="margin-top: 10px"><input type="button" onclick="addBookContent()" name="btnRegister" value="提交"
|
<li style="margin-top: 10px"><input type="button" onclick="addBookContent()"
|
||||||
id="btnRegister" class="btn_red">
|
name="btnRegister" value="提交"
|
||||||
|
id="btnRegister" class="btn_red">
|
||||||
|
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@ -113,9 +197,10 @@
|
|||||||
|
|
||||||
|
|
||||||
var lock = false;
|
var lock = false;
|
||||||
|
|
||||||
function addBookContent() {
|
function addBookContent() {
|
||||||
|
|
||||||
if(lock){
|
if (lock) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lock = true;
|
lock = true;
|
||||||
@ -125,14 +210,14 @@
|
|||||||
|
|
||||||
|
|
||||||
var indexName = $("#bookIndex").val();
|
var indexName = $("#bookIndex").val();
|
||||||
if(!indexName){
|
if (!indexName) {
|
||||||
$("#LabErr").html("章节名不能为空!");
|
$("#LabErr").html("章节名不能为空!");
|
||||||
lock = false;
|
lock = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var content = $("#bookContent").val();
|
var content = $("#bookContent").val();
|
||||||
if(!content){
|
if (!content) {
|
||||||
$("#LabErr").html("章节内容不能为空!");
|
$("#LabErr").html("章节内容不能为空!");
|
||||||
lock = false;
|
lock = false;
|
||||||
return;
|
return;
|
||||||
@ -142,17 +227,15 @@
|
|||||||
var isVip = $("input:checked[name=isVip]").val();
|
var isVip = $("input:checked[name=isVip]").val();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/author/addBookContent",
|
url: "/author/addBookContent",
|
||||||
data: {'bookId':bookId,'indexName':indexName,'content':content,'isVip':isVip},
|
data: {'bookId': bookId, 'indexName': indexName, 'content': content, 'isVip': isVip},
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
|
|
||||||
window.location.href = '/author/index_list.html?bookId='+bookId;
|
window.location.href = '/author/index_list.html?bookId=' + bookId;
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -169,5 +252,110 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 打字机效果函数
|
||||||
|
function typeWriter(textarea, text, speed = 50) {
|
||||||
|
let i = 0;
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
if (i < text.length) {
|
||||||
|
textarea.val(textarea.val() + text.charAt(i));
|
||||||
|
i++;
|
||||||
|
// 滚动到底部
|
||||||
|
textarea.scrollTop(textarea[0].scrollHeight);
|
||||||
|
} else {
|
||||||
|
clearInterval(timer);
|
||||||
|
}
|
||||||
|
}, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.ai-toolbar .ai-link').click(function(e){
|
||||||
|
e.preventDefault(); // 阻止默认链接行为
|
||||||
|
const type = $(this).data('type');
|
||||||
|
const textarea = $('#bookContent');
|
||||||
|
const selectedText = textarea.val().substring(textarea[0].selectionStart, textarea[0].selectionEnd);
|
||||||
|
|
||||||
|
// 检查是否选中文本
|
||||||
|
if (!selectedText) {
|
||||||
|
layer.msg('请先选中要处理的文本');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const loading = layer.load(1, {shade: 0.3});
|
||||||
|
|
||||||
|
// 参数配置
|
||||||
|
let params = {text: selectedText};
|
||||||
|
if(type === 'expand' || type === 'condense'){
|
||||||
|
layer.prompt({
|
||||||
|
title: '请输入比例',
|
||||||
|
value: 2,
|
||||||
|
btn: ['确定', '取消'],
|
||||||
|
btn2: function(){
|
||||||
|
layer.close(loading);
|
||||||
|
},
|
||||||
|
cancel: function(){
|
||||||
|
layer.close(loading);
|
||||||
|
}
|
||||||
|
}, function(value, index){
|
||||||
|
if(isNaN(Number(value)) || isNaN(parseFloat(value))){
|
||||||
|
layer.msg('请输入正确的比例');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(type === 'expand' && value <= 1){
|
||||||
|
layer.msg('请输入正确的比例');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(type === 'condense' && (value <=0 || value >= 1)){
|
||||||
|
layer.msg('请输入正确的比例');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
params.ratio = parseFloat(value) * 100;
|
||||||
|
layer.close(index);
|
||||||
|
sendRequest(type, params, loading, textarea);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}else if(type === 'continue'){
|
||||||
|
layer.prompt({
|
||||||
|
title: '请输入续写长度(字数)',
|
||||||
|
value: 200,
|
||||||
|
btn: ['确定', '取消'],
|
||||||
|
btn2: function(){
|
||||||
|
layer.close(loading);
|
||||||
|
},
|
||||||
|
cancel: function(){
|
||||||
|
layer.close(loading);
|
||||||
|
}
|
||||||
|
}, function(value, index){
|
||||||
|
if(!Number.isInteger(Number(value)) || value <= 0){
|
||||||
|
layer.msg('请输入正确的长度');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
params.length = parseInt(value);
|
||||||
|
layer.close(index);
|
||||||
|
sendRequest(type, params, loading, textarea);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendRequest(type, params, loading, textarea);
|
||||||
|
});
|
||||||
|
|
||||||
|
function sendRequest(type, params, loading, textarea){
|
||||||
|
$.ajax({
|
||||||
|
url: '/author/ai/' + type,
|
||||||
|
type: 'POST',
|
||||||
|
data: params,
|
||||||
|
success: function(res){
|
||||||
|
layer.close(loading);
|
||||||
|
// 将生成的内容追加到文本末尾
|
||||||
|
const newText = "\n\n" + res.data; // 添加换行符分隔
|
||||||
|
typeWriter(textarea, newText); // 使用打字机效果
|
||||||
|
},
|
||||||
|
error: function(){
|
||||||
|
layer.msg('请求失败,请稍后重试');
|
||||||
|
layer.close(loading);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user