parent
8fa46e3da8
commit
b202b8870f
@ -0,0 +1 @@ |
||||
@font-face{font-family:Cascadia;src:url(../fonts/Cascadia-Code-Regular-2.97c09831.ttf)}.editor{display:flex;align-items:stretch;height:100vh}.left{width:calc(50% - 55px);min-width:500px;display:inline-block}.main{width:100%;height:calc(100vh - 64px);overflow-y:auto}textarea{min-height:20px;flex:1;outline:none;border-radius:4px;border:1px solid #ccc;font-size:14px;font-family:Cascadia,Microsoft YaHei UI,Arial,serif;line-height:20px;padding:10px 10px 10px}.fixed[data-v-ab8a8a34]{position:fixed;top:100px;left:50%;transform:translateX(-50%)}.half-circle-spinner [data-v-ab8a8a34],.half-circle-spinner[data-v-ab8a8a34]{box-sizing:border-box}.half-circle-spinner[data-v-ab8a8a34]{width:60px;height:60px;border-radius:100%;position:relative}.half-circle-spinner .circle[data-v-ab8a8a34]{content:"";position:absolute;width:100%;height:100%;border-radius:100%;border:6px solid transparent}.half-circle-spinner .circle.circle-1[data-v-ab8a8a34]{border-top-color:#ff1d5e;-webkit-animation:half-circle-spinner-animation-ab8a8a34 1s infinite;animation:half-circle-spinner-animation-ab8a8a34 1s infinite}.half-circle-spinner .circle.circle-2[data-v-ab8a8a34]{border-bottom-color:#ff1d5e;-webkit-animation:half-circle-spinner-animation-ab8a8a34 1s infinite alternate;animation:half-circle-spinner-animation-ab8a8a34 1s infinite alternate}@-webkit-keyframes half-circle-spinner-animation-ab8a8a34{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes half-circle-spinner-animation-ab8a8a34{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.warm[data-v-27eae50d]{position:fixed;top:100px;left:50%;transform:translateX(-50%);color:#eee;background-color:#ff1d5e;padding:20px;border-radius:8px;font-size:18px}button[data-v-27eae50d]{float:right;width:70px;height:35px;outline:none;border:unset;border-radius:8px;font-size:14px;transition:background-color .3s ease}.success[data-v-bef92f74],button[data-v-27eae50d]:hover{color:#333;background-color:#7fffd4}.success[data-v-bef92f74]{z-index:3;position:fixed;top:100px;left:50%;transform:translateX(-50%);padding:10px;border-radius:8px}p[data-v-bef92f74]{margin:0}.menu{display:flex;flex-direction:column;justify-content:center}button[data-v-3fa941b0]{width:100px;height:50px;margin:5px;outline:none;padding:10px;font-size:16px;border-radius:4px;box-sizing:border-box;border:1px solid #333;background-color:transparent;transition:all .3s ease;overflow:hidden}button span[data-v-3fa941b0]{display:inline-block;transform:translateY(20px);opacity:0;font-size:12px;transition:all .3s ease}button[data-v-3fa941b0]:hover{color:#fff;background-color:gray}button:hover span[data-v-3fa941b0]{transform:translateY(0);opacity:1}textarea[data-v-4301c68c]{font-size:14px}input[data-v-f11ea0d0]{outline:none;height:25px;font-size:16px}textarea[data-v-f11ea0d0]{font-size:14px}.search[data-v-7d0424af]{border:1px solid #ddd;border-radius:4px}input[data-v-7d0424af]{text-align:center;font-size:16px;height:25px;outline:none}.tool[data-v-7d0424af]{display:flex;justify-content:space-around;padding:4px 0}.tool button[data-v-7d0424af]{border-radius:4px;padding:5px;outline:none;border:none;flex:1;margin:0 2px}.tool button[data-v-7d0424af]:hover{background-color:#ddd}input[type=checkbox][data-v-7d0424af]{transform:scale(2);margin:0 15px 0}.book_item[data-v-7d0424af]{display:flex;align-items:center;margin-top:10px;padding:10px;cursor:pointer;background-color:#eee}.book_active[data-v-7d0424af]{background-color:#32cd32}.book_index[data-v-7d0424af]{width:30px;height:30px;text-align:center;line-height:30px;border-radius:50%;background-color:#ffb6c1}.book_info[data-v-7d0424af]{width:500px;display:flex;justify-content:space-between}.book_list[data-v-7d0424af]{height:calc(100vh - 125px);overflow-y:auto}a[data-v-d4554fa8]{display:block;height:25px;transition:margin-left .3s ease}a[data-v-d4554fa8]:hover{color:red;margin-left:10px}code[data-v-d4554fa8]{display:inline-block;font-size:16px;font-family:Cascadia Mono,JetBrains Mono,Microsoft YaHei UI,serif;background-color:#f3f4f4;border-radius:4px}.author[data-v-d4554fa8]{position:fixed;right:20px;bottom:20px}.author a[data-v-d4554fa8]{padding:5px 10px;border-radius:4px}.author a[data-v-d4554fa8]:hover{box-shadow:0 0 3px 3px #ccc;background-color:#ddd}.out{min-width:620px}.out,.out .box{flex:1;display:flex;flex-flow:column}a{text-decoration:none;color:#333}body,ul{margin:0;padding:0}ul{width:100%;height:40px;display:flex}ul li{display:block;text-align:center;line-height:40px;width:16%;list-style:none;cursor:pointer}ul li:hover{color:red}.active{color:#fff!important;background-color:hsla(0,0%,50%,.459);border-bottom:unset!important}ul li[data-v-de4729c0]{border-bottom:2px solid #333}a[data-v-de4729c0]{font-size:18px;color:blue}span[data-v-3974490a]{display:flex;justify-content:space-around;width:70px;white-space:nowrap}span i[data-v-3974490a]{font-style:normal}.edit_input[data-v-3974490a]{display:flex;justify-content:space-between;align-items:center;margin:10px 5px} |
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
@ -1,150 +0,0 @@ |
||||
body { |
||||
margin: 0; |
||||
} |
||||
.editor { |
||||
display: flex; |
||||
align-items: stretch; |
||||
} |
||||
.setbox, |
||||
.menu, |
||||
.outbox { |
||||
flex: 1; |
||||
display: flex; |
||||
flex-flow: column; |
||||
max-height: 100vh; |
||||
overflow-y: auto; |
||||
} |
||||
.menu { |
||||
justify-content: center; |
||||
max-width: 90px; |
||||
margin: 0 5px; |
||||
} |
||||
.menu .button { |
||||
width: 90px; |
||||
height: 30px; |
||||
min-height: 30px; |
||||
margin: 5px 0px; |
||||
cursor: pointer; |
||||
} |
||||
@keyframes stroker { |
||||
0% { |
||||
stroke-dashoffset: 0; |
||||
} |
||||
100% { |
||||
stroke-dashoffset: -240; |
||||
} |
||||
} |
||||
.button rect { |
||||
width: 100%; |
||||
height: 100%; |
||||
fill: transparent; |
||||
stroke: #666; |
||||
stroke-width: 2px; |
||||
} |
||||
.button rect.busy { |
||||
stroke: #fd1850; |
||||
stroke-dasharray: 30 90; |
||||
animation: stroker 1s linear infinite; |
||||
} |
||||
.button text { |
||||
text-anchor: middle; |
||||
dominant-baseline: middle; |
||||
} |
||||
.setbox { |
||||
min-width: 40em; |
||||
} |
||||
.rules { |
||||
overflow: auto; |
||||
} |
||||
.tabbox { |
||||
flex: 1; |
||||
display: flex; |
||||
flex-flow: column; |
||||
} |
||||
.rules > * { |
||||
display: flex; |
||||
margin: 2px 0; |
||||
} |
||||
.rules textarea { |
||||
flex: 1; |
||||
margin-left: 5px; |
||||
} |
||||
.rules > *, |
||||
.rules > * > div, |
||||
.rules textarea { |
||||
min-height: 1em; |
||||
} |
||||
textarea { |
||||
word-break: break-all; |
||||
} |
||||
.tabtitle { |
||||
display: flex; |
||||
z-index: 1; |
||||
justify-content: flex-end; |
||||
} |
||||
.tabtitle > div { |
||||
cursor: pointer; |
||||
padding: 1px 10px 0 10px; |
||||
border-bottom: 3px solid transparent; |
||||
font-weight: bold; |
||||
} |
||||
.tabtitle > .this { |
||||
color: #4f9da6; |
||||
border-bottom-color: #4ebbe4; |
||||
} |
||||
.tabbody { |
||||
flex: 1; |
||||
display: flex; |
||||
margin-top: -1px; |
||||
border: 1px solid #a9a9a9; |
||||
height: 0; |
||||
} |
||||
.tabbody > * { |
||||
flex: 1; |
||||
flex-flow: column; |
||||
display: none; |
||||
} |
||||
.tabbody > .this { |
||||
display: flex; |
||||
} |
||||
.tabbody > * > .titlebar { |
||||
display: flex; |
||||
} |
||||
.tabbody > * > .titlebar > * { |
||||
flex: 1; |
||||
margin: 1px 1px 1px 1px; |
||||
} |
||||
.tabbody > * > .context { |
||||
flex: 1; |
||||
flex-flow: column; |
||||
border: 0; |
||||
padding: 5px; |
||||
overflow-y: auto; |
||||
} |
||||
.tabbody > * > .inputbox { |
||||
border: 0; |
||||
border-bottom: #a9a9a9 solid 1px; |
||||
height: 15px; |
||||
text-align: center; |
||||
} |
||||
.link > * { |
||||
display: flex; |
||||
margin: 5px; |
||||
border-bottom: 1px solid; |
||||
text-decoration: none; |
||||
} |
||||
#RuleList > label > * { |
||||
background: #eee; |
||||
padding-left: 3px; |
||||
margin: 2px 0; |
||||
cursor: pointer; |
||||
} |
||||
#RuleList input[type="radio"] { |
||||
display: none; |
||||
} |
||||
#RuleList input[type="radio"]:checked + * { |
||||
background: #15cda8; |
||||
} |
||||
.isError { |
||||
color: #ff0000; |
||||
} |
@ -1,516 +0,0 @@ |
||||
// 简化js原生选择器
|
||||
function $(selector) { return document.querySelector(selector); } |
||||
function $$(selector) { return document.querySelectorAll(selector); } |
||||
// 读写Hash值(val未赋值时为读取)
|
||||
function hashParam(key, val) { |
||||
let hashstr = decodeURIComponent(window.location.hash); |
||||
let regKey = new RegExp(`${key}=([^&]*)`); |
||||
let getVal = regKey.test(hashstr) ? hashstr.match(regKey)[1] : null; |
||||
if (val == undefined) return getVal; |
||||
if (hashstr == '' || hashstr == '#') { |
||||
window.location.hash = `#${key}=${val}`; |
||||
} |
||||
else { |
||||
if (getVal) window.location.hash = hashstr.replace(getVal, val); |
||||
else { |
||||
window.location.hash = hashstr.indexOf(key) > -1 ? hashstr.replace(regKey, `${key}=${val}`) : `${hashstr}&${key}=${val}`; |
||||
} |
||||
} |
||||
} |
||||
// 创建源规则容器对象
|
||||
function Container() { |
||||
let ruleJson = {}; |
||||
let searchJson = {}; |
||||
let exploreJson = {}; |
||||
let bookInfoJson = {}; |
||||
let tocJson = {}; |
||||
let contentJson = {}; |
||||
|
||||
// 基本以及其他
|
||||
$$('.rules .base').forEach(item => ruleJson[item.title] = ''); |
||||
ruleJson.lastUpdateTime = 0; |
||||
ruleJson.customOrder = 0; |
||||
ruleJson.weight = 0; |
||||
ruleJson.enabled = true; |
||||
ruleJson.enabledExplore = true; |
||||
|
||||
// 搜索规则
|
||||
$$('.rules .ruleSearch').forEach(item => searchJson[item.title] = ''); |
||||
ruleJson.ruleSearch = searchJson; |
||||
|
||||
// 发现规则
|
||||
$$('.rules .ruleExplore').forEach(item => exploreJson[item.title] = ''); |
||||
ruleJson.ruleExplore = exploreJson; |
||||
|
||||
// 详情页规则
|
||||
$$('.rules .ruleBookInfo').forEach(item => bookInfoJson[item.title] = ''); |
||||
ruleJson.ruleBookInfo = bookInfoJson; |
||||
|
||||
// 目录规则
|
||||
$$('.rules .ruleToc').forEach(item => tocJson[item.title] = ''); |
||||
ruleJson.ruleToc = tocJson; |
||||
|
||||
// 正文规则
|
||||
$$('.rules .ruleContent').forEach(item => contentJson[item.title] = ''); |
||||
ruleJson.ruleContent = contentJson; |
||||
|
||||
return ruleJson; |
||||
} |
||||
// 选项卡Tab切换事件处理
|
||||
function showTab(tabName) { |
||||
$$('.tabtitle>*').forEach(node => { node.className = node.className.replace(' this', ''); }); |
||||
$$('.tabbody>*').forEach(node => { node.className = node.className.replace(' this', ''); }); |
||||
$(`.tabbody>.${$(`.tabtitle>*[name=${tabName}]`).className}`).className += ' this'; |
||||
$(`.tabtitle>*[name=${tabName}]`).className += ' this'; |
||||
hashParam('tab', tabName); |
||||
} |
||||
// 源列表列表标签构造函数
|
||||
function newRule(rule) { |
||||
return `<label for="${rule.bookSourceUrl}"><input type="radio" name="rule" id="${rule.bookSourceUrl}"><div>${rule.bookSourceName}<br>${rule.bookSourceUrl}</div></label>`; |
||||
} |
||||
// 缓存规则列表
|
||||
var RuleSources = []; |
||||
if (localStorage.getItem('BookSources')) { |
||||
RuleSources = JSON.parse(localStorage.getItem('BookSources')); |
||||
RuleSources.forEach(item => $('#RuleList').innerHTML += newRule(item)); |
||||
} |
||||
// 页面加载完成事件
|
||||
window.onload = () => { |
||||
$$('.tabtitle>*').forEach(item => { |
||||
item.addEventListener('click', () => { |
||||
showTab(item.innerHTML); |
||||
}); |
||||
}); |
||||
if (hashParam('tab')) showTab(hashParam('tab')); |
||||
} |
||||
// 获取数据
|
||||
function HttpGet(url) { |
||||
return fetch(hashParam('domain') ? hashParam('domain') + url : url) |
||||
.then(res => res.json()).catch(err => console.error('Error:', err)); |
||||
} |
||||
// 提交数据
|
||||
function HttpPost(url, data) { |
||||
return fetch(hashParam('domain') ? hashParam('domain') + url : url, { |
||||
body: JSON.stringify(data), |
||||
method: 'POST', |
||||
mode: "cors", |
||||
headers: new Headers({ |
||||
'Content-Type': 'application/json;charset=utf-8' |
||||
}) |
||||
}).then(res => res.json()).catch(err => console.error('Error:', err)); |
||||
} |
||||
// 将源表单转化为源对象
|
||||
function rule2json() { |
||||
let RuleJSON = Container(); |
||||
// 转换base
|
||||
Object.keys(RuleJSON).forEach(key => { |
||||
if (!key.startsWith("rule")) { |
||||
RuleJSON[key] = $('#' + key).value; |
||||
} |
||||
}); |
||||
|
||||
// 转换搜索规则
|
||||
let searchJson = {}; |
||||
Object.keys(RuleJSON.ruleSearch).forEach(key => { |
||||
if ($('#' + 'ruleSearch_' + key).value) |
||||
searchJson[key] = $('#' + 'ruleSearch_' + key).value; |
||||
}); |
||||
RuleJSON.ruleSearch = searchJson; |
||||
|
||||
// 转换发现规则
|
||||
let exploreJson = {}; |
||||
Object.keys(RuleJSON.ruleExplore).forEach(key => { |
||||
if ($('#' + 'ruleExplore_' + key).value) |
||||
exploreJson[key] = $('#' + 'ruleExplore_' + key).value; |
||||
}); |
||||
RuleJSON.ruleExplore = exploreJson; |
||||
|
||||
// 转换详情页规则
|
||||
let bookInfoJson = {}; |
||||
Object.keys(RuleJSON.ruleBookInfo).forEach(key => { |
||||
if ($('#' + 'ruleBookInfo_' + key).value) |
||||
bookInfoJson[key] = $('#' + 'ruleBookInfo_' + key).value; |
||||
}); |
||||
RuleJSON.ruleBookInfo = bookInfoJson; |
||||
|
||||
// 转换目录规则
|
||||
let tocJson = {}; |
||||
Object.keys(RuleJSON.ruleToc).forEach(key => { |
||||
if ($('#' + 'ruleToc_' + key).value) |
||||
tocJson[key] = $('#' + 'ruleToc_' + key).value; |
||||
}); |
||||
RuleJSON.ruleToc = tocJson; |
||||
|
||||
// 转换正文规则
|
||||
let contentJson = {}; |
||||
Object.keys(RuleJSON.ruleContent).forEach(key => { |
||||
if ($('#' + 'ruleContent_' + key).value) |
||||
contentJson[key] = $('#' + 'ruleContent_' + key).value; |
||||
}); |
||||
RuleJSON.ruleContent = contentJson; |
||||
|
||||
RuleJSON.lastUpdateTime = new Date().getTime(); |
||||
RuleJSON.customOrder = RuleJSON.customOrder == '' ? 0 : parseInt(RuleJSON.customOrder); |
||||
RuleJSON.weight = RuleJSON.weight == '' ? 0 : parseInt(RuleJSON.weight); |
||||
RuleJSON.bookSourceType == RuleJSON.bookSourceType == '' ? 0 : parseInt(RuleJSON.bookSourceType); |
||||
RuleJSON.enabled = RuleJSON.enabled == '' || String(RuleJSON.enabled).toLocaleLowerCase().replace(/^\s*|\s*$/g, '') == 'true'; |
||||
RuleJSON.enabledExplore = RuleJSON.enabledExplore == '' || String(RuleJSON.enabledExplore).toLocaleLowerCase().replace(/^\s*|\s*$/g, '') == 'true'; |
||||
return RuleJSON; |
||||
} |
||||
// 将源对象填充到源表单
|
||||
function json2rule(RuleEditor) { |
||||
let RuleJSON = Container(); |
||||
// 转换base
|
||||
Object.keys(RuleJSON).forEach(key => { |
||||
if (!key.startsWith("rule")) { |
||||
let val = RuleEditor[key]; |
||||
if (typeof val == "number") { |
||||
$("#" + key).value = val ? String(val) : '0'; |
||||
} |
||||
else if (typeof val == "boolean") { |
||||
$("#" + key).value = val ? String(val) : 'false'; |
||||
} |
||||
else { |
||||
$("#" + key).value = val ? String(val) : ''; |
||||
} |
||||
} |
||||
}); |
||||
|
||||
// 转换搜索规则
|
||||
if (RuleEditor.ruleSearch) { |
||||
let searchJson = RuleEditor.ruleSearch; |
||||
Object.keys(RuleJSON.ruleSearch).forEach(key => { |
||||
$('#' + 'ruleSearch_' + key).value = searchJson[key] ? searchJson[key] : ''; |
||||
}); |
||||
} |
||||
|
||||
// 转换发现规则
|
||||
if (RuleEditor.ruleExplore) { |
||||
let exploreJson = RuleEditor.ruleExplore; |
||||
Object.keys(RuleJSON.ruleExplore).forEach(key => { |
||||
$('#' + 'ruleExplore_' + key).value = exploreJson[key] ? exploreJson[key] : ''; |
||||
}); |
||||
} |
||||
|
||||
// 转换详情页规则
|
||||
if (RuleEditor.ruleBookInfo) { |
||||
let bookInfoJson = RuleEditor.ruleBookInfo; |
||||
Object.keys(RuleJSON.ruleBookInfo).forEach(key => { |
||||
$('#' + 'ruleBookInfo_' + key).value = bookInfoJson[key] ? bookInfoJson[key] : ''; |
||||
}); |
||||
} |
||||
|
||||
// 转换目录规则
|
||||
if (RuleEditor.ruleToc) { |
||||
let tocJson = RuleEditor.ruleToc; |
||||
Object.keys(RuleJSON.ruleToc).forEach(key => { |
||||
$('#' + 'ruleToc_' + key).value = tocJson[key] ? tocJson[key] : ''; |
||||
}); |
||||
} |
||||
|
||||
// 转换正文规则
|
||||
if (RuleEditor.ruleContent) { |
||||
let contentJson = RuleEditor.ruleContent; |
||||
Object.keys(RuleJSON.ruleContent).forEach(key => { |
||||
$('#' + 'ruleContent_' + key).value = contentJson[key] ? contentJson[key] : ''; |
||||
}); |
||||
} |
||||
} |
||||
// 记录操作过程
|
||||
var course = { "old": [], "now": {}, "new": [] }; |
||||
if (localStorage.getItem('bookSourceCourse')) { |
||||
course = JSON.parse(localStorage.getItem('bookSourceCourse')); |
||||
json2rule(course.now); |
||||
} |
||||
else { |
||||
course.now = rule2json(); |
||||
window.localStorage.setItem('bookSourceCourse', JSON.stringify(course)); |
||||
} |
||||
function todo() { |
||||
course.old.push(Object.assign({}, course.now)); |
||||
course.now = rule2json(); |
||||
course.new = []; |
||||
if (course.old.length > 50) course.old.shift(); // 限制历史记录堆栈大小
|
||||
localStorage.setItem('bookSourceCourse', JSON.stringify(course)); |
||||
} |
||||
function undo() { |
||||
course = JSON.parse(localStorage.getItem('bookSourceCourse')); |
||||
if (course.old.length > 0) { |
||||
course.new.push(course.now); |
||||
course.now = course.old.pop(); |
||||
localStorage.setItem('bookSourceCourse', JSON.stringify(course)); |
||||
json2rule(course.now); |
||||
} |
||||
} |
||||
function redo() { |
||||
course = JSON.parse(localStorage.getItem('bookSourceCourse')); |
||||
if (course.new.length > 0) { |
||||
course.old.push(course.now); |
||||
course.now = course.new.pop(); |
||||
localStorage.setItem('bookSourceCourse', JSON.stringify(course)); |
||||
json2rule(course.now); |
||||
} |
||||
} |
||||
function setRule(editRule) { |
||||
let checkRule = RuleSources.find(x => x.bookSourceUrl == editRule.bookSourceUrl); |
||||
if ($(`input[id="${editRule.bookSourceUrl}"]`)) { |
||||
Object.keys(checkRule).forEach(key => { checkRule[key] = editRule[key]; }); |
||||
$(`input[id="${editRule.bookSourceUrl}"]+*`).innerHTML = `${editRule.bookSourceName}<br>${editRule.bookSourceUrl}`; |
||||
} else { |
||||
RuleSources.push(editRule); |
||||
$('#RuleList').innerHTML += newRule(editRule); |
||||
} |
||||
} |
||||
$$('input').forEach((item) => { item.addEventListener('change', () => { todo() }) }); |
||||
$$('textarea').forEach((item) => { item.addEventListener('change', () => { todo() }) }); |
||||
// 处理按钮点击事件
|
||||
$('.menu').addEventListener('click', e => { |
||||
let thisNode = e.target; |
||||
thisNode = thisNode.parentNode.nodeName == 'svg' ? thisNode.parentNode.querySelector('rect') : |
||||
thisNode.nodeName == 'svg' ? thisNode.querySelector('rect') : null; |
||||
if (!thisNode) return; |
||||
if (thisNode.getAttribute('class') == 'busy') return; |
||||
thisNode.setAttribute('class', 'busy'); |
||||
switch (thisNode.id) { |
||||
case 'push': |
||||
$$('#RuleList>label>div').forEach(item => { item.className = ''; }); |
||||
(async () => { |
||||
await HttpPost(`/saveBookSources`, RuleSources).then(json => { |
||||
if (json.isSuccess) { |
||||
let okData = json.data; |
||||
if (Array.isArray(okData)) { |
||||
let failMsg = ``; |
||||
if (RuleSources.length > okData.length) { |
||||
RuleSources.forEach(item => { |
||||
if (okData.find(x => x.bookSourceUrl == item.bookSourceUrl)) { } |
||||
else { $(`#RuleList #${item.bookSourceUrl}+*`).className += 'isError'; } |
||||
}); |
||||
failMsg = '\n推送失败的源将用红色字体标注!'; |
||||
} |
||||
alert(`批量推送源到「阅读3.0APP」\n共计: ${RuleSources.length} 条\n成功: ${okData.length} 条\n失败: ${RuleSources.length - okData.length} 条${failMsg}`); |
||||
} |
||||
else { |
||||
alert(`批量推送源到「阅读3.0APP」成功!\n共计: ${RuleSources.length} 条`); |
||||
} |
||||
} |
||||
else { |
||||
alert(`批量推送源失败!\nErrorMsg: ${json.errorMsg}`); |
||||
} |
||||
}).catch(err => { alert(`批量推送源失败,无法连接到「阅读3.0APP」!\n${err}`); }); |
||||
thisNode.setAttribute('class', ''); |
||||
})(); |
||||
return; |
||||
case 'pull': |
||||
showTab('源列表'); |
||||
(async () => { |
||||
await HttpGet(`/getBookSources`).then(json => { |
||||
if (json.isSuccess) { |
||||
$('#RuleList').innerHTML = '' |
||||
localStorage.setItem('BookSources', JSON.stringify(RuleSources = json.data)); |
||||
RuleSources.forEach(item => { |
||||
$('#RuleList').innerHTML += newRule(item); |
||||
}); |
||||
alert(`成功拉取 ${RuleSources.length} 条源`); |
||||
} |
||||
else { |
||||
alert(`批量拉取源失败!\nErrorMsg: ${json.errorMsg}`); |
||||
} |
||||
}).catch(err => { alert(`批量拉取源失败,无法连接到「阅读3.0APP」!\n${err}`); }); |
||||
thisNode.setAttribute('class', ''); |
||||
})(); |
||||
return; |
||||
case 'editor': |
||||
if ($('#RuleJsonString').value == '') break; |
||||
try { |
||||
json2rule(JSON.parse($('#RuleJsonString').value)); |
||||
todo(); |
||||
} catch (error) { |
||||
console.log(error); |
||||
alert(error); |
||||
} |
||||
break; |
||||
case 'conver': |
||||
showTab('编辑源'); |
||||
$('#RuleJsonString').value = JSON.stringify(rule2json(), null, 4); |
||||
break; |
||||
case 'initial': |
||||
$$('.rules textarea').forEach(item => { item.value = '' }); |
||||
todo(); |
||||
break; |
||||
case 'undo': |
||||
undo() |
||||
break; |
||||
case 'redo': |
||||
redo() |
||||
break; |
||||
case 'debug': |
||||
showTab('调试源'); |
||||
let wsOrigin = (hashParam('domain') || location.origin).replace(/^.*?:/, 'ws:').replace(/\d+$/, (port) => (parseInt(port) + 1)); |
||||
let DebugInfos = $('#DebugConsole'); |
||||
function DebugPrint(msg) { DebugInfos.value += `\n${msg}`; DebugInfos.scrollTop = DebugInfos.scrollHeight; } |
||||
let saveRule = [rule2json()]; |
||||
HttpPost(`/saveBookSources`, saveRule).then(sResult => { |
||||
if (sResult.isSuccess) { |
||||
let sKey = DebugKey.value ? DebugKey.value : '我的'; |
||||
$('#DebugConsole').value = `源《${saveRule[0].bookSourceName}》保存成功!使用搜索关键字“${sKey}”开始调试...`; |
||||
let ws = new WebSocket(`${wsOrigin}/bookSourceDebug`); |
||||
ws.onopen = () => { |
||||
ws.send(`{"tag":"${saveRule[0].bookSourceUrl}", "key":"${sKey}"}`); |
||||
}; |
||||
ws.onmessage = (msg) => { |
||||
console.log('[调试]', msg); |
||||
DebugPrint(msg.data); |
||||
}; |
||||
ws.onerror = (err) => { |
||||
throw `${err.data}`; |
||||
} |
||||
ws.onclose = () => { |
||||
thisNode.setAttribute('class', ''); |
||||
DebugPrint(`\n调试服务已关闭!`); |
||||
} |
||||
} else throw `${sResult.errorMsg}`; |
||||
}).catch(err => { |
||||
DebugPrint(`调试过程意外中止,以下是详细错误信息:\n${err}`); |
||||
thisNode.setAttribute('class', ''); |
||||
}); |
||||
return; |
||||
case 'accept': |
||||
(async () => { |
||||
let saveRule = [rule2json()]; |
||||
await HttpPost(`/saveBookSource`, saveRule[0]).then(json => { |
||||
alert(json.isSuccess ? `源《${saveRule[0].bookSourceName}》已成功保存到「阅读3.0APP」` : `源《${saveRule[0].bookSourceName}》保存失败!\nErrorMsg: ${json.errorMsg}`); |
||||
setRule(saveRule[0]); |
||||
}).catch(err => { alert(`保存源失败,无法连接到「阅读3.0APP」!\n${err}`); }); |
||||
thisNode.setAttribute('class', ''); |
||||
})(); |
||||
return; |
||||
default: |
||||
} |
||||
setTimeout(() => { thisNode.setAttribute('class', ''); }, 500); |
||||
}); |
||||
$('#DebugKey').addEventListener('keydown', e => { |
||||
if (e.keyCode == 13) { |
||||
let clickEvent = document.createEvent('MouseEvents'); |
||||
clickEvent.initEvent("click", true, false); |
||||
$('#debug').dispatchEvent(clickEvent); |
||||
} |
||||
}); |
||||
$('#Filter').addEventListener('keydown', e => { |
||||
if (e.keyCode == 13) { |
||||
let cashList = []; |
||||
$('#RuleList').innerHTML = ""; |
||||
let sKey = Filter.value ? Filter.value : ''; |
||||
if (sKey == '') { |
||||
cashList = RuleSources; |
||||
} else { |
||||
let patt = new RegExp(sKey); |
||||
RuleSources.forEach(source => { |
||||
if (patt.test(source.bookSourceUrl) || patt.test(source.bookSourceName) || patt.test(source.bookSourceGroup)) { |
||||
cashList.push(source); |
||||
} |
||||
}) |
||||
} |
||||
cashList.forEach(source => { |
||||
$('#RuleList').innerHTML += newRule(source); |
||||
}) |
||||
} |
||||
}); |
||||
|
||||
// 列表规则更改事件
|
||||
$('#RuleList').addEventListener('click', e => { |
||||
let editRule = null; |
||||
if (e.target && e.target.getAttribute('name') == 'rule') { |
||||
editRule = rule2json(); |
||||
json2rule(RuleSources.find(x => x.bookSourceUrl == e.target.id)); |
||||
} else return; |
||||
if (editRule.bookSourceUrl == '') return; |
||||
if (editRule.bookSourceName == '') editRule.bookSourceName = editRule.bookSourceUrl.replace(/.*?\/\/|\/.*/g, ''); |
||||
setRule(editRule); |
||||
localStorage.setItem('BookSources', JSON.stringify(RuleSources)); |
||||
}); |
||||
// 处理列表按钮事件
|
||||
$('.tab3>.titlebar').addEventListener('click', e => { |
||||
let thisNode = e.target; |
||||
if (thisNode.nodeName != 'BUTTON') return; |
||||
switch (thisNode.id) { |
||||
case 'Import': |
||||
let fileImport = document.createElement('input'); |
||||
fileImport.type = 'file'; |
||||
fileImport.accept = '.json'; |
||||
fileImport.addEventListener('change', () => { |
||||
let file = fileImport.files[0]; |
||||
let reader = new FileReader(); |
||||
reader.onloadend = function (evt) { |
||||
if (evt.target.readyState == FileReader.DONE) { |
||||
let fileText = evt.target.result; |
||||
try { |
||||
let fileJson = JSON.parse(fileText); |
||||
let newSources = []; |
||||
newSources.push(...fileJson); |
||||
if (window.confirm(`如何处理导入的源?\n"确定": 覆盖当前列表(不会删除APP源)\n"取消": 插入列表尾部(自动忽略重复源)`)) { |
||||
localStorage.setItem('BookSources', JSON.stringify(RuleSources = newSources)); |
||||
$('#RuleList').innerHTML = '' |
||||
RuleSources.forEach(item => { |
||||
$('#RuleList').innerHTML += newRule(item); |
||||
}); |
||||
} |
||||
else { |
||||
newSources = newSources.filter(item => !JSON.stringify(RuleSources).includes(item.bookSourceUrl)); |
||||
RuleSources.push(...newSources); |
||||
localStorage.setItem('BookSources', JSON.stringify(RuleSources)); |
||||
newSources.forEach(item => { |
||||
$('#RuleList').innerHTML += newRule(item); |
||||
}); |
||||
} |
||||
alert(`成功导入 ${newSources.length} 条源`); |
||||
} |
||||
catch (err) { |
||||
alert(`导入源文件失败!\n${err}`); |
||||
} |
||||
} |
||||
}; |
||||
reader.readAsText(file); |
||||
}, false); |
||||
fileImport.click(); |
||||
break; |
||||
case 'Export': |
||||
let fileExport = document.createElement('a'); |
||||
fileExport.download = `Rules${Date().replace(/.*?\s(\d+)\s(\d+)\s(\d+:\d+:\d+).*/, '$2$1$3').replace(/:/g, '')}.json`; |
||||
let myBlob = new Blob([JSON.stringify(RuleSources, null, 4)], { type: "application/json" }); |
||||
fileExport.href = window.URL.createObjectURL(myBlob); |
||||
fileExport.click(); |
||||
break; |
||||
case 'Delete': |
||||
let selectRule = $('#RuleList input:checked'); |
||||
if (!selectRule) { |
||||
alert(`没有源被选中!`); |
||||
return; |
||||
} |
||||
if (confirm(`确定要删除选定源吗?\n(同时删除APP内源)`)) { |
||||
let selectRuleUrl = selectRule.id; |
||||
let deleteSources = RuleSources.filter(item => item.bookSourceUrl == selectRuleUrl); // 提取待删除的源
|
||||
let laveSources = RuleSources.filter(item => !(item.bookSourceUrl == selectRuleUrl)); // 提取待留下的源
|
||||
HttpPost(`/deleteBookSources`, deleteSources).then(json => { |
||||
if (json.isSuccess) { |
||||
let selectNode = document.getElementById(selectRuleUrl).parentNode; |
||||
selectNode.parentNode.removeChild(selectNode); |
||||
localStorage.setItem('BookSources', JSON.stringify(RuleSources = laveSources)); |
||||
if ($('#bookSourceUrl').value == selectRuleUrl) { |
||||
$$('.rules textarea').forEach(item => { item.value = '' }); |
||||
todo(); |
||||
} |
||||
console.log(deleteSources); |
||||
console.log(`以上源已删除!`) |
||||
} |
||||
}).catch(err => { alert(`删除源失败,无法连接到「阅读3.0APP」!\n${err}`); }); |
||||
} |
||||
break; |
||||
case 'ClrAll': |
||||
if (confirm(`确定要清空当前源列表吗?\n(不会删除APP内源)`)) { |
||||
localStorage.setItem('BookSources', JSON.stringify(RuleSources = [])); |
||||
$('#RuleList').innerHTML = '' |
||||
} |
||||
break; |
||||
default: |
||||
} |
||||
}); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue