// ==UserScript==
// @name 学术下载解析工具-知网-万方-维普-皮书
// @namespace http://tampermonkey.net/
// @version 1.2
// @description 反馈邮件:[email protected]
// @author [email protected]
// @match https://oss.wanfangdata.com.cn/*
// @match https://*.cnki.net/kcms2/*
// @match https://d.wanfangdata.com.cn/*
// @match https://lib.cqvip.com/Qikan/Article/*
// @match https://www.pishu.com.cn/skwx_ps/literature*
// @match https://www.pishu.com.cn/skwx_ps/initDatabaseDetail*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant unsafeWindow
// @require https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js
// @require https://unpkg.com/[email protected]/dist/layui.js
// @connect xuexi365.top
// @connect scriptcat.org
// @connect 127.0.0.1
// @connect wanfangdata.com.cn
// @connect cqvip.com
// @connect cnki.net
// @grant GM_xmlhttpRequest
// @grant GM_getResourceText
// @grant GM_cookie
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_listValues
// @grant GM_deleteValue
// @grant GM_download
// @license MIT
// ==/UserScript==
(function () {
'use strict';
/* globals jQuery, $, waitForKeyElements */
const $ = unsafeWindow.jQuery;
// 代码内部 引入bootstrap的css文件并加入html中
let link = document.createElement('link');
link.rel = "stylesheet"
link.href = 'https://unpkg.com/[email protected]/dist/css/layui.css';
document.head.appendChild(link);
const x_path = "http://www.xuexi365.top/"
const X_root = "www.xuexi365.top"
const x_api_path = "R85ED6952/"
const x_api_ERR_path = "K85ED695211/"
const x_sso_path="HG907DJF6D/"
//验证码地址
const captcha_url = x_path+x_sso_path+"verify";
//登录地址
const login_url = x_path+x_sso_path+"login";
//注册地址
const reg_url = x_path+x_sso_path+"reg";
//隐藏本来的滚动条
$('.fixedbar').hide();
$('.anxs-left-bom').hide();
$('.web-tools').hide();
let Gmsg = "";
function get(url, retAll = false, headers = { "Content-Type": "text/json,charset=utf-8" }, responseType = "json") {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "get",
url: url,
headers: headers,
responseType: responseType,
onload: function (res) {
if (retAll) {
resolve(res);
} else {
if(res.response==undefined&&responseType != "json"){
resolve(res.responseText);
}else if(res.response==undefined&&responseType == "json"){
resolve(JSON.parse(res.responseText));
}else{
resolve(res.response);
}
}
},
onerror: function (err) {
reject(err)
}
});
});
}
let url = 'http://www.xuexi365.top/msg.json?' + Date.now();
let a = get(url,false,{ "Accept": "application/json" ,"Content-Type":"application/json"}, "json");
a.then(resolve => {
Gmsg = resolve;
if (GM_getValue(Gmsg.msg_id, -1) == -1 && Gmsg.msg_active != 0) {
layer.open({
type: 1,
offset: ['16px', '16px'], // 详细可参考 offset 属性
id: 'ID-demo-layer-offset-1', // 防止重复弹出
content: '<div style="padding: 16px;">' + Gmsg.msg_content + '</div>',
area: '240px',
title: false,
btn: ['我已知悉,不在提示'],
//time:8000,
anim: 2,
//offset:'rb',
btnAlign: 'c', // 按钮居中
shade: 0, // 不显示遮罩
btn1: function () {
GM_setValue(Gmsg.msg_id, 1);
layer.closeAll();
}
});
}
})
//const help_content = GM_getResourceText("Content");
let login_content = `<div><form class="layui-form" style="margin:20px" lay-filter="loginForm">
<div class="demo-login-container">
<div class="layui-form-item">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-username"></i>
</div>
<input type="text" name="username" value="" lay-verify="required" placeholder="用户名" lay-reqtext="请填写用户名" autocomplete="off" class="layui-input" lay-affix="clear">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-password"></i>
</div>
<input type="password" name="password" value="" lay-verify="required" placeholder="密 码" lay-reqtext="请填写密码" autocomplete="off" class="layui-input" lay-affix="eye">
</div>
</div>
<div class="layui-form-item">
<div class="layui-row">
<div class="layui-col-xs7">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-vercode"></i>
</div>
<input type="text" name="checkCode" value="" lay-verify="required" placeholder="验证码" lay-reqtext="请填写验证码" autocomplete="off" class="layui-input" lay-affix="clear">
</div>
</div>
<div class="layui-col-xs5">
<div style="margin-left: 10px;">
<img lay-filter="getCaptchaData" lay-on="getCaptchaData" id="getCaptchaData" style="width:120px;height:40px" src="{imageData}" >
</div>
</div>
</div>
</div>
<div class="layui-form-item">
<input type="checkbox" name="remember" value=1 lay-skin="primary" title="记住密码">
</div>
<div class="layui-form-item">
<button class="layui-btn layui-btn-fluid" lay-submit lay-filter="login-login">登录</button>
</div>
<div class="layui-form-item demo-login-other">
<a lay-filter="gotoReg" lay-on="gotoReg" >注册帐号</a>
</div>
</div>
</form></div>`
let success_content = `<div class="layui-bg-gray" style="">
<div class="layui-row ">
<div >
<div class="layui-card" style="">
<div class="layui-card-header">个人中心</div>
<div class="layui-card-body">
登录状态:已登录
</div>
<div class="layui-card-body">
登录账号:{username}
</div>
<div class="layui-card-body">
<button type="button" lay-submit lay-filter="loginOut" id="loginOut" class="layui-btn layui-btn-fluid">退出登录</button>
</div>
</div>
</div>
</div>
</div>`
let reg_content = `<form class="layui-form" style="margin:20px" lay-filter="regForm">
<div class="demo-login-container">
<div class="layui-form-item">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-username"></i>
</div>
<input type="text" name="username" value="" lay-verify="required|username" placeholder="用户名" lay-reqtext="请填写用户名" autocomplete="off" class="layui-input" lay-affix="clear">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-password"></i>
</div>
<input type="password" name="password" value="" lay-verify="required|password" placeholder="密 码" lay-reqtext="请填写密码" autocomplete="off" class="layui-input" lay-affix="eye">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-password"></i>
</div>
<input type="password" name="password2" value="" lay-verify="required|password" placeholder="确认密码" lay-reqtext="请填写密码" autocomplete="off" class="layui-input" lay-affix="eye">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-email"></i>
</div>
<input type="text" name="email" value="" lay-verify="required|email" placeholder="邮箱" lay-reqtext="请填写用户名" autocomplete="off" class="layui-input" lay-affix="clear">
</div>
</div>
<div class="layui-form-item">
<div class="layui-row">
<div class="layui-col-xs7">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-vercode"></i>
</div>
<input type="text" name="checkCode" value="" lay-verify="required" placeholder="验证码" lay-reqtext="请填写验证码" autocomplete="off" class="layui-input" lay-affix="clear">
</div>
</div>
<div class="layui-col-xs5">
<div style="margin-left: 10px;">
<img lay-filter="getCaptchaData" id="getCaptchaData" lay-on="getCaptchaData" style="width:120px;height:40px" src="{imageData}" >
</div>
</div>
</div>
</div>
<div class="layui-form-item">
<button class="layui-btn layui-btn-fluid" lay-submit lay-filter="reg-reg">注册账号</button>
</div>
</div>
</form>
`
let help_content = `
<div class="layui-card">
<div class="layui-card-header">本地插件版本</div>
<div class="layui-card-body" style="max-height: 100px; overflow: auto">
<h4>${GM_info.script.version} <a href="https://scriptcat.org/zh-CN/script-show-page/1397/" target="_blank"
class="layui-btn layui-btn-xs">更新地址</a> </h4>
</div>
</div>
<div class="layui-card">
<div class="layui-card-header">网络更新日志</div>
<div class="layui-card-body" style="max-height: 300px;overflow: auto;">
<div class="layui-timeline">
<div class="layui-timeline-item">
<i class="layui-icon layui-anim layui-anim-rotate layui-anim-loop layui-timeline-axis"></i>
<div class="layui-timeline-content layui-text">
<div class="layui-timeline-title">持续更新中~。</div>
</div>
{items}
</div>
</div>
</div>
</div>
<div class="layui-card">
<div class="layui-card-header">其他链接</div>
<div class="layui-card-body" style="max-height: 200px; overflow: auto">
<div class="layui-row">
<a href="https://www.sousoushu.top/" type="button" class="layui-btn layui-btn-fluid" target="_blank">
免费电子书下载
</a>
</div>
<div class="layui-row layui-col-space5" style="padding-top: 10px;">
<div class="layui-col-xs3">
<a href="https://www.cnki.net/" type="button" class="layui-btn layui-btn-fluid" target="_blank">
知网
</a>
</div>
<div class="layui-col-xs3">
<a href="https://www.wanfangdata.com.cn/" type="button" class="layui-btn layui-btn-fluid" target="_blank">
万方
</a>
</div>
<div class="layui-col-xs3">
<a href="https://lib.cqvip.com/" type="button" class="layui-btn layui-btn-fluid" target="_blank">
维普
</a>
</div>
<div class="layui-col-xs3">
<a href="https://www.pishu.com.cn/" type="button" class="layui-btn layui-btn-fluid" target="_blank">
皮书
</a>
</div>
</div>
</lay-row>
</div>
</div>
`
let cnki_select_content = `
<form class="layui-form layui-form-pane" action="" lay-filter="cnkiSelect" style="margin:20px">
<div class="layui-form-item" pane>
<label class="layui-form-label">文件格式</label>
<div class="layui-input-block">
<input type="radio" name="dowType" value="pdf" title="PDF" checked>
<input type="radio" name="dowType" value="caj" title="CAJ">
</div>
</div>
<div class="layui-form-item" pane>
<label class="layui-form-label">期刊类型</label>
<div class="layui-input-block">
<input type="radio" name="cnkiType" value="0" title="通用" checked>
<input type="radio" name="cnkiType" value="1" title="特殊">
</div>
</div>
<p style="color:red">注意:只有无法下载的期刊才选用特殊</P>
<br/>
<div class="layui-form-item layui-row" >
<button type="button" lay-submit class="layui-btn layui-btn-fluid" lay-filter="cnkiSelectBtn" >下载</button>
</div>
</form>
`
layui.use('element', function () {
var util = layui.util;
var form = layui.form;
var layer = layui.layer;
var element = layui.element;
var util = layui.util;
//验证码cookie
var captchaCookies = ""
var regWinId = 0;
var bars = [{
type: 'user',
icon: 'layui-icon-username',
style: 'background-color:#1e9fff',
}, {
type: 'help',
icon: 'layui-icon-app',
style: 'background-color: #16b777',
}, {
type: 'error',
icon: 'layui-icon-survey',
style: 'background-color:#16b777;',
}, {
type: 'download',
icon: 'layui-icon-download-circle',
style: 'background-color: #16b777;',
}, {
type: 'read',
icon: 'layui-icon-read',
style: 'background-color: #16b777;',
}]
// 自定义固定条
util.fixbar({
bars: bars,
default: false,
css: { bottom: 200 },
on: { // 任意事件 -- v2.8.0 新增
mouseenter: function (type) {
let C = { 'help': "使用说明", "download": "下载文章", 'error': "无法使用/错误上报", "read": "在线预览", "user": "用户登录" }
layer.tips(C[type], this, {
tips: 4,
fixed: true
});
},
mouseleave: function (type) {
layer.closeAll('tips');
}
},
// 点击事件
click: function (type) {
if (type == 'help') {
getUpdateLog();
} else if (type == 'download') {
x_dow();
} else if (type == 'read') {
x_dow(true);
} else if (type == 'error') {
x_err();
} else if (type == 'user') {
userBtnClick();
}
}
});
//知网选项点击
form.on('submit(cnkiSelectBtn)', function (data) {
let json=data.field;
x_dow(false,json);
});
var data="";
function x_dow(t=false,json=""){
data={"url":location.href,'time':Date.now()};
GM_xmlhttpRequest({
method: "POST",
url: x_path + x_api_path,
data: JSON.stringify(data),
anonymous: true,
headers: {
"Accept": "application/json, text/javascript, */*; q=0.01",
"Content-Type": "application/json; charset=utf-8"
},
onload: function (res) {
let json = JSON.parse(res.responseText);
//正常获取到参数
layer.alert(json.data.msg);
},
onerror: function () {
layer.close(loadIndex);
layer.alert('出现错误,请重试');
}
});
}
function x_err(){
data={"url":location.href,'time':Date.now()};
GM_xmlhttpRequest({
method: "POST",
url: x_path + x_api_ERR_path,
data: JSON.stringify(data),
anonymous: true,
headers: {
"Accept": "application/json, text/javascript, */*; q=0.01",
"Content-Type": "application/json; charset=utf-8"
},
onload: function (res) {
let json = JSON.parse(res.responseText);
//正常获取到参数
layer.alert(json.data.msg);
},
onerror: function () {
layer.close(loadIndex);
layer.alert('出现错误,请重试');
}
});
}
//获取验证码数据
function getCaptchaData(element = "") {
let a = get(captcha_url, true, {}, "blob");
a.then(resolve => {
var setCookieRegex = /Set-Cookie:\s*([^;\n]*)(;\s*[^;\n]*)?/ig;
var match = setCookieRegex.exec(resolve.responseHeaders)
captchaCookies = match[1];
captchaCookies = captchaCookies.replace(/^"|"$/g, '');
var baseimg = "data:image/png;base64," + btoa(resolve.responseText);
if (element == "") {
return baseimg;
} else {
element.attr("src", baseimg);
}
});
}
//退出登录
form.on('submit(loginOut)', function (data) {
GM_setValue("token", undefined);
layer.closeAll();
layer.msg('退出登录成功');
});
//跳转注册
util.on({
gotoReg: function () {
let a = get(captcha_url, true, {}, "blob");
a.then(resolve => {
var setCookieRegex = /Set-Cookie:\s*([^;\n]*)(;\s*[^;\n]*)?/ig;
var match = setCookieRegex.exec(resolve.responseHeaders)
captchaCookies = match[1];
captchaCookies = captchaCookies.replace(/^"|"$/g, '');
var baseimg = "data:image/png;base64," + btoa(resolve.responseText);
let content = reg_content
content = content.replace("{imageData}", baseimg);
regWinId = layer.open({
title: '用户注册',
type: 1,
//area:['370px'],
shade: 0.5,
shadeClose: true,
// area: ['520px', '340px'], // 宽高
content: content
});
});
}
});
//验证码点击
util.on({
getCaptchaData: function () {
getCaptchaData($(this));
}
});
// 登录提交事件
form.on('submit(login-login)', function (data) {
var field = JSON.stringify(data.field); // 获取表单字段值
var this_ = $(this);
// 显示填写结果,仅作演示用
GM_xmlhttpRequest({
method: "POST",
url: login_url,
data: field,
anonymous: true,
cookie: captchaCookies,
headers: {
"Accept": "application/json",
"Content-Type": "application/json; charset=utf-8"
},
onload: function (res) {
let json = JSON.parse(res.responseText);
//正常获取到参数
GM_setValue("token", json.data.token);
GM_setValue("username", data.field.username);
GM_setValue("remember", data.field.remember == "1" ? true : false);
if (data.field.remember == '1') {
GM_setValue("password", data.field.password);
} else {
GM_setValue("password", "");
}
processingReturn(json, 'login', this_)
},
onerror: function () {
layer.close(loadIndex);
layer.alert('出现错误,请重试');
}
});
return false; // 阻止默认 form 跳转
});
form.on('submit(reg-reg)', function (data) {
var field = JSON.stringify(data.field); // 获取表单字段值
// 显示填写结果,仅作演示用
GM_xmlhttpRequest({
method: "POST",
url: reg_url,
data: field,
cookie: captchaCookies,
anonymous: true,
headers: {
"Accept": "application/json",
"Content-Type": "application/json; charset=utf-8"
},
onload: function (res) {
let json = JSON.parse(res.responseText);
if (data.field.password != data.field.password2) {
layer.alert("两次密码不一致");
return false;
}
//正常获取到参数
processingReturn(json, 'reg', this)
},
onerror: function () {
layer.close(loadIndex);
layer.alert('出现错误,请重试');
}
});
return false; // 阻止默认 form 跳转
});
//处理登录验证的信息返回
function processingReturn(data, funName, element = this) {
data = data.data;
if (typeof data.code == "undefined") {
// 变量不存在
layui.alert("[0X86889]返回值不正常,可能是网络问题,请重试,多次请反馈!");
}
//登录成功处理一下信息框
if (funName == 'login' && data.code == 1) {
layer.closeAll();
layer.msg(data.msg);
return;
}
//注册成功
if (funName == 'reg' && data.code == 1) {
layer.close(regWinId);
layer.msg(data.msg);
return;
}
if (data.code == -3) {
getCaptchaData($('#getCaptchaData'));
}
layer.alert(data.msg);
}
//点击帮助
function getUpdateLog() {
let a = get("https://scriptcat.org/zh-CN/script-show-page/1397/version?_data=routes%2F%24lng%2Fscript-show-page%2F%24id%2Fversion")
a.then(resolve => {
let items = "";
$.each(resolve.list, function (index, value) {
if (value.changelog == undefined || value.changelog == "" || value.changelog == null) {
value.changelog = "作者很懒,没留下更新内容"
}
let item2 = ""
$.each(value.changelog.split("\n"), function (index2, value2) {
item2 = item2 + `<div class="layui-timeline-title">${value2}</div>`
})
let item = ` <div class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis layui-icon-face-smile"></i>
<div class="layui-timeline-content layui-text">
<div class="layui-timeline-title">${value.version}</div>
${item2}
</div>
</div>`
items = items + item;
})
help_content = help_content.replace("{items}", items);
layer.open({
type: 1,
offset: 'l',
anim: 'slideRight', // 从左往右
area: ['320px', '100%'],
shade: 0.1,
shadeClose: true,
id: 'ID-demo-layer-direction-l',
content: help_content
});
})
}
//点击用户按钮
function userBtnClick() {
//通过get函数获取验证码二进制数据
let a = get(captcha_url, true, {}, "blob");
a.then(resolve => {
var setCookieRegex = /Set-Cookie:\s*([^;\n]*)(;\s*[^;\n]*)?/ig;
var match = setCookieRegex.exec(resolve.responseHeaders)
captchaCookies = match[1];
captchaCookies = captchaCookies.replace(/^"|"$/g, '');
var baseimg = "data:image/png;base64," + btoa(resolve.responseText);
let content = login_content;
content = content.replace("{imageData}", baseimg);
if (GM_getValue("token") != undefined) {
content = success_content;
//文本替换
content = content.replace("{username}", GM_getValue("username"));
var position = $('.layui-fixbar').offset();
var mouseX = position.top - 70
var mouseY = position.left - 290
layer.open({
type: 1,
offset: [mouseX + "px", mouseY + "px"],
area: ['270px', '200px'],
title: false, // 不显示标题栏
closeBtn: 0,
shadeClose: true, // 点击遮罩关闭层
content: content
});
} else {
layer.open({
title: '用户登录',
type: 1,
//area:['370px'],
shade: 0.5,
shadeClose: true,
// area: ['520px', '340px'], // 宽高
content: content
});
if (GM_getValue("remember") == true) {
form.val('loginForm', {
"username": GM_getValue("username"),
"password": GM_getValue("password"),
"remember": true
});
}
form.render();
}
});
}
});
})();