From a476f5224632e48b82cfe715112676f0db44f40b Mon Sep 17 00:00:00 2001 From: MrSuM Date: Fri, 6 Jun 2025 16:10:17 +0800 Subject: [PATCH 1/5] =?UTF-8?q?refactor(waitForElement):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20waitForElement=20=E5=87=BD=E6=95=B0=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 增加对元素是否已存在的判断 - 如果元素已存在,则直接返回该元素 - 如果元素不存在,则继续使用 MutationObserver 监听 --- ...350\257\204\346\225\231\350\204\232\346\234\254.user.js" | 6 ++++++ 1 file changed, 6 insertions(+) diff --git "a/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" "b/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" index 37e9428..4ca932a 100644 --- "a/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" +++ "b/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" @@ -21,10 +21,16 @@ // 等待元素加载 function waitForElement(selector) { return new Promise(resolve => { + const element = document.querySelector(selector); + if (element) { + resolve(element); + } + else { const observer = new MutationObserver(() => { const element = document.querySelector(selector); if (element) { observer.disconnect(); + } resolve(element); } }); -- Gitee From 2f3ccc1128f2b4259ae4eb7339d7138549d6327a Mon Sep 17 00:00:00 2001 From: MrSuM Date: Fri, 6 Jun 2025 16:12:59 +0800 Subject: [PATCH 2/5] =?UTF-8?q?refactor(xauat=E8=87=AA=E5=8A=A8=E8=AF=84?= =?UTF-8?q?=E6=95=99=E8=84=9A=E6=9C=AC):=20=E9=87=8D=E6=9E=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=B9=B6=E4=BC=98=E5=8C=96=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增元素配置和全局配置,提高代码可维护性 - 分离即时性评教和总结性评教逻辑,增强代码清晰度 - 优化路由处理,提高脚本执行效率 - 添加配置项控制脚本运行状态,提升用户体验 --- ...6\225\231\350\204\232\346\234\254.user.js" | 193 ++++++++++-------- 1 file changed, 105 insertions(+), 88 deletions(-) diff --git "a/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" "b/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" index 4ca932a..c4222cb 100644 --- "a/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" +++ "b/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" @@ -13,6 +13,21 @@ console.log('xauat自动评教脚本-1.2'); + // 元素配置 + const appSelector = '#app'; + const itemSelector = '.item'; + const radioSelector = 'input.el-radio__original'; + const checkboxSelector = 'input.el-checkbox__original'; + const textareaSelector = 'textarea.el-textarea__inner'; + const submitBtnSelector = 'button.el-button.el-button--primary.el-button--small'; + const timelySurveySelector = 'button.el-button.el-button--primary.el-button--mini.is-plain.is-round.borderhalf'; + const byTaskSelector = 'a.el-tooltip.el-link.el-link--primary.is-underline'; + + var config = { + is_running: true, + current_route: '/', + } + // 延迟函数 function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); @@ -26,122 +41,121 @@ resolve(element); } else { - const observer = new MutationObserver(() => { - const element = document.querySelector(selector); - if (element) { - observer.disconnect(); + const observer = new MutationObserver(() => { + const element = document.querySelector(selector); + if (element) { + observer.disconnect(); + + resolve(element); + } + }); + + observer.observe(document.body, { childList: true, subtree: true }); } - resolve(element); + }); + } + + // 即时性评教答题填写 + async function solveTimelySurvey() { + const items = document.querySelectorAll(itemSelector); + for (let item of items) { + let option_count = 0; + const options = item.querySelectorAll('label.el-checkbox'); + + for (let option of options) { + const checkbox = option.querySelector(checkboxSelector); + if (checkbox && !checkbox.checked) { + checkbox.click(); + // console.log(`选项 ${checkbox.value} 已选中`); } - }); + await sleep(1); + if (++option_count >= 3) break; + } + } - observer.observe(document.body, { childList: true, subtree: true }); - }); + const textarea = document.querySelector(textareaSelector); + if (textarea) { + textarea.value = '这个老师真棒!'; + textarea.dispatchEvent(new Event('input', { bubbles: true })); + // console.log('已填写评教内容'); + } + + const submitBtn = document.querySelector(submitBtnSelector); + if (submitBtn) { + // submitBtn.click(); + // console.log('提交按钮点击成功'); + } } + // 总性性评教答题填写 + async function solveTSurvey() { + const items = document.querySelectorAll(itemSelector); + for (let item of items) { + const option = item.querySelector(radioSelector); + if (option) { + option.click(); + // console.log(`选项 ${option.value} 已选中`); + } + + const textarea = item.querySelector(textareaSelector); + if (textarea) { + textarea.value = '这个老师真棒!'; + textarea.dispatchEvent(new Event('input', { bubbles: true })); + // console.log('已填写评教内容'); + } + + await sleep(1); + } + + const submitBtn = document.querySelector(submitBtnSelector); + if (submitBtn) { + submitBtn.click(); + // console.log('提交按钮点击成功'); + } + } + + // 路由处理 const route_handler = { - // 即时性评教答题 + // 即时性评教答题页面 '/timelySurvey': async function () { try { - await waitForElement('.item'); - console.log('开始自动评教'); - - const items = document.querySelectorAll('.item'); - for (let item of items) { - let option_count = 0; - const options = item.querySelectorAll('label.el-checkbox'); - - for (let option of options) { - const checkbox = option.querySelector('input.el-checkbox__original'); - if (checkbox && !checkbox.checked) { - checkbox.click(); - console.log(`选项 ${checkbox.value} 已选中`); - } - await sleep(1); - if (++option_count >= 3) break; - } - } - - const textarea = document.querySelector('textarea.el-textarea__inner'); - if (textarea) { - textarea.value = '这个老师真棒!'; - textarea.dispatchEvent(new Event('input', { bubbles: true })); - console.log('已填写评教内容'); - } - - const submitBtn = document.querySelector('.el-button.el-button--primary.el-button--small'); - if (submitBtn) { - submitBtn.click(); - console.log('提交按钮点击成功'); + if (config.is_running) { + await waitForElement(itemSelector).then(solveTimelySurvey); } - - console.log('评教完成并提交'); } catch (e) { console.error('/timelySurvey 出错:', e); } }, - // 自动进入即时性评教页面 + // 即时性评教选择页面 '/timely-evaluation/myparticipate': async function () { try { - const linksSelector = 'button.el-button.el-button--primary.el-button--mini.is-plain.is-round.borderhalf'; - await waitForElement(linksSelector); - - const btn = document.querySelector(linksSelector); - if (btn) { - btn.click(); - console.log('已点击评教按钮'); + if (config.is_running) { + await waitForElement(timelySurveySelector).then((element) => { + element.click(); + }); } } catch (e) { console.error('/timely-evaluation/myparticipate 出错:', e); } }, - // 自动进入总结性评教页面 + // 总结性评教选择页面 '/byTask': async function () { try { - const linksSelector = 'a.el-tooltip.el-link.el-link--primary.is-underline'; - await waitForElement(linksSelector); - - // await sleep(1000); // TODO: 触发服务器限流(访问太过频繁,休息,休息一下!) - - const btn = document.querySelector(linksSelector); - if (btn) { - btn.click(); - console.log('已点击评教按钮'); + if (config.is_running) { + await waitForElement(byTaskSelector).then((element) => { + // await sleep(1000); // TODO: 触发服务器限流(访问太过频繁,休息,休息一下!) + element.click(); + }); } } catch (e) { console.error('/byTask 出错:', e); } }, - // 总结性评教答题 + // 总结性评教答题页面 '/tSurvey': async function () { try { - await waitForElement('.item'); - console.log('开始自动评教'); - - - const items = document.querySelectorAll('.item'); - for (let item of items) { - const option = item.querySelector('input.el-radio__original'); - if (option) { - option.click(); - console.log(`选项 ${option.value} 已选中`); - } - - const textarea = item.querySelector('textarea.el-textarea__inner'); - if (textarea) { - textarea.value = '这个老师真棒!'; - textarea.dispatchEvent(new Event('input', { bubbles: true })); - console.log('已填写评教内容'); - } - - await sleep(1); - } - - const submitBtn = document.querySelector('.el-button.el-button--primary.el-button--small'); - if (submitBtn) { - // console.log(submitBtn); - submitBtn.click(); - console.log('提交按钮点击成功'); + if (config.is_running) { + await waitForElement(itemSelector).then(solveTSurvey); } } catch (e) { console.error('/tSurvey 出错:', e); @@ -160,10 +174,13 @@ appVue.$router.afterHooks.push((to, from) => { console.log('路由切换:', from.path, '->', to.path); + console.log(config); + config.current_route = to.path; for (const key in route_handler) { if (to.path.startsWith(key)) { - console.log('匹配到路由:', key); + // console.log('匹配到路由:', key); route_handler[key](); + break; } } }); -- Gitee From 5292439a6cb6be5488ca0424568d898259428bb3 Mon Sep 17 00:00:00 2001 From: MrSuM Date: Fri, 6 Jun 2025 16:27:29 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat(xauat):=20=E6=B7=BB=E5=8A=A0=E6=82=AC?= =?UTF-8?q?=E6=B5=AE=E7=AA=97=20UI=20=E7=94=A8=E4=BA=8E=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E8=AF=84=E6=95=99=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...6\225\231\350\204\232\346\234\254.user.js" | 64 ++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git "a/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" "b/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" index c4222cb..93a12d8 100644 --- "a/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" +++ "b/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" @@ -174,11 +174,9 @@ appVue.$router.afterHooks.push((to, from) => { console.log('路由切换:', from.path, '->', to.path); - console.log(config); config.current_route = to.path; for (const key in route_handler) { if (to.path.startsWith(key)) { - // console.log('匹配到路由:', key); route_handler[key](); break; } @@ -189,8 +187,70 @@ } } + // 配置UI + function setupUI() { + // 创建悬浮窗容器 + const container = document.createElement('div'); + container.style.position = 'fixed'; + container.style.top = '20px'; + container.style.right = '20px'; + container.style.backgroundColor = '#fff'; + container.style.padding = '10px'; + container.style.border = '1px solid #ccc'; + container.style.borderRadius = '5px'; + container.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.1)'; + container.style.zIndex = '9999'; + container.style.display = 'flex'; + container.style.flexDirection = 'column'; + container.style.alignItems = 'flex-start'; + + // 创建按钮 + const button_run = document.createElement('button'); + button_run.textContent = config.is_running ? '停止评教' : '开始评教'; + button_run.style.marginBottom = '10px'; + button_run.style.padding = '5px 10px'; + button_run.style.cursor = 'pointer'; + + // 创建状态标签 + const label_status = document.createElement('label'); + label_status.textContent = config.is_running ? '状态:评教中' : '状态:已停止'; + label_status.style.fontSize = '14px'; + label_status.style.color = config.is_running ? 'green' : 'red'; + + // 添加点击事件 + button_run.addEventListener('click', async () => { + config.is_running = !config.is_running; + + // 更新按钮文本 + button_run.textContent = config.is_running ? '停止评教' : '开始评教'; + + // 更新状态标签 + label_status.textContent = config.is_running ? '状态:评教中' : '状态:已停止'; + label_status.style.color = config.is_running ? 'green' : 'red'; + + if (config.is_running) { + for (const key in route_handler) { + if (config.current_route.startsWith(key)) { + console.log('匹配到路由:', key); + await route_handler[key](); + break; + } + } + } + }); + + // 将按钮和标签添加到容器 + container.appendChild(button_run); + container.appendChild(label_status); + + // 将容器添加到 body + document.body.appendChild(container); + console.log('已添加悬浮窗', container); + } + // 初始化 (async () => { setupRouteHook(); + setupUI(); })(); })(); \ No newline at end of file -- Gitee From 27b41e52d3cffbf5ba6fd1ab8c94e5fb33ec0fc2 Mon Sep 17 00:00:00 2001 From: MrSuM Date: Fri, 6 Jun 2025 16:41:38 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=A6=96?= =?UTF-8?q?=E9=A1=B5=E8=B7=AF=E7=94=B1=E5=A4=84=E7=90=86=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在路由处理中添加对其他路由的处理,用于跳转到页面 - 取消注释提交按钮点击逻辑 - 增加路由匹配日志输出,便于调试 --- ...\346\225\231\350\204\232\346\234\254.user.js" | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git "a/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" "b/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" index 93a12d8..11d44e6 100644 --- "a/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" +++ "b/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" @@ -82,7 +82,7 @@ const submitBtn = document.querySelector(submitBtnSelector); if (submitBtn) { - // submitBtn.click(); + submitBtn.click(); // console.log('提交按钮点击成功'); } } @@ -160,6 +160,19 @@ } catch (e) { console.error('/tSurvey 出错:', e); } + }, + // 其他 + '/': async function () { + try { + if (config.is_running) { + // const a = document.createElement('a'); + // a.href = '#/timely-evaluation/myparticipate'; + // a.click(); + window.location.href = '#/timely-evaluation/myparticipate'; + } + } catch (e) { + console.error('/ 出错:', e); + } } }; @@ -177,6 +190,7 @@ config.current_route = to.path; for (const key in route_handler) { if (to.path.startsWith(key)) { + console.log('匹配到路由:', key); route_handler[key](); break; } -- Gitee From 7b1ba2cb0c72fa06443c6e80905f95441ef3599a Mon Sep 17 00:00:00 2001 From: MrSuM Date: Fri, 6 Jun 2025 16:50:13 +0800 Subject: [PATCH 5/5] =?UTF-8?q?feat(xauat=E8=AF=84=E6=95=99):=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=AF=84=E6=95=99=E5=AE=8C=E6=88=90=E6=8F=90=E9=86=92?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 增加即时性评教和总结性评教完成后的提醒 - 添加 UI 全局变量并实现动态更新 - 优化等待元素加载的函数,增加超时设置 --- ...6\225\231\350\204\232\346\234\254.user.js" | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git "a/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" "b/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" index 11d44e6..a604df4 100644 --- "a/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" +++ "b/xauat\350\207\252\345\212\250\350\257\204\346\225\231\350\204\232\346\234\254.user.js" @@ -28,24 +28,31 @@ current_route: '/', } + var ui = {}; + // 延迟函数 function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // 等待元素加载 - function waitForElement(selector) { + function waitForElement(selector, timeout = 5000) { return new Promise(resolve => { const element = document.querySelector(selector); if (element) { resolve(element); } else { + const t = setTimeout(() => { + observer.disconnect(); + resolve(null); + }, timeout); + const observer = new MutationObserver(() => { const element = document.querySelector(selector); if (element) { observer.disconnect(); - + clearTimeout(t); resolve(element); } }); @@ -131,7 +138,15 @@ try { if (config.is_running) { await waitForElement(timelySurveySelector).then((element) => { - element.click(); + if (element) { + element.click(); + } + else { + config.is_running = false; + updateUI(); + + alert('即时性评教完成!'); + } }); } } catch (e) { @@ -144,7 +159,15 @@ if (config.is_running) { await waitForElement(byTaskSelector).then((element) => { // await sleep(1000); // TODO: 触发服务器限流(访问太过频繁,休息,休息一下!) - element.click(); + if (element) { + element.click(); + } + else { + config.is_running = false; + updateUI(); + + alert('总结性评教完成!'); + } }); } } catch (e) { @@ -253,6 +276,11 @@ } }); + // ui全局变量 + ui.container = container; + ui.button_run = button_run; + ui.label_status = label_status; + // 将按钮和标签添加到容器 container.appendChild(button_run); container.appendChild(label_status); @@ -262,6 +290,13 @@ console.log('已添加悬浮窗', container); } + // 更新ui + function updateUI() { + ui.button_run.textContent = config.is_running ? '停止评教' : '开始评教'; + ui.label_status.textContent = config.is_running ? '状态:评教中' : '状态:已停止'; + ui.label_status.style.color = config.is_running ? 'green' : 'red'; + } + // 初始化 (async () => { setupRouteHook(); -- Gitee