岐黄天使刷课助手 - 远程同步模块

岐黄天使刷课助手的远程同步模块,负责与远程服务器同步题库和配置信息。

当前为 2025-05-24 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/537078/1594817/%E5%B2%90%E9%BB%84%E5%A4%A9%E4%BD%BF%E5%88%B7%E8%AF%BE%E5%8A%A9%E6%89%8B%20-%20%E8%BF%9C%E7%A8%8B%E5%90%8C%E6%AD%A5%E6%A8%A1%E5%9D%97.js

  1. // ==UserScript==
  2. // @name 岐黄天使刷课助手 - 远程同步模块
  3. // @namespace http://tampermonkey.net/qhtx-modules
  4. // @version 1.3.0
  5. // @description 岐黄天使刷课助手的远程同步模块,负责与远程服务器同步题库和配置信息。
  6. // @author AI助手
  7. // ==/UserScript==
  8.  
  9. // 远程同步模块
  10. (function() {
  11. 'use strict';
  12.  
  13. // 同步远程题库
  14. window.syncRemoteQuestionBank = function() {
  15. // 如果已经在同步中,则不重复执行
  16. if (window.qh.isSyncing) {
  17. console.log('题库同步已在进行中,跳过本次同步');
  18. return;
  19. }
  20.  
  21. // 检查是否启用远程题库
  22. if (!window.qh.remoteQuestionBankConfig.enabled) {
  23. console.log('远程题库功能未启用,跳过同步');
  24. return;
  25. }
  26.  
  27. // 检查是否需要同步(根据上次同步时间和同步间隔)
  28. const now = Date.now();
  29. const lastSyncTime = window.qh.remoteQuestionBankConfig.lastSyncTime || 0;
  30. const syncInterval = window.qh.remoteQuestionBankConfig.syncInterval || 3600000; // 默认1小时
  31.  
  32. if (now - lastSyncTime < syncInterval) {
  33. console.log('距离上次同步时间不足,跳过本次同步');
  34. return;
  35. }
  36.  
  37. // 设置同步状态
  38. window.qh.isSyncing = true;
  39. updateStatus('正在同步远程题库...');
  40.  
  41. // 获取远程题库
  42. fetchRemoteQuestionBank();
  43. };
  44.  
  45. // 获取远程题库
  46. function fetchRemoteQuestionBank(retryCount = 0) {
  47. try {
  48. const url = window.qh.remoteQuestionBankConfig.url;
  49. if (!url) {
  50. console.error('远程题库URL未设置');
  51. window.qh.isSyncing = false;
  52. updateStatus('远程题库URL未设置');
  53. return;
  54. }
  55.  
  56. console.log('开始获取远程题库:', url);
  57.  
  58. // 检查是否为HTTPS页面访问HTTP资源(混合内容问题)
  59. const isHttpsPage = window.location.protocol === 'https:';
  60. const isHttpResource = url.startsWith('http:');
  61.  
  62. if (isHttpsPage && isHttpResource) {
  63. console.log('检测到混合内容问题,尝试使用本地存储的题库');
  64.  
  65. // 如果有本地题库,直接使用
  66. if (window.qh.savedQuestionBank && window.qh.savedQuestionBank.length > 0) {
  67. console.log('使用本地题库,题目数量:', window.qh.savedQuestionBank.length);
  68.  
  69. // 更新同步时间
  70. window.qh.remoteQuestionBankConfig.lastSyncTime = Date.now();
  71. GM_setValue('qh-remote-question-bank-config', window.qh.remoteQuestionBankConfig);
  72.  
  73. // 更新状态
  74. updateStatus(`使用本地题库,共 ${window.qh.savedQuestionBank.length} 道题目`);
  75.  
  76. // 重置同步状态
  77. window.qh.isSyncing = false;
  78. return;
  79. }
  80.  
  81. // 如果没有本地题库,提示用户
  82. console.warn('由于HTTPS安全限制,无法从HTTP服务器获取题库');
  83. updateStatus('由于安全限制,无法从HTTP服务器获取题库');
  84. window.qh.isSyncing = false;
  85. return;
  86. }
  87.  
  88. // 使用fetch API获取远程题库
  89. fetch(url)
  90. .then(response => {
  91. if (!response.ok) {
  92. throw new Error('网络响应不正常: ' + response.status);
  93. }
  94. return response.json();
  95. })
  96. .then(data => {
  97. console.log('成功获取远程题库,题目数量:', data.length);
  98. mergeQuestionBanks(data);
  99. })
  100. .catch(error => {
  101. console.error('获取远程题库失败:', error);
  102.  
  103. // 如果是混合内容错误,尝试使用本地题库
  104. if (error.message && (
  105. error.message.includes('Mixed Content') ||
  106. error.message.includes('blocked:mixed') ||
  107. error.message.includes('Failed to fetch')
  108. )) {
  109. console.log('检测到混合内容错误,尝试使用本地题库');
  110.  
  111. // 如果有本地题库,直接使用
  112. if (window.qh.savedQuestionBank && window.qh.savedQuestionBank.length > 0) {
  113. console.log('使用本地题库,题目数量:', window.qh.savedQuestionBank.length);
  114.  
  115. // 更新同步时间
  116. window.qh.remoteQuestionBankConfig.lastSyncTime = Date.now();
  117. GM_setValue('qh-remote-question-bank-config', window.qh.remoteQuestionBankConfig);
  118.  
  119. // 更新状态
  120. updateStatus(`使用本地题库,共 ${window.qh.savedQuestionBank.length} 道题目`);
  121.  
  122. // 重置同步状态
  123. window.qh.isSyncing = false;
  124. return;
  125. }
  126. }
  127.  
  128. // 重试逻辑
  129. const maxRetries = window.qh.remoteQuestionBankConfig.maxRetries || 3;
  130. const retryDelay = window.qh.remoteQuestionBankConfig.retryDelay || 5000;
  131.  
  132. if (retryCount < maxRetries) {
  133. console.log(`将在 ${retryDelay/1000} 秒后进行第 ${retryCount + 1} 次重试`);
  134. updateStatus(`远程题库同步失败,将在 ${retryDelay/1000} 秒后重试...`);
  135.  
  136. setTimeout(() => {
  137. fetchRemoteQuestionBank(retryCount + 1);
  138. }, retryDelay);
  139. } else {
  140. console.error(`已达到最大重试次数 ${maxRetries},同步失败`);
  141. window.qh.isSyncing = false;
  142. updateStatus('远程题库同步失败,请检查网络连接');
  143. }
  144. });
  145. } catch (e) {
  146. console.error('获取远程题库出错:', e);
  147. window.qh.isSyncing = false;
  148. updateStatus('远程题库同步出错: ' + e.message);
  149. }
  150. }
  151.  
  152. // 合并题库
  153. function mergeQuestionBanks(remoteQuestions) {
  154. try {
  155. if (!remoteQuestions || !Array.isArray(remoteQuestions)) {
  156. console.error('远程题库格式不正确');
  157. window.qh.isSyncing = false;
  158. updateStatus('远程题库格式不正确');
  159. return;
  160. }
  161.  
  162. // 统计新增和更新的题目数量
  163. let newCount = 0;
  164. let updatedCount = 0;
  165.  
  166. // 合并题库
  167. remoteQuestions.forEach(remoteQuestion => {
  168. // 检查题目是否已存在
  169. const existingIndex = window.qh.savedQuestionBank.findIndex(q => q.id === remoteQuestion.id);
  170.  
  171. if (existingIndex === -1) {
  172. // 新题目
  173. window.qh.savedQuestionBank.push(remoteQuestion);
  174. newCount++;
  175. } else {
  176. // 更新已有题目
  177. const existingQuestion = window.qh.savedQuestionBank[existingIndex];
  178.  
  179. // 只有在远程题目有答案且本地题目没有答案,或者远程题目更新时间更新时才更新
  180. if ((!existingQuestion.answer && remoteQuestion.answer) ||
  181. (remoteQuestion.updateTime && (!existingQuestion.updateTime || remoteQuestion.updateTime > existingQuestion.updateTime))) {
  182. window.qh.savedQuestionBank[existingIndex] = remoteQuestion;
  183. updatedCount++;
  184. }
  185. }
  186. });
  187.  
  188. // 保存合并后的题库
  189. GM_setValue('qh-question-bank', window.qh.savedQuestionBank);
  190.  
  191. // 更新同步时间
  192. window.qh.remoteQuestionBankConfig.lastSyncTime = Date.now();
  193. GM_setValue('qh-remote-question-bank-config', window.qh.remoteQuestionBankConfig);
  194.  
  195. // 更新状态
  196. console.log(`题库同步完成: 新增 ${newCount} 道题目, 更新 ${updatedCount} 道题目, 总计 ${window.qh.savedQuestionBank.length} 道题目`);
  197. updateStatus(`题库同步完成: 新增 ${newCount} 道题目, 更新 ${updatedCount} 道题目`);
  198.  
  199. // 更新题库状态显示
  200. const statusElement = document.getElementById('qh-question-status');
  201. if (statusElement) {
  202. statusElement.textContent = `题库状态: 已保存 ${window.qh.savedQuestionBank.length} 道题目`;
  203. }
  204.  
  205. // 重置同步状态
  206. window.qh.isSyncing = false;
  207. } catch (e) {
  208. console.error('合并题库出错:', e);
  209. window.qh.isSyncing = false;
  210. updateStatus('合并题库出错: ' + e.message);
  211. }
  212. }
  213.  
  214. // 上传题库
  215. window.uploadQuestionBank = function() {
  216. // 检查是否启用远程题库上传
  217. if (!window.qh.remoteQuestionBankConfig.enabled || !window.qh.remoteQuestionBankConfig.uploadEnabled) {
  218. console.log('远程题库上传功能未启用,跳过上传');
  219. return;
  220. }
  221.  
  222. // 检查题库是否为空
  223. if (!window.qh.savedQuestionBank || window.qh.savedQuestionBank.length === 0) {
  224. console.log('本地题库为空,跳过上传');
  225. return;
  226. }
  227.  
  228. try {
  229. const url = window.qh.remoteQuestionBankConfig.url;
  230. if (!url) {
  231. console.error('远程题库URL未设置');
  232. return;
  233. }
  234.  
  235. // 检查是否为HTTPS页面访问HTTP资源(混合内容问题)
  236. const isHttpsPage = window.location.protocol === 'https:';
  237. const isHttpResource = url.startsWith('http:');
  238.  
  239. if (isHttpsPage && isHttpResource) {
  240. console.warn('由于HTTPS安全限制,无法上传题库到HTTP服务器');
  241. updateStatus('由于安全限制,无法上传题库');
  242.  
  243. // 提示用户可以导出题库
  244. if (confirm('由于浏览器安全限制,无法直接上传题库到HTTP服务器。是否要导出题库到本地?')) {
  245. exportQuestionBank();
  246. }
  247. return;
  248. }
  249.  
  250. console.log('开始上传题库:', url);
  251. updateStatus('正在上传题库...');
  252.  
  253. // 使用fetch API上传题库
  254. fetch(url, {
  255. method: 'POST',
  256. headers: {
  257. 'Content-Type': 'application/json'
  258. },
  259. body: JSON.stringify(window.qh.savedQuestionBank)
  260. })
  261. .then(response => {
  262. if (!response.ok) {
  263. throw new Error('网络响应不正常: ' + response.status);
  264. }
  265. return response.json();
  266. })
  267. .then(data => {
  268. console.log('题库上传成功:', data);
  269. updateStatus('题库上传成功');
  270. })
  271. .catch(error => {
  272. console.error('题库上传失败:', error);
  273.  
  274. // 如果是混合内容错误,提示用户
  275. if (error.message && (
  276. error.message.includes('Mixed Content') ||
  277. error.message.includes('blocked:mixed') ||
  278. error.message.includes('Failed to fetch')
  279. )) {
  280. console.warn('由于HTTPS安全限制,无法上传题库到HTTP服务器');
  281. updateStatus('由于安全限制,无法上传题库');
  282.  
  283. // 提示用户可以导出题库
  284. if (confirm('由于浏览器安全限制,无法直接上传题库到HTTP服务器。是否要导出题库到本地?')) {
  285. exportQuestionBank();
  286. }
  287. } else {
  288. updateStatus('题库上传失败: ' + error.message);
  289. }
  290. });
  291. } catch (e) {
  292. console.error('上传题库出错:', e);
  293. updateStatus('上传题库出错: ' + e.message);
  294. }
  295. };
  296.  
  297. // 显示题库管理面板
  298. window.showQuestionManagePanel = function() {
  299. try {
  300. // 检查是否已存在题库管理面板
  301. if (document.getElementById('qh-question-manage-panel')) {
  302. document.getElementById('qh-question-manage-panel').style.display = 'block';
  303. document.getElementById('qh-question-manage-overlay').style.display = 'block';
  304. return;
  305. }
  306.  
  307. // 创建遮罩层
  308. const overlay = document.createElement('div');
  309. overlay.className = 'qh-question-overlay';
  310. overlay.id = 'qh-question-manage-overlay';
  311. document.body.appendChild(overlay);
  312.  
  313. // 创建题库管理面板
  314. const panel = document.createElement('div');
  315. panel.className = 'qh-question-panel';
  316. panel.id = 'qh-question-manage-panel';
  317. panel.innerHTML = `
  318. <div class="qh-question-title">
  319. 题库管理
  320. <span class="qh-question-close" id="qh-question-manage-close">×</span>
  321. </div>
  322. <div class="qh-question-content" id="qh-question-manage-content">
  323. <div style="margin-bottom: 15px;">
  324. <div style="font-weight: bold; margin-bottom: 10px;">本地题库</div>
  325. <div>题目数量: ${window.qh.savedQuestionBank.length} 道</div>
  326. <div style="margin-top: 10px;">
  327. <button class="qh-question-btn" style="width: 48%;" id="qh-export-btn">导出题库</button>
  328. <button class="qh-question-btn" style="width: 48%;" id="qh-import-btn">导入题库</button>
  329. </div>
  330. <div style="margin-top: 10px;">
  331. <button class="qh-question-btn" style="width: 48%;" id="qh-clear-btn">清空题库</button>
  332. <button class="qh-question-btn" style="width: 48%;" id="qh-backup-btn">备份题库</button>
  333. </div>
  334. </div>
  335. <div style="margin-bottom: 15px;">
  336. <div style="font-weight: bold; margin-bottom: 10px;">远程题库设置</div>
  337. <div style="margin-bottom: 10px;">
  338. <label style="display: block; margin-bottom: 5px;">远程题库URL:</label>
  339. <input type="text" id="qh-remote-url" style="width: 100%; padding: 5px; box-sizing: border-box;" value="${window.qh.remoteQuestionBankConfig.url}">
  340. </div>
  341. <div style="margin-bottom: 10px;">
  342. <label style="display: flex; align-items: center;">
  343. <input type="checkbox" id="qh-remote-enabled" ${window.qh.remoteQuestionBankConfig.enabled ? 'checked' : ''}>
  344. <span style="margin-left: 5px;">启用远程题库</span>
  345. </label>
  346. </div>
  347. <div style="margin-bottom: 10px;">
  348. <label style="display: flex; align-items: center;">
  349. <input type="checkbox" id="qh-auto-sync" ${window.qh.remoteQuestionBankConfig.autoSync ? 'checked' : ''}>
  350. <span style="margin-left: 5px;">自动同步</span>
  351. </label>
  352. </div>
  353. <div style="margin-bottom: 10px;">
  354. <label style="display: flex; align-items: center;">
  355. <input type="checkbox" id="qh-upload-enabled" ${window.qh.remoteQuestionBankConfig.uploadEnabled ? 'checked' : ''}>
  356. <span style="margin-left: 5px;">启用上传</span>
  357. </label>
  358. </div>
  359. <div style="margin-top: 10px;">
  360. <button class="qh-question-btn" style="width: 48%;" id="qh-sync-btn">立即同步</button>
  361. <button class="qh-question-btn" style="width: 48%;" id="qh-upload-btn">立即上传</button>
  362. </div>
  363. </div>
  364. </div>
  365. <div class="qh-question-btns">
  366. <button class="qh-question-btn" id="qh-save-settings-btn">保存设置</button>
  367. </div>
  368. `;
  369. document.body.appendChild(panel);
  370.  
  371. // 绑定关闭按钮事件
  372. document.getElementById('qh-question-manage-close').addEventListener('click', function() {
  373. document.getElementById('qh-question-manage-panel').style.display = 'none';
  374. document.getElementById('qh-question-manage-overlay').style.display = 'none';
  375. });
  376.  
  377. // 绑定导出题库按钮事件
  378. document.getElementById('qh-export-btn').addEventListener('click', function() {
  379. exportQuestionBank();
  380. });
  381.  
  382. // 绑定导入题库按钮事件
  383. document.getElementById('qh-import-btn').addEventListener('click', function() {
  384. importQuestionBank();
  385. });
  386.  
  387. // 绑定清空题库按钮事件
  388. document.getElementById('qh-clear-btn').addEventListener('click', function() {
  389. clearQuestionBank();
  390. });
  391.  
  392. // 绑定备份题库按钮事件
  393. document.getElementById('qh-backup-btn').addEventListener('click', function() {
  394. backupQuestionBank();
  395. });
  396.  
  397. // 绑定立即同步按钮事件
  398. document.getElementById('qh-sync-btn').addEventListener('click', function() {
  399. syncRemoteQuestionBank();
  400. });
  401.  
  402. // 绑定立即上传按钮事件
  403. document.getElementById('qh-upload-btn').addEventListener('click', function() {
  404. uploadQuestionBank();
  405. });
  406.  
  407. // 绑定保存设置按钮事件
  408. document.getElementById('qh-save-settings-btn').addEventListener('click', function() {
  409. saveRemoteSettings();
  410. });
  411.  
  412. // 显示面板
  413. document.getElementById('qh-question-manage-panel').style.display = 'block';
  414. document.getElementById('qh-question-manage-overlay').style.display = 'block';
  415. } catch (e) {
  416. console.error('显示题库管理面板出错:', e);
  417. }
  418. };
  419.  
  420. // 导出题库
  421. function exportQuestionBank() {
  422. try {
  423. // 检查题库是否为空
  424. if (!window.qh.savedQuestionBank || window.qh.savedQuestionBank.length === 0) {
  425. alert('题库为空,无法导出');
  426. return;
  427. }
  428.  
  429. // 将题库转换为JSON字符串
  430. const json = JSON.stringify(window.qh.savedQuestionBank, null, 2);
  431.  
  432. // 创建Blob对象
  433. const blob = new Blob([json], { type: 'application/json' });
  434.  
  435. // 创建下载链接
  436. const url = URL.createObjectURL(blob);
  437. const a = document.createElement('a');
  438. a.href = url;
  439. a.download = `qh-question-bank-${new Date().toISOString().slice(0, 10)}.json`;
  440. document.body.appendChild(a);
  441. a.click();
  442.  
  443. // 清理
  444. setTimeout(() => {
  445. document.body.removeChild(a);
  446. URL.revokeObjectURL(url);
  447. }, 0);
  448.  
  449. alert('题库导出成功');
  450. } catch (e) {
  451. console.error('导出题库出错:', e);
  452. alert('导出题库出错: ' + e.message);
  453. }
  454. }
  455.  
  456. // 导入题库
  457. function importQuestionBank() {
  458. try {
  459. // 创建文件输入元素
  460. const input = document.createElement('input');
  461. input.type = 'file';
  462. input.accept = '.json';
  463. input.style.display = 'none';
  464. document.body.appendChild(input);
  465.  
  466. // 监听文件选择事件
  467. input.addEventListener('change', function() {
  468. if (input.files.length === 0) {
  469. return;
  470. }
  471.  
  472. const file = input.files[0];
  473. const reader = new FileReader();
  474.  
  475. reader.onload = function(e) {
  476. try {
  477. const importedQuestions = JSON.parse(e.target.result);
  478.  
  479. if (!Array.isArray(importedQuestions)) {
  480. throw new Error('导入的题库格式不正确');
  481. }
  482.  
  483. // 合并题库
  484. mergeQuestionBanks(importedQuestions);
  485.  
  486. alert(`题库导入成功,当前题库共有 ${window.qh.savedQuestionBank.length} 道题目`);
  487. } catch (e) {
  488. console.error('解析导入的题库出错:', e);
  489. alert('解析导入的题库出错: ' + e.message);
  490. }
  491. };
  492.  
  493. reader.onerror = function() {
  494. alert('读取文件出错');
  495. };
  496.  
  497. reader.readAsText(file);
  498. });
  499.  
  500. // 触发文件选择对话框
  501. input.click();
  502.  
  503. // 清理
  504. setTimeout(() => {
  505. document.body.removeChild(input);
  506. }, 0);
  507. } catch (e) {
  508. console.error('导入题库出错:', e);
  509. alert('导入题库出错: ' + e.message);
  510. }
  511. }
  512.  
  513. // 清空题库
  514. function clearQuestionBank() {
  515. try {
  516. if (confirm('确定要清空题库吗?此操作不可恢复!')) {
  517. // 清空题库
  518. window.qh.savedQuestionBank = [];
  519. GM_setValue('qh-question-bank', []);
  520.  
  521. // 更新状态
  522. const statusElement = document.getElementById('qh-question-status');
  523. if (statusElement) {
  524. statusElement.textContent = '题库状态: 题库为空';
  525. }
  526.  
  527. alert('题库已清空');
  528. }
  529. } catch (e) {
  530. console.error('清空题库出错:', e);
  531. alert('清空题库出错: ' + e.message);
  532. }
  533. }
  534.  
  535. // 备份题库
  536. function backupQuestionBank() {
  537. try {
  538. // 检查题库是否为空
  539. if (!window.qh.savedQuestionBank || window.qh.savedQuestionBank.length === 0) {
  540. alert('题库为空,无法备份');
  541. return;
  542. }
  543.  
  544. // 创建备份
  545. const backup = {
  546. timestamp: Date.now(),
  547. questions: window.qh.savedQuestionBank
  548. };
  549.  
  550. // 获取现有备份
  551. let backups = GM_getValue('qh-question-bank-backups', []);
  552.  
  553. // 添加新备份
  554. backups.push(backup);
  555.  
  556. // 最多保留10个备份
  557. if (backups.length > 10) {
  558. backups = backups.slice(-10);
  559. }
  560.  
  561. // 保存备份
  562. GM_setValue('qh-question-bank-backups', backups);
  563.  
  564. alert(`备份成功,当前共有 ${backups.length} 个备份`);
  565. } catch (e) {
  566. console.error('备份题库出错:', e);
  567. alert('备份题库出错: ' + e.message);
  568. }
  569. }
  570.  
  571. // 保存远程设置
  572. function saveRemoteSettings() {
  573. try {
  574. // 获取设置
  575. const url = document.getElementById('qh-remote-url').value.trim();
  576. const enabled = document.getElementById('qh-remote-enabled').checked;
  577. const autoSync = document.getElementById('qh-auto-sync').checked;
  578. const uploadEnabled = document.getElementById('qh-upload-enabled').checked;
  579.  
  580. // 更新设置
  581. window.qh.remoteQuestionBankConfig.url = url;
  582. window.qh.remoteQuestionBankConfig.enabled = enabled;
  583. window.qh.remoteQuestionBankConfig.autoSync = autoSync;
  584. window.qh.remoteQuestionBankConfig.uploadEnabled = uploadEnabled;
  585.  
  586. // 保存设置
  587. GM_setValue('qh-remote-question-bank-config', window.qh.remoteQuestionBankConfig);
  588.  
  589. alert('设置已保存');
  590. } catch (e) {
  591. console.error('保存远程设置出错:', e);
  592. alert('保存远程设置出错: ' + e.message);
  593. }
  594. }
  595.  
  596. // 显示自动化设置面板
  597. window.showAutoFlowSettingsPanel = function() {
  598. try {
  599. // 检查是否已存在自动化设置面板
  600. if (document.getElementById('qh-auto-flow-panel')) {
  601. document.getElementById('qh-auto-flow-panel').style.display = 'block';
  602. document.getElementById('qh-auto-flow-overlay').style.display = 'block';
  603. return;
  604. }
  605.  
  606. // 创建遮罩层
  607. const overlay = document.createElement('div');
  608. overlay.className = 'qh-question-overlay';
  609. overlay.id = 'qh-auto-flow-overlay';
  610. document.body.appendChild(overlay);
  611.  
  612. // 创建自动化设置面板
  613. const panel = document.createElement('div');
  614. panel.className = 'qh-question-panel';
  615. panel.id = 'qh-auto-flow-panel';
  616. panel.innerHTML = `
  617. <div class="qh-question-title">
  618. 自动化设置
  619. <span class="qh-question-close" id="qh-auto-flow-close">×</span>
  620. </div>
  621. <div class="qh-question-content" id="qh-auto-flow-content">
  622. <div style="margin-bottom: 15px;">
  623. <div style="margin-bottom: 10px;">
  624. <label style="display: flex; align-items: center;">
  625. <input type="checkbox" id="qh-auto-flow-enabled" ${window.qh.autoFlowConfig.enabled ? 'checked' : ''}>
  626. <span style="margin-left: 5px;">启用自动化流程</span>
  627. </label>
  628. </div>
  629. <div style="margin-bottom: 10px;">
  630. <label style="display: flex; align-items: center;">
  631. <input type="checkbox" id="qh-auto-start-next-course" ${window.qh.autoFlowConfig.autoStartNextCourse ? 'checked' : ''}>
  632. <span style="margin-left: 5px;">自动开始下一课程</span>
  633. </label>
  634. </div>
  635. <div style="margin-bottom: 10px;">
  636. <label style="display: flex; align-items: center;">
  637. <input type="checkbox" id="qh-auto-take-exams" ${window.qh.autoFlowConfig.autoTakeExams ? 'checked' : ''}>
  638. <span style="margin-left: 5px;">自动参加考试</span>
  639. </label>
  640. </div>
  641. <div style="margin-bottom: 10px;">
  642. <label style="display: flex; align-items: center;">
  643. <input type="checkbox" id="qh-prioritize-incomplete" ${window.qh.autoFlowConfig.prioritizeIncomplete ? 'checked' : ''}>
  644. <span style="margin-left: 5px;">优先学习未完成课程</span>
  645. </label>
  646. </div>
  647. <div style="margin-bottom: 10px;">
  648. <label style="display: block; margin-bottom: 5px;">学习速度:</label>
  649. <select id="qh-learning-speed" style="width: 100%; padding: 5px; box-sizing: border-box;">
  650. <option value="slow" ${window.qh.autoFlowConfig.learningSpeed === 'slow' ? 'selected' : ''}>慢速</option>
  651. <option value="normal" ${window.qh.autoFlowConfig.learningSpeed === 'normal' ? 'selected' : ''}>正常</option>
  652. <option value="fast" ${window.qh.autoFlowConfig.learningSpeed === 'fast' ? 'selected' : ''}>快速</option>
  653. </select>
  654. </div>
  655. </div>
  656. </div>
  657. <div class="qh-question-btns">
  658. <button class="qh-question-btn" id="qh-save-auto-flow-btn">保存设置</button>
  659. </div>
  660. `;
  661. document.body.appendChild(panel);
  662.  
  663. // 绑定关闭按钮事件
  664. document.getElementById('qh-auto-flow-close').addEventListener('click', function() {
  665. document.getElementById('qh-auto-flow-panel').style.display = 'none';
  666. document.getElementById('qh-auto-flow-overlay').style.display = 'none';
  667. });
  668.  
  669. // 绑定保存设置按钮事件
  670. document.getElementById('qh-save-auto-flow-btn').addEventListener('click', function() {
  671. saveAutoFlowSettings();
  672. });
  673.  
  674. // 显示面板
  675. document.getElementById('qh-auto-flow-panel').style.display = 'block';
  676. document.getElementById('qh-auto-flow-overlay').style.display = 'block';
  677. } catch (e) {
  678. console.error('显示自动化设置面板出错:', e);
  679. }
  680. };
  681.  
  682. // 保存自动化设置
  683. function saveAutoFlowSettings() {
  684. try {
  685. // 获取设置
  686. const enabled = document.getElementById('qh-auto-flow-enabled').checked;
  687. const autoStartNextCourse = document.getElementById('qh-auto-start-next-course').checked;
  688. const autoTakeExams = document.getElementById('qh-auto-take-exams').checked;
  689. const prioritizeIncomplete = document.getElementById('qh-prioritize-incomplete').checked;
  690. const learningSpeed = document.getElementById('qh-learning-speed').value;
  691.  
  692. // 更新设置
  693. window.qh.autoFlowConfig.enabled = enabled;
  694. window.qh.autoFlowConfig.autoStartNextCourse = autoStartNextCourse;
  695. window.qh.autoFlowConfig.autoTakeExams = autoTakeExams;
  696. window.qh.autoFlowConfig.prioritizeIncomplete = prioritizeIncomplete;
  697. window.qh.autoFlowConfig.learningSpeed = learningSpeed;
  698.  
  699. // 保存设置
  700. GM_setValue('qh-auto-flow-config', window.qh.autoFlowConfig);
  701.  
  702. // 根据学习速度设置延迟时间
  703. switch (learningSpeed) {
  704. case 'slow':
  705. window.qh.humanLikeDelay = { min: 3000, max: 6000 };
  706. window.qh.autoSubmitDelay = { min: 10000, max: 15000 };
  707. break;
  708. case 'normal':
  709. window.qh.humanLikeDelay = { min: 1000, max: 3000 };
  710. window.qh.autoSubmitDelay = { min: 5000, max: 10000 };
  711. break;
  712. case 'fast':
  713. window.qh.humanLikeDelay = { min: 500, max: 1500 };
  714. window.qh.autoSubmitDelay = { min: 2000, max: 5000 };
  715. break;
  716. }
  717.  
  718. alert('设置已保存');
  719. } catch (e) {
  720. console.error('保存自动化设置出错:', e);
  721. alert('保存自动化设置出错: ' + e.message);
  722. }
  723. }
  724. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址