// ==UserScript== // @name Search Mixer // @name:zh-CN 搜索聚合 // @name:zh-TW 搜索聚合 // @license GPL-3.0 License // @namespace https://github.com/Yukari0201/UserScript // @supportURL https://github.com/Yukari0201/UserScript // @homepageURL https://github.com/Yukari0201/UserScript // @version 0.1.3 // @description Quick search by selection + Search engine sidebar // @description:zh-CN 划词快速搜索 + 搜索引擎侧边栏 // @description:zh-TW 劃詞快速搜索 + 搜索引擎側邊欄 // @author Yukari0201 // @match *://*/* // @require https://unpkg.com/vue@3/dist/vue.global.prod.js // @require data:application/javascript,unsafeWindow.Vue%3DVue%2Cthis.Vue%3DVue%3B // @require https://unpkg.com/element-plus // @require https://unpkg.com/@element-plus/icons-vue // @resource ELEMENT_CSS https://unpkg.com/element-plus/dist/index.css // @connect raw.githubusercontent.com // @connect jsdelivr.net // @connect gh-proxy.org // @grant unsafeWindow // @grant GM_getResourceText // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_xmlhttpRequest // @icon data:image/png;base64,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 // @run-at document-end // @downloadURL https://update.greasyfork.icu/scripts/574563/Search%20Mixer.user.js // @updateURL https://update.greasyfork.icu/scripts/574563/Search%20Mixer.meta.js // ==/UserScript== (function () { "use strict"; // Default config const DEFAULT_CONFIG = { icon: { anchor: "bottom-right", // top-left | top-right | bottom-left | bottom-right offsetX: 10, offsetY: 10, }, rule: { update: true, updateInterval: 24 * 60 * 60 * 1000, // 24 hours defaultIndex: 0, }, ui: { sideBtnPosition: "right", // left | right drawerPosition: "rtl", // rtl | ltr | ttb | btt }, }; let config = GM_getValue("config"); if (!config || typeof config !== "object") { GM_setValue("config", DEFAULT_CONFIG); config = DEFAULT_CONFIG; } // rules URL const RULES_URL = [ "https://raw.githubusercontent.com/Yukari0201/UserScript/refs/heads/main/rules/search-mixer/rules_v1.0.json", "https://cdn.jsdelivr.net/gh/Yukari0201/UserScript@refs/heads/main/rules/search-mixer/rules_v1.0.json", "https://gcore.jsdelivr.net/gh/Yukari0201/UserScript@refs/heads/main/rules/search-mixer/rules_v1.0.json", "https://fastly.jsdelivr.net/gh/Yukari0201/UserScript@refs/heads/main/rules/search-mixer/rules_v1.0.json", "https://testingcf.jsdelivr.net/gh/Yukari0201/UserScript@refs/heads/main/rules/search-mixer/rules_v1.0.json", "https://gh-proxy.org/https://raw.githubusercontent.com/Yukari0201/UserScript/refs/heads/main/rules/search-mixer/rules_v1.0.json", "https://hk.gh-proxy.org/https://raw.githubusercontent.com/Yukari0201/UserScript/refs/heads/main/rules/search-mixer/rules_v1.0.json", "https://cdn.gh-proxy.org/https://raw.githubusercontent.com/Yukari0201/UserScript/refs/heads/main/rules/search-mixer/rules_v1.0.json", "https://edgeone.gh-proxy.org/https://raw.githubusercontent.com/Yukari0201/UserScript/refs/heads/main/rules/search-mixer/rules_v1.0.json", ]; // Default rules const DEFAULT_RULE = { lastUpdate: 0, rules: [ { name: "Google", icon: "https://www.google.com/favicon.ico", url: "https://www.google.com/", searchPrefix: "https://www.google.com/search?q=", }, ], }; let rule = GM_getValue("rule"); if (!rule || typeof rule !== "object") { GM_setValue("rule", DEFAULT_RULE); rule = DEFAULT_RULE; } const fetchRule = (url) => { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: url, timeout: 5000, responseType: "json", onload: (response) => { if (response.status === 200 && response.response) { resolve(response.response); } else { reject(`Status: ${response.status}`); } }, onerror: (err) => reject("Network Error"), ontimeout: () => reject("Timeout"), }); }); }; const updateRules = async () => { const now = new Date().getTime(); // 检查是否开启更新及是否到达间隔时间 if ( config.rule.update && now - rule.lastUpdate > config.rule.updateInterval ) { console.log("Search Mixer: 正在尝试从远程更新规则..."); for (const url of RULES_URL) { try { const rulesArr = await fetchRule(url); // 更新本地数据 rule.lastUpdate = new Date().getTime(); rule.rules = rulesArr; GM_setValue("rule", rule); console.log(`Search Mixer: 规则更新成功! 来源: ${url}`); return; // 成功后立即跳出 } catch (error) { console.warn(`Search Mixer: 尝试从 ${url} 更新失败: ${error}`); } } console.error("Search Mixer: 所有预设的规则地址均无法访问。"); } }; updateRules(); // Vue & Element Plus const { ElMessageBox } = ElementPlus; const elementPlusCss = GM_getResourceText("ELEMENT_CSS"); GM_addStyle(elementPlusCss); GM_addStyle(` html, body { margin: 0; padding: 0; } #search-mixer-app-container { position: fixed; ${config.ui.sideBtnPosition}: 10px; top: 0; height: 100vh; display: flex; align-items: center; z-index: 1000; pointer-events: none; /* 使容器不干扰页面的其他元素 */ } #search-mixer-app { pointer-events: auto; /* 恢复应用的可点击性 */ } .btn-container { display: flex; flex-direction: column; gap: 15px; } #search-mixer-app .btn { margin-left: 0px !important; /* 去除默认的 margin-left */ width: 40px !important; /* 固定宽度 */ height: 40px !important; /* 固定高度 */ padding: 0 !important; /* 去除默认的 padding */ } .drawer { pointer-events: auto; } .search-input-wrapper { position: sticky; top: 0; z-index: 100; background-color: #ffffff; padding: 15px 0; margin-bottom: 10px; border-bottom: 1px solid var(--el-border-color-lighter); } .search-card-container { display: flex; flex-direction: column; gap: 12px; } .search-engine-card { cursor: pointer; transition: transform 0.2s, box-shadow 0.2s; border-radius: 8px !important; } .search-engine-card:hover { transform: translateX(-4px); /* 悬停时向左轻微位移 */ border-color: var(--el-color-primary-light-5); } .search-card-content { display: flex; align-items: center; gap: 12px; } .engine-icon-wrapper { width: 32px; height: 32px; flex-shrink: 0; } .engine-icon-wrapper img { width: 100%; height: 100%; } .engine-info { display: flex; flex-direction: column; overflow: hidden; /* 防止 URL 过长溢出 */ } .engine-name { font-size: 14px; font-weight: 600; line-height: 1.2; } .engine-url { font-size: 12px; color: #999; margin-top: 4px; /* 强制单行并显示省略号 */ display: block; width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* 默认引擎卡片的高亮样式 */ .search-engine-card.is-default { border: 1.5px solid var(--el-color-primary-light-3) !important; background-color: var(--el-color-primary-light-9) !important; } /* 调整输入框内选择器的宽度 */ .el-form-item .el-select { width: 100%; } .quick-search-btn { position: fixed; z-index: 999999; width: 28px; height: 28px; padding: 4px; background: #fff; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.15); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: transform 0.1s; } .quick-search-btn:hover { transform: scale(1.1); background: var(--el-color-primary-light-9); } .quick-search-btn img { width: 20px; height: 20px; object-fit: contain; } `); let text = `
search
`; var div = document.createElement("div"); div.innerHTML = text; document.body.append(div); const App = { data() { return { searchDrawer: false, settingDrawer: false, direction: config.ui.drawerPosition, localConfig: JSON.parse(JSON.stringify(config)), // 深拷贝配置对象 ruleData: rule, // 规则数据 currentSearchText: "", // 当前搜索框中的文本 showQuickBtn: false, quickBtnStyle: { top: "0px", left: "0px", }, quickIcon: rule.rules[config.rule.defaultIndex].icon || "data:image/png;base64,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", }; }, mounted() { // 全局监听鼠标抬起 document.addEventListener("mouseup", this.handleMouseUp); // 滚动或点击其他地方时隐藏按钮 document.addEventListener("mousedown", (e) => { if (!e.target.closest(".quick-search-btn")) { this.showQuickBtn = false; } }); }, methods: { handleSearchClick() { this.searchDrawer = true; }, handleSearchClose() { this.currentSearchText = ""; // 关闭抽屉时清空当前选择 }, openSearch(engine) { // 判断 currentSearchText 是否非空 const query = this.currentSearchText ? this.currentSearchText.trim() : ""; if (query.length > 0) { // 有内容,拼搜索地址 const searchUrl = engine.searchPrefix + encodeURIComponent(query); window.open(searchUrl, "_blank"); } else { // 为空,跳转主页 window.open(engine.url, "_blank"); } }, onDrawerOpened() { if (this.$refs.searchInput) { this.$refs.searchInput.focus(); } }, handleEnterSearch() { const idx = this.localConfig.rule.defaultIndex || 0; const defaultEngine = this.ruleData.rules[idx]; if (defaultEngine) { this.openSearch(defaultEngine); } }, handleSettingClick() { this.settingDrawer = true; }, handleSettingClose(done) { ElMessageBox.confirm("Are you sure you want to close?") .then(() => { done(); }) .catch(() => { // catch error }); }, cancelClick() { ElMessageBox.confirm("Are you sure you want to close?") .then(() => { this.settingDrawer = false; this.localConfig = JSON.parse(JSON.stringify(config)); // 恢复配置 }) .catch(() => { // catch error }); }, confirmClick() { // 保存到本地 GM_setValue("config", this.localConfig); ElMessageBox.alert( "配置已保存,部分设置可能需要刷新页面生效。", "提示", { confirmButtonText: "确定", callback: () => { location.reload(); // 或者根据需要手动更新 config 对象 }, }, ); }, resetToDefault() { ElMessageBox.confirm("确定要恢复默认设置吗?").then(() => { this.localConfig = JSON.parse(JSON.stringify(DEFAULT_CONFIG)); }); }, handleMouseUp(e) { // 延迟一丢丢,确保 getSelection 能抓到最新的 setTimeout(() => { const selection = window.getSelection(); const text = selection.toString().trim(); if (text && text.length > 0) { const range = selection.getRangeAt(0); const rect = range.getBoundingClientRect(); // 根据 config 中的锚点逻辑计算位置 this.calculatePosition(rect); this.currentSelection = text; this.showQuickBtn = true; } else { this.showQuickBtn = false; } }, 10); }, calculatePosition(rect) { const { anchor, offsetX, offsetY } = config.icon; let top, left; // 基础逻辑:以选区矩形为基准 switch (anchor) { case "top-left": top = rect.top - 30 - offsetY; left = rect.left - offsetX; break; case "top-right": top = rect.top - 30 - offsetY; left = rect.right + offsetX; break; case "bottom-left": top = rect.bottom + offsetY; left = rect.left - offsetX; break; case "bottom-right": default: top = rect.bottom + offsetY; left = rect.right + offsetX; break; } this.quickBtnStyle = { top: `${top}px`, left: `${left}px`, }; }, handleQuickSearch() { const idx = this.localConfig.rule.defaultIndex || 0; const engine = this.ruleData.rules[idx]; if (engine && this.currentSelection) { const searchUrl = engine.searchPrefix + encodeURIComponent(this.currentSelection); window.open(searchUrl, "_blank"); this.showQuickBtn = false; // 点击后消失 } }, }, }; const app = Vue.createApp(App); app.use(ElementPlus); for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component); } app.mount("#search-mixer-app"); })();