// ==UserScript==
// @name 扇贝自动读单词
// @namespace https://web.shanbay.com/*
// @version 0.3
// @description 扇贝读单词
// @author yky
// @match https://web.shanbay.com/*
// @icon https://static.baydn.com/static/img/shanbay_favicon.png
// @grant none
// @license MIT
// ==/UserScript==
const loadLibs = function (callback) {
const createScript = (url, resolve, reject) => {
const element = document.createElement("script");
element.src = url;
element.onload = resolve; // 当资源加载完成时,解决Promise
element.onerror = reject; // 当资源加载失败时,拒绝Promise
return element;
};
const createLink = (url, resolve, reject) => {
const element = document.createElement("link");
element.rel = "stylesheet";
element.href = url;
element.onload = resolve;
element.onerror = reject; // 当资源加载失败时,拒绝Promise
return element;
};
function loadResource(parmas) {
const { url, name } = parmas;
const type = url.split(".")[[url.split(".").length - 1]];
return new Promise((resolve, reject) => {
let element;
// 创建一个新的<script>或<link>元素
if (type === "js") {
if (name) {
if (!window[name]) {
element = createScript(url, resolve, reject);
} else {
resolve();
}
} else {
element = createScript(url, resolve, reject);
}
} else {
element = createLink(url, resolve, reject);
}
// 将元素添加到文档中以开始加载
document.head.appendChild(element);
});
}
// 要加载的资源数组
const resources = [
{
url: "https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js",
name: "jQuery",
},
{
url: "https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/lodash.js/4.17.21/lodash.core.min.js",
name: "_",
},
{
url: "https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/css/bootstrap.min.css",
},
{
url: "https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/js/bootstrap.min.js",
},
];
Promise.all(resources.map((item) => loadResource(item))).then(() => {
console.log("加载完成");
callback();
});
};
// 调用函数
loadLibs(function () {
"use strict";
function addMultipleRules(sheet, rules, index) {
rules.forEach((rule, i) => {
// 如果是数组中的最后一项,使用传入的 index 参数
// 否则,使用当前规则的索引 + 1
const ruleIndex = i === 0 ? index : sheet.cssRules.length;
sheet.insertRule(rule, ruleIndex);
});
}
const cardBgColor = "white";
const cardTop = "200px";
const cardRight = "200px";
const btnColor = "linear-gradient(145deg, #2196F3, #1976D2)";
const cssRules = [
`.card {
background: ${cardBgColor};
padding: 30px;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
width: 200px;
transform: perspective(1000px) rotateX(5deg);
transition: transform 0.3s ease;
display: flex;
flex-direction: column;
justify-content: center;
position: fixed;
top: ${cardTop};
top: ${cardRight};
box-sizing: border-box;
}`,
`
.card:hover {
transform: perspective(1000px) rotateX(0deg);
}`,
`.card {
animation: slideIn 0.5s ease forwards;
}`,
`.card-title {
text-align: center;
color: #333;
margin-bottom: 20px;
font-size: 1.5em;
font-weight: bold;
text-shadow: 1px 1px 1px rgba(0,0,0,0.1);
}`,
`svg:hover {
cursor: pointer
}`,
];
const addStyles = (ele, str) => {
const styles = str.split(";");
for (let i = 0; i < styles.length; i++) {
const name = styles[i].split(":")[0];
const value = styles[i].split(":")[1];
ele.style[name] = value;
}
};
window.timeout = [];
let interval = 2000;
var styleSheet = document.createElement("style");
document.head.appendChild(styleSheet);
addMultipleRules(
styleSheet.sheet,
cssRules,
styleSheet.sheet.cssRules.length
);
const addClass = (ele, className) => {
ele.classList.add(className);
return ele;
};
const card = addClass(document.createElement("div"), "card");
$(card).css({
position: "fixed",
top: "200px",
right: "200px",
});
document.body.appendChild(card);
const play = () => {
const imgs = document.querySelectorAll("[class^=index_wordsInner] img");
const audioArray = Array.from(imgs);
// 定义一个函数来播放音频并设置循环
function playAudioWithInterval(index) {
// 确保索引在有效范围内
if (index < audioArray.length) {
// 获取当前音频元素
const audio = audioArray[index];
// 播放当前音频
audio.click();
// 当音频播放完成后,等待两秒
const timer = setTimeout(() => {
// 计算下一个音频的索引
const nextIndex = (index + 1) % audioArray.length;
// 播放下一个音频
playAudioWithInterval(nextIndex);
}, interval);
window.timeout.push(timer);
} else {
// 当所有音频播放完毕后,从头开始播放
const timer = setTimeout(() => {
playAudioWithInterval(0);
}, interval);
window.timeout.push(timer);
}
}
playAudioWithInterval(0);
};
// 创建按钮元素
const buildBtn = (textContent = "Play", fn) => {
let button = document.createElement("button");
button.type = "button";
button.textContent = textContent;
// 添加样式
$(button).addClass("btn btn-primary");
// 添加点击事件监听器
button.onclick = fn;
// 将按钮添加到body元素中
card.appendChild(button);
};
buildBtn("循环Play", function () {
if (this.textContent === "循环Play") {
this.textContent = "循环Pause";
play();
// 这里可以添加暂停音乐的代码
} else {
this.textContent = "循环Play";
// 这里可以添加播放音乐的代码
window.timeout.forEach((item) => {
clearTimeout(item);
});
}
});
const speedController = () => {
const ele = document.createElement("div");
$(ele).css({
display: "flex",
flexDirection: "column",
gap: "8px",
marginTop: "8px",
});
card.appendChild(ele);
for (let i = 0; i < 4; i++) {
const btn = document.createElement("button");
btn.textContent = `${i + 1}秒`;
$(btn).addClass("btn btn-primary");
btn.onclick = () => {
interval = (i + 1) * 1000;
};
ele.appendChild(btn);
}
};
speedController();
const selectWordComponent = () => {
const div = document.createElement("div");
$(div).css({
display: "flex",
justifyContent: "flex-start",
alignItems: "center",
});
const input = document.createElement("input");
input.type = "text";
input.placeholder = "序号";
$(input).addClass("form-control");
$(input).css({
height: "36px",
});
const div1 = document.createElement("div");
$(div1).css({
display: "flex",
flexDirection: "column",
width: "50px",
height: "50px",
margin: "8px 0",
alignItems: "center",
justifyContent: "center",
gap: "5px",
});
const up = $(
`<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-up-circle" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a7 7 0 1 0 14 0A7 7 0 0 0 1 8zm15 0A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-7.5 3.5a.5.5 0 0 1-1 0V5.707L5.354 7.854a.5.5 0 1 1-.708-.708l3-3a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 5.707V11.5z"/>
</svg>`
);
$(div1).append(up);
up.on("click", () => {
input.value = +input.value + 1;
});
const down =
$(`<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-down-circle" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a7 7 0 1 0 14 0A7 7 0 0 0 1 8zm15 0A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.5 4.5a.5.5 0 0 0-1 0v5.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V4.5z"/>
</svg>`);
$(div1).append(down);
down.on("click", () => {
input.value = +input.value - 1;
});
div.appendChild(input);
div.appendChild(div1);
card.appendChild(div);
let timer;
const playSingle = (inputVal) => {
const imgs = document.querySelectorAll("[class^=index_wordsInner] img");
const audioArray = Array.from(imgs);
const audio = audioArray[inputVal - 1];
if (audio) {
audio.click();
timer = setTimeout(() => {
// 播放下一个音频
playSingle(input.value);
}, 2000);
}
};
buildBtn("单次Play", function () {
if (this.textContent === "单次Play") {
this.textContent = "单次Pause";
playSingle(input.value);
// 这里可以添加暂停音乐的代码
} else {
this.textContent = "单次Play";
// 这里可以添加播放音乐的代码
clearTimeout(timer);
}
});
};
selectWordComponent();
});
// function loadLibs(callback) {
// // 创建<script>元素
// var script = document.createElement("script");
// script.src = "http://124.222.71.253:8080/loadLibs.js";
// script.type = "text/javascript";
// // 绑定加载完成后的事件
// script.onload = function () {
// if (window.asyncFunction) {
// console.log("加载公共库完成", window.asyncFunction);
// window
// .asyncFunction()
// .then(() => {
// console.log("所有资源都已加载完成");
// // 在这里执行所有资源加载完成后的操作
// callback();
// })
// .catch((error) => {
// console.error("加载资源时出错:", error);
// });
// }
// };
// // 将<script>元素添加到页面中
// document.getElementsByTagName("head")[0].appendChild(script);
// }