// ==UserScript== // @name 💯【超星学习通满分助手】支持LLM智能答题 // @namespace askAuto // @version 3.5.3 // @author HaoduoYv // @description 💯超星学习通满分助手,挂机解放时间,无需任何操作自动完成所有任务点。汇集全网免费、付费题库接口支持一键对接,支持LLM智能答题(OpenAI/DeepSeek/kimi/智谱/千问/小米Mimo等),题库无答案时自动调用AI解答。 // @icon https://vitejs.dev/logo.svg // @match *://*.chaoxing.com/* // @match *://*.edu.cn/* // @match *://*.nbdlib.cn/* // @match *://*.hnsyu.net/* // @match *://*.gdhkmooc.com/* // @require https://cdn.staticfile.org/vue/3.3.4/vue.global.prod.js // @require https://cdn.staticfile.org/vue-demi/0.14.0/index.iife.min.js // @require https://cdn.staticfile.org/element-plus-icons-vue/2.1.0/global.iife.min.js // @require data:application/javascript,window.Vue%3DVue%3B // @require https://cdn.staticfile.org/pinia/2.1.6/pinia.iife.prod.js // @require https://cdn.staticfile.org/element-plus/2.3.12/index.full.min.js // @require https://cdn.staticfile.org/blueimp-md5/2.19.0/js/md5.min.js // @require https://cdn.staticfile.org/jquery/3.7.1/jquery.min.js // @resource element-plus https://cdn.staticfile.org/element-plus/2.3.12/index.css // @resource ttf https://www.forestpolice.org/ttf/2.0/table.json // @tag free // @connect api.openai.com // @connect api.deepseek.com // @connect api.anthropic.com // @connect open.bigmodel.cn // @connect dashscope.aliyuncs.com // @connect api.xiaomimimo.com // @connect token-plan-cn.xiaomimimo.com // @connect www.baidu.com // @connect www.bing.com // @connect cn.bing.com // @connect duckduckgo.com // @connect * // @grant GM_addStyle // @grant GM_getResourceText // @grant GM_getValue // @grant GM_info // @grant GM_setValue // @grant GM_xmlhttpRequest // @grant unsafeWindow // @run-at document-end // @license MIT // ==/UserScript== (t => { if (typeof GM_addStyle == "function") { GM_addStyle(t); return } const i = document.createElement("style"); i.textContent = t, document.head.append(i) })("/* ===== 超星学习通满分助手 现代简洁 UI ===== */:root{--cx-bg:#f8fafc;--cx-surface:#ffffff;--cx-surface-raised:#ffffff;--cx-primary:#4f46e5;--cx-primary-light:#6366f1;--cx-primary-soft:#e0e7ff;--cx-primary-dark:#4338ca;--cx-success:#16a34a;--cx-warning:#d97706;--cx-danger:#dc2626;--cx-info:#0891b2;--cx-text:#0f172a;--cx-text-secondary:#475569;--cx-text-tertiary:#94a3b8;--cx-border:#e2e8f0;--cx-border-light:#f1f5f9;--cx-radius-lg:16px;--cx-radius:12px;--cx-radius-sm:8px;--cx-radius-xs:6px;--cx-shadow:0 10px 30px -10px rgba(15,23,42,.12);--cx-shadow-sm:0 2px 8px rgba(15,23,42,.06);--cx-shadow-lg:0 20px 40px -12px rgba(15,23,42,.18);--cx-transition:all .2s cubic-bezier(.4,0,.2,1)}#csbutton,#csbutton[data-v-6ed29f7f],#csbutton[data-v-c3c6b09f]{position:fixed;bottom:24px;right:24px;z-index:99999;width:56px;height:56px;border-radius:16px!important;font-size:22px;box-shadow:var(--cx-shadow);transition:var(--cx-transition);border:none!important;background:var(--cx-primary)!important;color:#fff!important}#csbutton:hover,#csbutton[data-v-6ed29f7f]:hover,#csbutton[data-v-c3c6b09f]:hover{transform:translateY(-2px);box-shadow:var(--cx-shadow-lg)}#zeokdjg,#zeokdjg[data-v-c3c6b09f]{position:fixed;right:24px;bottom:96px;z-index:99999;width:56px;height:56px;border-radius:16px!important;font-size:22px;box-shadow:var(--cx-shadow);transition:var(--cx-transition);border:none!important;background:var(--cx-primary)!important;color:#fff!important;padding:0!important;display:flex;align-items:center;justify-content:center}#zeokdjg:hover,#zeokdjg[data-v-c3c6b09f]:hover{transform:translateY(-2px);box-shadow:var(--cx-shadow-lg)}#zeokdjg .el-button__text,#zeokdjg span{font-size:0!important}#zeokdjg .el-icon{font-size:22px!important}.el-dialog{border-radius:var(--cx-radius-lg)!important;box-shadow:var(--cx-shadow-lg)!important;background:var(--cx-surface)!important}.cx-config-dialog{width:720px!important;max-width:calc(100vw - 40px)!important}.cx-ask-dialog{width:480px!important;max-width:calc(100vw - 40px)!important}.el-dialog__header{padding:20px 24px 0!important;font-size:16px;font-weight:600;color:var(--cx-text);border-bottom:none}.el-dialog__body{padding:0!important;color:var(--cx-text-secondary);font-size:14px;line-height:1.6}.el-dialog__footer{padding:16px 24px!important;border-top:1px solid var(--cx-border);margin-top:0;display:flex;justify-content:flex-end;gap:12px}.el-dialog__headerbtn{top:18px!important;right:20px!important;font-size:18px!important;width:32px;height:32px;border-radius:var(--cx-radius-sm);transition:var(--cx-transition)}.el-dialog__headerbtn:hover{background:var(--cx-border-light);transform:rotate(90deg)}.cx-config-layout{display:flex;min-height:420px;max-height:70vh}.cx-config-nav{width:160px;flex-shrink:0;background:var(--cx-bg);border-right:1px solid var(--cx-border);padding:16px 12px;display:flex;flex-direction:column;gap:4px;border-radius:var(--cx-radius-lg) 0 0 var(--cx-radius-lg)}.cx-config-nav-item{width:100%;text-align:left;padding:10px 12px;border-radius:var(--cx-radius-sm);font-size:13px;font-weight:500;color:var(--cx-text-secondary);cursor:pointer;transition:var(--cx-transition);border:none;background:transparent}.cx-config-nav-item:hover{background:var(--cx-border-light);color:var(--cx-text)}.cx-config-nav-item.active{background:var(--cx-primary-soft);color:var(--cx-primary)}.cx-config-content{flex:1;min-width:0;padding:24px;overflow-y:auto}.cx-config-section-title{font-size:18px;font-weight:600;color:var(--cx-text);margin-bottom:8px}.cx-config-section-desc{font-size:13px;color:var(--cx-text-secondary);margin-bottom:24px}.cx-config-actions{display:flex;gap:8px;margin-top:24px;padding-top:20px;border-top:1px solid var(--cx-border)}.cx-config-group-title{font-size:14px;font-weight:600;color:var(--cx-text);margin:24px 0 12px;padding-bottom:8px;border-bottom:1px solid var(--cx-border-light)}.cx-config-group-title:first-child{margin-top:0}.el-form-item{margin-bottom:20px!important}.el-form-item__label{font-weight:500;color:var(--cx-text);padding-bottom:4px!important;font-size:13px}.el-form-item__content{line-height:1.5}.el-switch.is-checked .el-switch__core{background:var(--cx-primary)!important;border-color:var(--cx-primary)!important}.el-button--primary{--el-button-primary-bg-color:var(--cx-primary);--el-button-primary-border-color:var(--cx-primary)}.el-button--primary:hover{--el-button-primary-bg-color:var(--cx-primary-light);--el-button-primary-border-color:var(--cx-primary-light)}.el-button--danger{--el-button-danger-bg-color:var(--cx-danger);--el-button-danger-border-color:var(--cx-danger)}.el-button{border-radius:var(--cx-radius-sm)!important;font-weight:500!important;transition:var(--cx-transition)}.el-input__wrapper,.el-textarea__inner{border-radius:var(--cx-radius-sm)!important;box-shadow:0 0 0 1px var(--cx-border) inset!important}.el-input__wrapper:hover,.el-textarea__inner:hover{box-shadow:0 0 0 1px var(--cx-primary-light) inset!important}.el-input__wrapper.is-focus{box-shadow:0 0 0 1px var(--cx-primary) inset!important}.el-select{width:100%}.el-checkbox__input.is-checked .el-checkbox__inner{background:var(--cx-primary)!important;border-color:var(--cx-primary)!important}.el-checkbox__label{font-size:13px!important;color:var(--cx-text-secondary)}.el-checkbox-group.cx-checkbox-horizontal{display:flex;flex-wrap:wrap;gap:16px}.cx-runtime{padding:20px 24px}.cx-runtime-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;padding:12px 16px;background:var(--cx-bg);border-radius:var(--cx-radius-sm)}.cx-runtime-header-title{font-size:14px;font-weight:600;color:var(--cx-text)}.cx-runtime-header-meta{font-size:12px;color:var(--cx-text-secondary)}.cx-question-card{margin-bottom:16px;border-radius:var(--cx-radius)!important;border:1px solid var(--cx-border)!important;background:var(--cx-surface)!important}.cx-question-card .el-card__body{padding:20px!important}.cx-question-index{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:var(--cx-radius-xs);background:var(--cx-primary-soft);color:var(--cx-primary);font-size:12px;font-weight:600;margin-right:8px}.cx-question-title{font-size:15px;font-weight:500;color:var(--cx-text);line-height:1.6;margin-bottom:12px;word-break:break-word}.cx-question-answer{background:var(--cx-bg);border-radius:var(--cx-radius-sm);padding:12px;font-size:13px;color:var(--cx-text);white-space:pre-wrap;word-break:break-word;line-height:1.6}.cx-question-empty{display:flex;flex-direction:column;gap:12px;padding:8px 0}.cx-question-nav{display:flex;gap:8px;margin:16px 0;padding:8px 0}.cx-question-nav .el-button{min-width:36px;height:36px;padding:0 12px;border-radius:18px!important;font-size:13px;font-weight:500}.cx-source-list{display:flex;flex-direction:column;gap:12px;margin-top:16px}.cx-source-item{padding:14px 16px;border:1px solid var(--cx-border);border-radius:var(--cx-radius-sm);background:var(--cx-surface-raised)}.cx-source-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.cx-source-name{font-size:13px;font-weight:600;color:var(--cx-text)}.cx-source-answer{font-size:13px;color:var(--cx-text-secondary);line-height:1.6;white-space:pre-wrap;word-break:break-word}.cx-source-meta{display:flex;gap:8px;margin-top:10px}.cx-ask-tabs{margin-top:8px}.cx-source-tabs .el-tabs__item{max-width:120px;overflow:hidden;text-overflow:ellipsis}.cx-source-answer{font-size:13px;line-height:1.6;word-break:break-word}.cx-question-answer{white-space:pre-wrap;word-break:break-word;font-family:inherit;font-size:14px;margin:0}#cx-ask-fab{font-size:13px;font-weight:600;border-radius:22px!important}.cx-ask-panel{position:fixed;right:24px;top:72px;width:420px;max-height:calc(100vh - 100px);overflow:auto;z-index:100000;background:#fff;border-radius:12px;box-shadow:0 20px 40px -12px rgba(15,23,42,.18);font-size:13px;color:#0f172a;user-select:none}.cx-ask-panel.collapsed .cx-panel-body{display:none}.cx-ask-panel.collapsed{width:auto!important;min-width:200px}.cx-panel-toggle.pause{background:#fee2e2;color:#b91c1c}.cx-panel-toggle.pause:hover{background:#fecaca}.cx-panel-toggle{border:none;background:#e2e8f0;border-radius:6px;width:28px;height:28px;cursor:pointer;font-size:18px;line-height:1;flex-shrink:0}.cx-panel-body{padding:0 0 12px}.cx-video-tip{margin:12px;padding:10px 12px;background:#fef3c7;color:#b45309;border-radius:8px;font-weight:600;font-size:13px}.cx-follow-btn{border:none;background:#4f46e5;color:#fff;border-radius:6px;padding:2px 8px;font-size:11px;cursor:pointer;flex-shrink:0}.cx-badge{font-size:11px;padding:2px 8px;border-radius:99px;background:#e0e7ff;color:#4f46e5;font-weight:600;flex-shrink:0}.cx-badge.warn{background:#fef3c7;color:#b45309}.cx-drag-bar{display:flex;align-items:center;gap:8px;padding:10px 12px;background:#f8fafc;border-bottom:1px solid #e2e8f0;cursor:move;border-radius:12px 12px 0 0;position:sticky;top:0;z-index:2}.cx-drag-title{font-weight:600;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cx-panel-close{margin-left:auto;border:none;background:#f1f5f9;border-radius:6px;width:28px;height:28px;cursor:pointer;font-size:18px;line-height:1;flex-shrink:0}.cx-q-title{font-size:14px;font-weight:600;line-height:1.5;margin:12px 12px 8px}.cx-question-answer{margin:0 12px 8px;padding:10px;background:#f8fafc;border-radius:8px;white-space:pre-wrap;word-break:break-word;font-family:inherit}.cx-q-nav{display:flex;flex-wrap:wrap;gap:6px;margin:10px 12px}.cx-q-nav .question_btn{width:36px;height:36px;border-radius:8px;border:1px solid #e2e8f0;background:#f8fafc;cursor:pointer;font-weight:600}.cx-q-nav .question_btn.active{outline:2px solid #4f46e5}.cx-q-nav .question_btn.primary{background:#4f46e5;color:#fff;border-color:#4f46e5}.cx-q-nav .question_btn.danger{background:#fee2e2;color:#dc2626;border-color:#fecaca}.cx-source-item{border:1px solid #e2e8f0;border-radius:8px;padding:8px 10px;margin:6px 12px}.cx-source-header{display:flex;align-items:center;gap:8px;margin-bottom:4px}.cx-source-name{font-weight:600;flex:1}.cx-source-tag{font-size:11px;padding:2px 8px;border-radius:99px}.cx-source-tag.ok{background:#dcfce7;color:#166534}.cx-source-tag.no{background:#f1f5f9;color:#64748b}.cx-log-title{margin:12px 12px 4px;font-size:12px;font-weight:600;color:#64748b}.cx-log-list{padding:0 12px 12px;display:flex;flex-direction:column;gap:4px}.cx-log-item{font-size:12px;color:#475569;line-height:1.5}.cx-log-msg.success{color:#16a34a}.cx-log-msg.error{color:#dc2626}.cx-log-msg.info{color:#0891b2}.cx-fab{display:flex;align-items:center;justify-content:center;gap:6px;padding:0 14px;height:44px;width:auto;min-width:44px;position:fixed!important;right:24px!important;bottom:96px!important;z-index:100001;width:56px;height:56px;border-radius:16px!important;border:none!important;background:var(--cx-primary,#4f46e5)!important;color:#fff!important;font-size:22px;cursor:pointer;box-shadow:0 10px 30px -10px rgba(15,23,42,.2)}#cx-ask-fab{font-size:13px;font-weight:600;border-radius:22px!important}.cx-ask-panel{position:fixed;right:24px;top:72px;width:420px;max-height:calc(100vh - 100px);overflow:auto;z-index:100000;background:#fff;border-radius:12px;box-shadow:0 20px 40px -12px rgba(15,23,42,.18);padding:14px 16px;font-size:13px;color:#0f172a}.cx-panel-close{margin-left:auto;border:none;background:#f1f5f9;border-radius:6px;width:28px;height:28px;cursor:pointer;font-size:18px;line-height:1}.cx-q-title{font-size:14px;font-weight:600;line-height:1.5;margin:8px 0}.cx-q-nav{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0}.cx-q-nav .question_btn{width:36px;height:36px;border-radius:8px;border:1px solid #e2e8f0;background:#f8fafc;cursor:pointer;font-weight:600}.cx-q-nav .question_btn.primary{background:#4f46e5;color:#fff;border-color:#4f46e5}.cx-q-nav .question_btn.danger{background:#fee2e2;color:#dc2626;border-color:#fecaca}.cx-empty{padding:24px;text-align:center;color:#64748b}.cx-video-tip{padding:16px;text-align:center;color:#dc2626;font-weight:600}.cx-source-item{border:1px solid #e2e8f0;border-radius:8px;padding:8px 10px;margin:6px 0}.cx-source-header{display:flex;align-items:center;gap:8px;margin-bottom:4px}.cx-source-name{font-weight:600;flex:1}.cx-source-tag{font-size:11px;padding:2px 8px;border-radius:99px}.cx-source-tag.ok{background:#dcfce7;color:#166534}.cx-source-tag.no{background:#f1f5f9;color:#64748b}.cx-debug-line{margin:8px 0;padding:8px 10px;background:#fff7ed;border:1px solid #fdba74;border-radius:8px;font-size:12px;color:#c2410c;font-weight:600}.cx-log-title{margin:12px 4px 6px;font-size:12px;font-weight:600;letter-spacing:.04em;color:var(--cx-text-secondary)}.cx-log-list{display:flex;flex-direction:column;gap:8px;padding:16px 24px}.cx-log-item{display:flex;gap:12px;align-items:flex-start;padding:10px 12px;border-radius:var(--cx-radius-sm);background:var(--cx-bg);transition:var(--cx-transition)}.cx-log-item:hover{background:var(--cx-border-light)}.cx-log-time{font-size:12px;color:var(--cx-text-tertiary);white-space:nowrap;min-width:64px}.cx-log-dot{width:6px;height:6px;border-radius:50%;margin-top:7px;flex-shrink:0}.cx-log-dot.success{background:var(--cx-success)}.cx-log-dot.error{background:var(--cx-danger)}.cx-log-dot.info{background:var(--cx-info)}.cx-log-msg{font-size:13px;color:var(--cx-text-secondary);line-height:1.5;flex:1;word-break:break-word}.cx-log-msg.success{color:var(--cx-success)}.cx-log-msg.error{color:var(--cx-danger)}.cx-log-msg.info{color:var(--cx-info)}.cx-notice{padding:20px 24px}.cx-notice-card{border-radius:var(--cx-radius)!important;border:1px solid var(--cx-border)!important;background:var(--cx-surface)!important}.cx-notice-card .el-card__body{padding:20px!important;font-size:14px;line-height:1.8;color:var(--cx-text-secondary)}.el-tabs__item{font-size:13px;font-weight:500;padding:0 14px!important;transition:var(--cx-transition);color:var(--cx-text-secondary)}.el-tabs__item.is-active{color:var(--cx-primary)!important}.el-tabs__active-bar{background:var(--cx-primary)!important;height:2px;border-radius:2px}.el-tag{border-radius:var(--cx-radius-xs)!important;font-weight:500!important;border:none!important}.el-alert{border-radius:var(--cx-radius-sm)!important;border:none!important}.el-empty__description p{color:var(--cx-text-secondary)!important}.el-scrollbar__view{padding:2px 0}.el-skeleton__item{--el-skeleton-circle-size:8px}.el-divider__text{font-size:12px;color:var(--cx-text-secondary);background:var(--cx-surface)}.el-overlay{overflow:visible!important}.el-select-dropdown,.el-tooltip__popper,.el-popper,.el-select__popper,.el-picker__popper{z-index:999999!important}.el-message-box__wrapper{z-index:99999!important}.dialog-footer button[data-v-6ed29f7f]:first-child{margin-right:10px}.dialog-footer button[data-v-c3c6b09f]:first-child{margin-right:10px}.question_btn[data-v-c3c6b09f]{width:36px;height:36px;border-radius:18px!important;margin:4px;font-weight:500!important;transition:var(--cx-transition);padding:0!important}.question_btn[data-v-c3c6b09f]:hover{transform:scale(1.05);z-index:2}.question_div[data-v-c3c6b09f]{padding:4px 0}.question_ti[data-v-c3c6b09f]{margin:12px 0 16px;line-height:1.5;font-size:15px;font-weight:500}.cx_log[data-v-c3c6b09f]{margin:3px 0;padding:6px 10px;border-radius:6px;background:var(--cx-bg);transition:var(--cx-transition);font-size:13px}.cx_log[data-v-c3c6b09f]:hover{background:var(--cx-border-light)}.status_log[data-v-c3c6b09f]{margin-top:12px}.cx-log-success{color:var(--cx-success)}.cx-log-error{color:var(--cx-danger)}.cx-log-info{color:var(--cx-info)}.vjs-big-play-button{display:none!important}@media (max-width:640px){.cx-config-dialog,.cx-ask-dialog{width:100vw!important;max-width:100vw!important;margin:0!important;border-radius:0!important;height:100vh!important;max-height:100vh!important}.cx-config-layout{flex-direction:column;min-height:auto;max-height:calc(100vh - 55px)}.cx-config-nav{width:100%;flex-direction:row;overflow-x:auto;padding:8px;gap:8px;border-right:none;border-bottom:1px solid var(--cx-border);border-radius:0}.cx-config-nav-item{width:auto;white-space:nowrap;padding:8px 12px}.cx-config-content{padding:16px;max-height:calc(100vh - 120px)}.cx-runtime{padding:16px}.cx-ask-tabs{margin-top:8px}.cx-source-tabs .el-tabs__item{max-width:120px;overflow:hidden;text-overflow:ellipsis}.cx-source-answer{font-size:13px;line-height:1.6;word-break:break-word}.cx-question-answer{white-space:pre-wrap;word-break:break-word;font-family:inherit;font-size:14px;margin:0}#cx-ask-fab{font-size:13px;font-weight:600;border-radius:22px!important}.cx-ask-panel{position:fixed;right:24px;top:72px;width:420px;max-height:calc(100vh - 100px);overflow:auto;z-index:100000;background:#fff;border-radius:12px;box-shadow:0 20px 40px -12px rgba(15,23,42,.18);font-size:13px;color:#0f172a;user-select:none}.cx-ask-panel.collapsed .cx-panel-body{display:none}.cx-ask-panel.collapsed{width:auto!important;min-width:200px}.cx-panel-toggle.pause{background:#fee2e2;color:#b91c1c}.cx-panel-toggle.pause:hover{background:#fecaca}.cx-panel-toggle{border:none;background:#e2e8f0;border-radius:6px;width:28px;height:28px;cursor:pointer;font-size:18px;line-height:1;flex-shrink:0}.cx-panel-body{padding:0 0 12px}.cx-video-tip{margin:12px;padding:10px 12px;background:#fef3c7;color:#b45309;border-radius:8px;font-weight:600;font-size:13px}.cx-follow-btn{border:none;background:#4f46e5;color:#fff;border-radius:6px;padding:2px 8px;font-size:11px;cursor:pointer;flex-shrink:0}.cx-badge{font-size:11px;padding:2px 8px;border-radius:99px;background:#e0e7ff;color:#4f46e5;font-weight:600;flex-shrink:0}.cx-badge.warn{background:#fef3c7;color:#b45309}.cx-drag-bar{display:flex;align-items:center;gap:8px;padding:10px 12px;background:#f8fafc;border-bottom:1px solid #e2e8f0;cursor:move;border-radius:12px 12px 0 0;position:sticky;top:0;z-index:2}.cx-drag-title{font-weight:600;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cx-panel-close{margin-left:auto;border:none;background:#f1f5f9;border-radius:6px;width:28px;height:28px;cursor:pointer;font-size:18px;line-height:1;flex-shrink:0}.cx-q-title{font-size:14px;font-weight:600;line-height:1.5;margin:12px 12px 8px}.cx-question-answer{margin:0 12px 8px;padding:10px;background:#f8fafc;border-radius:8px;white-space:pre-wrap;word-break:break-word;font-family:inherit}.cx-q-nav{display:flex;flex-wrap:wrap;gap:6px;margin:10px 12px}.cx-q-nav .question_btn{width:36px;height:36px;border-radius:8px;border:1px solid #e2e8f0;background:#f8fafc;cursor:pointer;font-weight:600}.cx-q-nav .question_btn.active{outline:2px solid #4f46e5}.cx-q-nav .question_btn.primary{background:#4f46e5;color:#fff;border-color:#4f46e5}.cx-q-nav .question_btn.danger{background:#fee2e2;color:#dc2626;border-color:#fecaca}.cx-source-item{border:1px solid #e2e8f0;border-radius:8px;padding:8px 10px;margin:6px 12px}.cx-source-header{display:flex;align-items:center;gap:8px;margin-bottom:4px}.cx-source-name{font-weight:600;flex:1}.cx-source-tag{font-size:11px;padding:2px 8px;border-radius:99px}.cx-source-tag.ok{background:#dcfce7;color:#166534}.cx-source-tag.no{background:#f1f5f9;color:#64748b}.cx-log-title{margin:12px 12px 4px;font-size:12px;font-weight:600;color:#64748b}.cx-log-list{padding:0 12px 12px;display:flex;flex-direction:column;gap:4px}.cx-log-item{font-size:12px;color:#475569;line-height:1.5}.cx-log-msg.success{color:#16a34a}.cx-log-msg.error{color:#dc2626}.cx-log-msg.info{color:#0891b2}.cx-fab{display:flex;align-items:center;justify-content:center;gap:6px;padding:0 14px;height:44px;width:auto;min-width:44px;position:fixed!important;right:24px!important;bottom:96px!important;z-index:100001;width:56px;height:56px;border-radius:16px!important;border:none!important;background:var(--cx-primary,#4f46e5)!important;color:#fff!important;font-size:22px;cursor:pointer;box-shadow:0 10px 30px -10px rgba(15,23,42,.2)}#cx-ask-fab{font-size:13px;font-weight:600;border-radius:22px!important}.cx-ask-panel{position:fixed;right:24px;top:72px;width:420px;max-height:calc(100vh - 100px);overflow:auto;z-index:100000;background:#fff;border-radius:12px;box-shadow:0 20px 40px -12px rgba(15,23,42,.18);padding:14px 16px;font-size:13px;color:#0f172a}.cx-panel-close{margin-left:auto;border:none;background:#f1f5f9;border-radius:6px;width:28px;height:28px;cursor:pointer;font-size:18px;line-height:1}.cx-q-title{font-size:14px;font-weight:600;line-height:1.5;margin:8px 0}.cx-q-nav{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0}.cx-q-nav .question_btn{width:36px;height:36px;border-radius:8px;border:1px solid #e2e8f0;background:#f8fafc;cursor:pointer;font-weight:600}.cx-q-nav .question_btn.primary{background:#4f46e5;color:#fff;border-color:#4f46e5}.cx-q-nav .question_btn.danger{background:#fee2e2;color:#dc2626;border-color:#fecaca}.cx-empty{padding:24px;text-align:center;color:#64748b}.cx-video-tip{padding:16px;text-align:center;color:#dc2626;font-weight:600}.cx-source-item{border:1px solid #e2e8f0;border-radius:8px;padding:8px 10px;margin:6px 0}.cx-source-header{display:flex;align-items:center;gap:8px;margin-bottom:4px}.cx-source-name{font-weight:600;flex:1}.cx-source-tag{font-size:11px;padding:2px 8px;border-radius:99px}.cx-source-tag.ok{background:#dcfce7;color:#166534}.cx-source-tag.no{background:#f1f5f9;color:#64748b}.cx-debug-line{margin:8px 0;padding:8px 10px;background:#fff7ed;border:1px solid #fdba74;border-radius:8px;font-size:12px;color:#c2410c;font-weight:600}.cx-log-title{margin:12px 4px 6px;font-size:12px;font-weight:600;letter-spacing:.04em;color:var(--cx-text-secondary)}.cx-log-list{padding:16px}.cx-notice{padding:16px}}"); (async function (vue, pinia$1, ElementPlus, md5, $$1) { 'use strict'; var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; ((e) => { const t = GM_getResourceText(e); GM_addStyle(t); })("element-plus"); var _GM_getResourceText = (() => "undefined" != typeof GM_getResourceText ? GM_getResourceText : void 0)(), _GM_getValue = (() => "undefined" != typeof GM_getValue ? GM_getValue : void 0)(), _GM_info = (() => "undefined" != typeof GM_info ? GM_info : void 0)(), _GM_setValue = (() => "undefined" != typeof GM_setValue ? GM_setValue : void 0)(), _GM_xmlhttpRequest = (() => "undefined" != typeof GM_xmlhttpRequest ? GM_xmlhttpRequest : void 0)(), _unsafeWindow = (() => "undefined" != typeof unsafeWindow ? unsafeWindow : void 0)(); const encryptApiKey = (k) => k ? btoa(k.split("").reverse().join("")) : ""; const decryptApiKey = (e) => { if (!e) return ""; try { return atob(e).split("").reverse().join("") } catch { return e } }; const llmProviderPresets = [ { label: "自定义", value: "custom", baseUrl: "", suffix: "/chat/completions", models: [], apiKeyUrl: "" }, { label: "OpenAI", value: "openai", baseUrl: "https://api.openai.com/v1", suffix: "/chat/completions", models: [], apiKeyUrl: "https://platform.openai.com/api-keys" }, { label: "DeepSeek", value: "deepseek", baseUrl: "https://api.deepseek.com/v1", suffix: "/chat/completions", models: [], apiKeyUrl: "https://platform.deepseek.com/api_keys" }, { label: "Anthropic(Claude)", value: "anthropic", baseUrl: "https://api.anthropic.com/v1", suffix: "/chat/completions", models: [], apiKeyUrl: "https://console.anthropic.com/settings/keys" }, { label: "智谱GLM", value: "zhipu", baseUrl: "https://open.bigmodel.cn/api/paas/v4", suffix: "/chat/completions", models: [], apiKeyUrl: "https://open.bigmodel.cn/usercenter/apikeys" }, { label: "通义千问", value: "qwen", baseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1", suffix: "/chat/completions", models: [], apiKeyUrl: "https://bailian.console.aliyun.com/?apiKey=1" }, { label: "Kimi(Moonshot)", value: "kimi", baseUrl: "https://api.moonshot.cn/v1", suffix: "/chat/completions", models: [], apiKeyUrl: "https://platform.moonshot.cn/console/api-keys" }, { label: "小米Mimo", value: "mimo", baseUrl: "https://api.xiaomimimo.com/v1", suffix: "/chat/completions", models: [], apiKeyUrl: "https://platform.xiaomimimo.com/console/api-keys" } ]; const getConfig = () => { try { const gmConfig = _GM_getValue("config", null); if (gmConfig) { const parsed = typeof gmConfig === "string" ? JSON.parse(gmConfig) : gmConfig; if (parsed.llmApiKey) parsed.llmApiKey = decryptApiKey(parsed.llmApiKey); delete parsed.thtoken; delete parsed.yztoken; delete parsed.enncytoken; return { ...defaultConfig$1, ...parsed }; } } catch (e) { } const storage = (typeof _unsafeWindow !== 'undefined' && _unsafeWindow.top) ? _unsafeWindow.top.localStorage : localStorage; const config = storage.getItem("config"); if (config) { const parsed = JSON.parse(config); if (parsed.llmApiKey) parsed.llmApiKey = decryptApiKey(parsed.llmApiKey); delete parsed.thtoken; delete parsed.yztoken; delete parsed.enncytoken; return { ...defaultConfig$1, ...parsed }; } return { ...defaultConfig$1 }; }, defaultConfig$1 = { debugger: false, autoAnswer: true, autoVideo: true, autoJump: true, autoSubmit: true, llmApiKey: "", llmBaseUrl: "https://api.openai.com", llmModel: "", llmEnabled: false, llmTimeout: "30", llmMaxTokens: "1000", llmType: ["0", "1", "2", "3", "4", "5", "6", "7"], llmSuffix: "/chat/completions", llmProvider: "openai", llmWebSearch: false, llmSearchEngine: "baidu", llmSearchMode: "smart", interval: 3, answerInterval: 3, minAccuracy: 0.8, autoExam: true, hideExam: false, notice: "本脚本仅供学习交流使用,严禁用于商业用途,否则后果自负!" }, userConfig = [{ name: "quick", label: "快速配置", config: [{ name: "autoAnswer", label: "自动答题", type: "switch", value: defaultConfig$1.autoAnswer, desc: "开启后会自动答题" }, { name: "autoVideo", label: "自动视频", type: "switch", value: defaultConfig$1.autoVideo, desc: "开启后会自动观看视频" }, { name: "autoJump", label: "自动切换章节", type: "switch", value: defaultConfig$1.autoVideo, desc: "开启后会自动切换章节" }, { name: "autoSubmit", label: "自动提交答案", type: "switch", value: defaultConfig$1.autoSubmit, desc: "开启后自动提交答案" }, { name: "autoExam", label: "考试自动切换", type: "switch", value: defaultConfig$1.autoExam, desc: "开启后考试会自动切换" }, { name: "llmEnabled", label: "启用 LLM 智能答题", type: "switch", value: defaultConfig$1.llmEnabled, desc: "题库无答案时使用 AI 答题" }] }, { name: "base", label: "基础配置", config: [{ name: "interval", label: "通用间隔(秒)", type: "number", value: defaultConfig$1.interval, desc: "通用间隔,用于脚本运行切换" }, { name: "answerInterval", label: "答题间隔(秒)", type: "number", value: defaultConfig$1.answerInterval, desc: "控制答题速度" },] }, { name: "chapter", label: "章节配置", config: [{ name: "autoAnswer", label: "自动答题", type: "switch", value: defaultConfig$1.autoAnswer, desc: "开启后,会自动答题" }, { name: "autoVideo", label: "自动视频", type: "switch", value: defaultConfig$1.autoVideo, desc: "开启后,会自动观看视频" }, { name: "autoJump", label: "自动切换", type: "switch", value: defaultConfig$1.autoVideo, desc: "开启后,会自动切换章节" }, { name: "autoSubmit", label: "自动提交", type: "switch", value: defaultConfig$1.autoSubmit, desc: "开启后,会自动提交答案" }, { name: "minAccuracy", label: "最低正确率", type: "input", value: defaultConfig$1.minAccuracy, desc: "不满足最低正确率则不会自动提交答案" }] }, { name: "exam", label: "作业/考试配置", config: [{ name: "autoExam", label: "考试自动切换", type: "switch", value: defaultConfig$1.autoExam, desc: "开启后,会考试会自动切换" }] }, { name: "llm", label: "LLM配置", config: [{ name: "llmProvider", label: "供应商预设", type: "select", value: defaultConfig$1.llmProvider, desc: "选择供应商", options: llmProviderPresets.map(p => ({ label: p.label, value: p.value })) }, { name: "llmBaseUrl", label: "API Base URL", type: "input", value: defaultConfig$1.llmBaseUrl, desc: "API 基础地址,如 https://api.openai.com/v1" }, { name: "llmSuffix", label: "请求路径后缀", type: "input", value: defaultConfig$1.llmSuffix, desc: "拼接在 Base URL 后的路径,如 /chat/completions" }, { name: "llmApiKey", label: "API Key", type: "password", showPassword: true, value: defaultConfig$1.llmApiKey, desc: "LLM API 密钥" }, { name: "llmModel", label: "模型名称", type: "input", value: defaultConfig$1.llmModel, desc: "填写服务商当前有效的模型 ID,请以官方文档为准(脚本不预置推荐模型)" }, { name: "llmTimeout", label: "LLM 超时时间", type: "select", value: defaultConfig$1.llmTimeout, desc: "推理过长时选不设置,超时或报错自动跳过", options: [{ label: "30秒", value: "30" }, { label: "不设置", value: "0" }] }, { name: "llmMaxTokens", label: "最大输出 Token", type: "select", value: defaultConfig$1.llmMaxTokens, desc: "推理模型需要更大输出空间", options: [{ label: "1000", value: "1000" }, { label: "2000", value: "2000" }, { label: "4000", value: "4000" }, { label: "8000", value: "8000" }] }, { name: "llmEnabled", label: "启用 LLM 答题", type: "switch", value: defaultConfig$1.llmEnabled, desc: "开启后题库无答案时使用 LLM 进行答题" }, { name: "llmWebSearch", label: "启用联网搜索", type: "switch", value: defaultConfig$1.llmWebSearch, desc: "LLM 回答前先联网搜索相关资料" }, { name: "llmSearchEngine", label: "搜索引擎", type: "select", value: defaultConfig$1.llmSearchEngine, desc: "选择联网搜索引擎", options: [{ label: "百度", value: "baidu" }, { label: "Bing", value: "bing" }, { label: "DuckDuckGo", value: "duckduckgo" }] }, { name: "llmSearchMode", label: "搜索模式", type: "select", value: defaultConfig$1.llmSearchMode, desc: "始终搜索:每次都搜索;智能搜索:LLM 不确定时才搜索", options: [{ label: "始终搜索", value: "always" }, { label: "智能搜索", value: "smart" }] }, { name: "llmType", label: "允许使用 LLM 的题型", type: "checkbox", value: defaultConfig$1.llmType, desc: "选中后,将使用 LLM 回答对应题型", options: [{ label: "单选题", value: "0" }, { label: "多选题", value: "1" }, { label: "填空题", value: "2" }, { label: "判断题", value: "3" }, { label: "简答题", value: "4" }, { label: "名词解释", value: "5" }, { label: "论述题", value: "6" }, { label: "计算题", value: "7" }] }] }], useformStore = pinia$1.defineStore({ id: "formstore", state: () => ({ forminput: getConfig(), dialogV: false, activeName: "quick" }), actions: { saveConfig(forminput) { var config; config = { ...forminput }; if (config.llmApiKey) config.llmApiKey = encryptApiKey(config.llmApiKey); _GM_setValue("config", JSON.stringify(config)), (typeof _unsafeWindow !== 'undefined' && _unsafeWindow.top ? _unsafeWindow.top.localStorage : localStorage).setItem("config", JSON.stringify(config)); } } }); var export_helper_default = (sfc, props) => { let target = sfc.__vccOpts || sfc; for (let [key, val] of props) target[key] = val; return target; }, aim_vue_vue_type_script_lang_default = { name: "Aim" }, _hoisted_12$1 = { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 1024 1024" }, _hoisted_42 = [vue.createElementVNode("path", { fill: "currentColor", d: "M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768zm0 64a448 448 0 1 1 0-896 448 448 0 0 1 0 896z" }, null, -1), vue.createElementVNode("path", { fill: "currentColor", d: "M512 96a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V128a32 32 0 0 1 32-32zm0 576a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V704a32 32 0 0 1 32-32zM96 512a32 32 0 0 1 32-32h192a32 32 0 0 1 0 64H128a32 32 0 0 1-32-32zm576 0a32 32 0 0 1 32-32h192a32 32 0 1 1 0 64H704a32 32 0 0 1-32-32z" }, null, -1)]; var aim_default = export_helper_default(aim_vue_vue_type_script_lang_default, [["render", function (_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock("svg", _hoisted_12$1, _hoisted_42); }], ["__file", "aim.vue"]]), setting_vue_vue_type_script_lang_default = { name: "Setting" }, _hoisted_1231 = { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 1024 1024" }, _hoisted_3230 = [vue.createElementVNode("path", { fill: "currentColor", d: "M600.704 64a32 32 0 0 1 30.464 22.208l35.2 109.376c14.784 7.232 28.928 15.36 42.432 24.512l112.384-24.192a32 32 0 0 1 34.432 15.36L944.32 364.8a32 32 0 0 1-4.032 37.504l-77.12 85.12a357.12 357.12 0 0 1 0 49.024l77.12 85.248a32 32 0 0 1 4.032 37.504l-88.704 153.6a32 32 0 0 1-34.432 15.296L708.8 803.904c-13.44 9.088-27.648 17.28-42.368 24.512l-35.264 109.376A32 32 0 0 1 600.704 960H423.296a32 32 0 0 1-30.464-22.208L357.696 828.48a351.616 351.616 0 0 1-42.56-24.64l-112.32 24.256a32 32 0 0 1-34.432-15.36L79.68 659.2a32 32 0 0 1 4.032-37.504l77.12-85.248a357.12 357.12 0 0 1 0-48.896l-77.12-85.248A32 32 0 0 1 79.68 364.8l88.704-153.6a32 32 0 0 1 34.432-15.296l112.32 24.256c13.568-9.152 27.776-17.408 42.56-24.64l35.2-109.312A32 32 0 0 1 423.232 64H600.64zm-23.424 64H446.72l-36.352 113.088-24.512 11.968a294.113 294.113 0 0 0-34.816 20.096l-22.656 15.36-116.224-25.088-65.28 113.152 79.68 88.192-1.92 27.136a293.12 293.12 0 0 0 0 40.192l1.92 27.136-79.808 88.192 65.344 113.152 116.224-25.024 22.656 15.296a294.113 294.113 0 0 0 34.816 20.096l24.512 11.968L446.72 896h130.688l36.48-113.152 24.448-11.904a288.282 288.282 0 0 0 34.752-20.096l22.592-15.296 116.288 25.024 65.28-113.152-79.744-88.192 1.92-27.136a293.12 293.12 0 0 0 0-40.256l-1.92-27.136 79.808-88.128-65.344-113.152-116.288 24.96-22.592-15.232a287.616 287.616 0 0 0-34.752-20.096l-24.448-11.904L577.344 128zM512 320a192 192 0 1 1 0 384 192 192 0 0 1 0-384zm0 64a128 128 0 1 0 0 256 128 128 0 0 0 0-256z" }, null, -1)]; var setting_default = export_helper_default(setting_vue_vue_type_script_lang_default, [["render", function (_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock("svg", _hoisted_1231, _hoisted_3230); }], ["__file", "setting.vue"]]); const _sfc_main$1 = vue.defineComponent({ components: {}, setup() { const formstoreObj = useformStore(), { forminput, dialogV, activeName } = pinia$1.storeToRefs(formstoreObj); vue.watch(dialogV, v => { if (v) { const fresh = getConfig(); Object.assign(forminput.value, fresh); } }); const ruleFormRef = vue.ref(), rules = vue.reactive({ interval: [{ required: true, message: "间隔时间不能为空" }, { type: "number", message: "间隔时间必须为数字" }, { validator: (rule, value) => value >= 1 ? Promise.resolve() : Promise.reject("间隔时间必须大于等于1") }], answerInterval: [{ required: true, message: "答题间隔不能为空" }, { type: "number", message: "答题间隔必须为数字" }, { validator: (rule, value) => value >= 1 ? Promise.resolve() : Promise.reject("答题间隔必须大于等于1") }], token: [{ validator: (rule, value) => { if (value) { return /^[a-zA-Z0-9]{6,}$/.test(value) ? Promise.resolve() : Promise.reject("token格式错误"); } return Promise.resolve(); } }] }); const importDialogV = vue.ref(false), importText = vue.ref(''), currentProviderUrl = vue.ref((() => { const _p = llmProviderPresets.find(x => x.value === forminput.value.llmProvider); return _p ? _p.apiKeyUrl || '' : ''; })()); return { importDialogV, importText, currentProviderUrl, dialogV, activeName, ruleFormRef, forminput, rules, llmProviderPresets, onProviderChange: (v) => { const p = llmProviderPresets.find(x => x.value === v); if (p) { forminput.value.llmBaseUrl = p.baseUrl; forminput.value.llmSuffix = p.suffix || "/chat/completions"; currentProviderUrl.value = p.apiKeyUrl || ""; } }, isCustomProvider: vue.computed(() => forminput.value.llmProvider === "custom"), submitForm: async (formEl) => { formEl && await formEl.validate((valid, fields) => { valid && (formstoreObj.saveConfig(forminput.value), ElementPlus.ElNotification({ title: "Success", message: "配置保存成功,请自行刷新页面", type: "success" }), dialogV.value = false); }); }, exportConfig: () => { const _exp = { ...forminput.value }; delete _exp.thtoken; delete _exp.yztoken; delete _exp.enncytoken; const txt = JSON.stringify(_exp, null, 2); navigator.clipboard?.writeText(txt).then(() => ElementPlus.ElNotification({ title: '已导出', message: '配置已复制到剪贴板', type: 'success' })).catch(() => { const ta = document.createElement('textarea'); ta.value = txt; document.body.append(ta); ta.select(); document.execCommand('copy'); ta.remove(); ElementPlus.ElNotification({ title: '已导出', message: '配置已复制到剪贴板', type: 'success' }) }) }, importConfig: () => { importText.value = ''; importDialogV.value = true; }, doImport: () => { try { const parsed = JSON.parse(importText.value); if (parsed.llmApiKey === undefined) throw new Error('无效配置'); forminput.value = { ...forminput.value, ...parsed }; ElementPlus.ElNotification({ title: '已导入', message: '配置已加载,点击保存生效', type: 'success' }); importDialogV.value = false; } catch { ElementPlus.ElNotification({ title: '导入失败', message: 'JSON格式错误', type: 'error' }); } }, testLLM: async () => { const { llmApiKey, llmBaseUrl, llmModel, llmApiType } = forminput.value; if (!llmApiKey || !llmBaseUrl || !llmModel) { ElementPlus.ElNotification({ title: '测试失败', message: '请先填写完整的 LLM 配置', type: 'error' }); return } const suffix = forminput.value.llmSuffix || '/chat/completions'; const url = llmBaseUrl + suffix; const headers = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${llmApiKey}` }; const body = { model: llmModel, messages: [{ role: 'system', content: '只回复OK' }, { role: 'user', content: '测试' }], max_tokens: 10 }; ElementPlus.ElNotification({ title: '测试中', message: '正在连接 LLM 服务...', type: 'info' }); _GM_xmlhttpRequest({ method: 'POST', url, data: JSON.stringify(body), headers, timeout: 1e4, onload: (res) => { try { res.status === 200 ? ElementPlus.ElNotification({ title: '连接成功', message: `${llmModel} 响应正常`, type: 'success' }) : ElementPlus.ElNotification({ title: '连接失败', message: `HTTP ${res.status}: ${JSON.parse(res.responseText)?.error?.message || res.responseText?.slice(0, 100)}`, type: 'error' }) } catch { ElementPlus.ElNotification({ title: '连接失败', message: `HTTP ${res.status}`, type: 'error' }) } }, onerror: () => { ElementPlus.ElNotification({ title: '连接失败', message: '无法连接到 LLM 服务', type: 'error' }) }, ontimeout: () => { ElementPlus.ElNotification({ title: '连接超时', message: 'LLM 服务未响应', type: 'error' }) } }) }, userConfig, Setting: setting_default }; } }), _export_sfc = (sfc, props) => { const target = sfc.__vccOpts || sfc; for (const [key, val] of props) target[key] = val; return target; }, _hoisted_1$1 = { class: "dialog-footer" }; const App = _export_sfc(_sfc_main$1, [['render', function (e, l, o, t, a, n) { const u = vue.resolveComponent('el-button'), c = vue.resolveComponent('el-switch'), r = vue.resolveComponent('el-input'), m = vue.resolveComponent('el-option'), d = vue.resolveComponent('el-select'), v = vue.resolveComponent('el-checkbox'), i = vue.resolveComponent('el-checkbox-group'), p = vue.resolveComponent('el-tooltip'), s = vue.resolveComponent('el-form-item'), k = vue.resolveComponent('el-form'), V = vue.resolveComponent('el-dialog'); return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [vue.createVNode(u, { type: 'primary', id: 'csbutton', icon: e.Setting, circle: '', 'aria-label': '打开设置', onClick: l[0] || (l[0] = l => e.dialogV = !e.dialogV) }, null, 8, ['icon']), vue.createVNode(V, { modelValue: e.dialogV, 'onUpdate:modelValue': l[1] || (l[1] = l => e.dialogV = l), title: '超星学习通满分助手', width: '720px', modal: !1, center: '', appendToBody: !0, draggable: !0, class: 'cx-config-dialog', 'z-index': 1e5 }, { footer: vue.withCtx(() => [vue.createElementVNode('span', _hoisted_1$1, [vue.createVNode(u, { onClick: l[2] || (l[2] = l => e.dialogV = !1) }, { default: vue.withCtx(() => [vue.createTextVNode('取消')]), _: 1 }), vue.createVNode(u, { type: 'primary', onClick: l[3] || (l[3] = l => e.submitForm(e.ruleFormRef)) }, { default: vue.withCtx(() => [vue.createTextVNode('保存')]), _: 1 })])]), default: vue.withCtx(() => [vue.createVNode(k, { ref: 'ruleFormRef', rules: e.rules, model: e.forminput, class: 'demo-ruleForm', 'label-position': 'top' }, { default: vue.withCtx(() => [vue.createElementVNode('div', { class: 'cx-config-layout' }, [vue.createElementVNode('div', { class: 'cx-config-nav' }, [(vue.openBlock(!0), vue.createElementBlock(vue.Fragment, null, vue.renderList(e.userConfig, l => (vue.openBlock(), vue.createElementBlock('button', { key: l.name, type: 'button', class: vue.normalizeClass(['cx-config-nav-item', { active: e.activeName === l.name }]), onClick: o => e.activeName = l.name }, vue.toDisplayString(l.label), 11, ['class', 'onClick']))), 128))]), vue.createElementVNode('div', { class: 'cx-config-content' }, [(vue.openBlock(!0), vue.createElementBlock(vue.Fragment, null, vue.renderList(e.userConfig, l => (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: l.name }, [e.activeName === l.name ? (vue.openBlock(), vue.createElementBlock('div', { key: 0 }, [vue.createElementVNode('div', { class: 'cx-config-section-title' }, vue.toDisplayString(l.label), 1), vue.createElementVNode('div', { class: 'cx-config-section-desc' }, '调整以下选项以自定义脚本行为', -1), (vue.openBlock(!0), vue.createElementBlock(vue.Fragment, null, vue.renderList(l.config, l => (vue.openBlock(), vue.createBlock(s, { label: l.label, prop: l.name }, { default: vue.withCtx(() => [vue.createVNode(p, { class: 'box-item', effect: 'dark', content: l.desc || '', placement: 'top', teleported: !1 }, { default: vue.withCtx(() => ['switch' === l.type ? (vue.openBlock(), vue.createBlock(c, { key: 0, modelValue: e.forminput[l.name], 'onUpdate:modelValue': o => e.forminput[l.name] = o }, null, 8, ['modelValue', 'onUpdate:modelValue'])) : 'password' === l.type ? (vue.openBlock(), vue.createBlock(r, { key: 1, modelValue: e.forminput[l.name], 'onUpdate:modelValue': o => e.forminput[l.name] = o, type: 'password', showPassword: !0 }, null, 8, ['modelValue', 'onUpdate:modelValue'])) : 'input' === l.type && 'llmBaseUrl' === l.name ? (vue.openBlock(), vue.createBlock(r, { key: 1, modelValue: e.forminput[l.name], 'onUpdate:modelValue': o => e.forminput[l.name] = o, disabled: !e.isCustomProvider }, null, 8, ['modelValue', 'onUpdate:modelValue', 'disabled'])) : 'input' === l.type ? (vue.openBlock(), vue.createBlock(r, { key: 1, modelValue: e.forminput[l.name], 'onUpdate:modelValue': o => e.forminput[l.name] = o }, null, 8, ['modelValue', 'onUpdate:modelValue'])) : 'number' === l.type ? (vue.openBlock(), vue.createBlock(r, { key: 2, modelValue: e.forminput[l.name], 'onUpdate:modelValue': o => e.forminput[l.name] = 1 * o, type: 'number', min: '1', style: { width: '120px' } }, null, 8, ['modelValue', 'onUpdate:modelValue'])) : 'select' === l.type && 'llmProvider' === l.name ? (vue.openBlock(), vue.createElementBlock('div', { key: 3, style: { display: 'flex', alignItems: 'center', gap: '8px' } }, [vue.createVNode(d, { modelValue: e.forminput[l.name], 'onUpdate:modelValue': o => { e.forminput[l.name] = o, e.onProviderChange(o) }, placeholder: '请选择', teleported: !1 }, { default: vue.withCtx(() => [(vue.openBlock(!0), vue.createElementBlock(vue.Fragment, null, vue.renderList(l.options, e => (vue.openBlock(), vue.createBlock(m, { key: e.value, label: e.label, value: e.value }, null, 8, ['label', 'value']))), 128))]), _: 2 }, 1032, ['modelValue', 'onUpdate:modelValue']), e.currentProviderUrl ? (vue.openBlock(), vue.createElementBlock('a', { key: 0, href: e.currentProviderUrl, target: '_blank', style: { fontSize: '12px', color: '#409eff', whiteSpace: 'nowrap', textDecoration: 'none' } }, '获取 API Key')) : vue.createCommentVNode('', !0)])) : 'select' === l.type ? (vue.openBlock(), vue.createBlock(d, { key: 3, modelValue: e.forminput[l.name], 'onUpdate:modelValue': o => e.forminput[l.name] = o, placeholder: '请选择', teleported: !1 }, { default: vue.withCtx(() => [(vue.openBlock(!0), vue.createElementBlock(vue.Fragment, null, vue.renderList(l.options, e => (vue.openBlock(), vue.createBlock(m, { key: e.value, label: e.label, value: e.value }, null, 8, ['label', 'value']))), 128))]), _: 2 }, 1032, ['modelValue', 'onUpdate:modelValue'])) : 'checkbox' === l.type ? (vue.openBlock(), vue.createBlock(i, { key: 4, modelValue: e.forminput[l.name], 'onUpdate:modelValue': o => e.forminput[l.name] = o, class: 'cx-checkbox-horizontal' }, { default: vue.withCtx(() => [(vue.openBlock(!0), vue.createElementBlock(vue.Fragment, null, vue.renderList(l.options, e => (vue.openBlock(), vue.createBlock(v, { key: e.value, label: e.value, name: e.value }, { default: vue.withCtx(() => [vue.createTextVNode(vue.toDisplayString(e.label), 1)]), _: 2 }, 1032, ['label', 'name']))), 128))]), _: 2 }, 1032, ['modelValue', 'onUpdate:modelValue'])) : vue.createCommentVNode('', !0)]), _: 2 }, 1032, ['content'])]), _: 2 }, 1032, ['label', 'prop']))), 256)), 'llm' === l.name ? (vue.openBlock(), vue.createElementBlock('div', { key: 'llm-actions', class: 'cx-config-actions' }, [vue.createVNode(u, { size: 'small', onClick: e.exportConfig }, { default: vue.withCtx(() => [vue.createTextVNode('导出配置')]), _: 1 }, 8, ['onClick']), vue.createVNode(u, { size: 'small', onClick: e.importConfig }, { default: vue.withCtx(() => [vue.createTextVNode('导入配置')]), _: 1 }, 8, ['onClick']), vue.createVNode(u, { size: 'small', type: 'success', plain: '', onClick: e.testLLM }, { default: vue.withCtx(() => [vue.createTextVNode('测试 LLM')]), _: 1 }, 8, ['onClick'])])) : vue.createCommentVNode('', !0)])) : vue.createCommentVNode('', !0)]))), 128))])])]), _: 1 }, 8, ['rules', 'model'])]), _: 1 }, 8, ['modelValue']), vue.createVNode(V, { modelValue: e.importDialogV, 'onUpdate:modelValue': l[5] || (l[5] = l => e.importDialogV = l), title: '导入配置', width: '400px', modal: !1, center: '', 'z-index': 100001 }, { footer: vue.withCtx(() => [vue.createElementVNode('span', null, [vue.createVNode(u, { onClick: l[6] || (l[6] = l => e.importDialogV = !1) }, { default: vue.withCtx(() => [vue.createTextVNode('取消')]), _: 1 }), vue.createVNode(u, { type: 'primary', onClick: e.doImport }, { default: vue.withCtx(() => [vue.createTextVNode('确定')]), _: 1 })])]), default: vue.withCtx(() => [vue.createElementVNode('p', { style: { 'margin-bottom': '8px', color: '#64748b', 'font-size': '13px' } }, '请粘贴配置JSON'), vue.createVNode(r, { modelValue: e.importText, 'onUpdate:modelValue': l[4] || (l[4] = l => e.importText = l), type: 'textarea', rows: 6, placeholder: '{ "interval": 3, ... }' }, null, 8, ['modelValue'])]), _: 1 }, 8, ['modelValue'])], 64) }], ['__scopeId', 'data-v-6ed29f7f']]); let defaultConfig = getConfig(); class ServerApi { constructor(window2 = _unsafeWindow) { __publicField(this, "windowz", _unsafeWindow); __publicField(this, "apiIcodef", "http://cx.icodef.com/wyn-nb?v=4"); this.windowz = window2; } async defaultRequest(url, method, data = {}, headers = {}, type = false) { var _a; return type && (headers = { "Content-Type": "POST" == method ? "application/json" : "text/plain", Referer: (this.windowz && this.windowz.location && this.windowz.location.href) || "", v: _GM_info.script.version, uid: _unsafeWindow.uid || ((_a = _unsafeWindow == null ? void 0 : _unsafeWindow.getCookie) == null ? void 0 : _a.call(_unsafeWindow, "_uid")) || "", ...headers }), new Promise((resolve, reject) => { _GM_xmlhttpRequest({ method, url, data: JSON.stringify(data), headers, timeout: 1e4, onload: (res) => { resolve(res); }, ontimeout: () => { reject("timeout"); }, onerror: (err) => { reject(err); } }); }); } async getAnswerIcodef(questionData) { let ip = Array.from({ length: 4 }, () => Math.floor(255 * Math.random())).join("."); return new Promise((resolve) => { const ques = { question: questionData.question }; this.defaultRequest(this.apiIcodef, "POST", ques, { "Content-Type": "application/json", "X-Forwarded-For": ip, "X-Real-IP": ip }).then((response) => { const res = JSON.parse(response.responseText); let answer = ""; if (1 === res.code) { let data = res.data.replace(/javascript:void\(0\);/g, "").trim().replace(/\n/g, ""); data.includes("叛逆") || data.includes("公众号") || data.includes("李恒雅") || data.includes("一之") || (answer = data.split("#")); } resolve({ form: "icodef题库", answer }); }).catch(() => { resolve({ form: "icodef题库", answer: "" }); }); }); } getSearchCountByType(questionType) { const countMap = { "0": 2, "1": 3, "2": 3, "3": 2, "4": 5, "5": 5, "6": 5, "7": 5 }; return countMap[questionType] || 3; } async searchBaidu(query, count) { return new Promise((resolve) => { const url = "https://www.baidu.com/s?wd=" + encodeURIComponent(query) + "&rn=" + count; _GM_xmlhttpRequest({ method: "GET", url, headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" }, timeout: 10000, onload: (res) => { try { const html = res.responseText; const results = []; const itemRegex = /
([\s\S]*?)<\/p>/i) || block.match(/
]*>([\s\S]*?)<\/p>/i); const snippet = snippetMatch ? snippetMatch[1].replace(/<[^>]+>/g, "").trim() : ""; if (title && url) results.push({ title, snippet, url }); } // 2. 兜底:使用更宽泛的正则 if (results.length === 0) { const fallbackRegex = /
禁止用于各种非法用途,否则后果自负
本脚本题库接口均来源于网络以及用户反馈添加,不对题库准确率以及可用性负责,请自行判断、评估是否使用。
"); return { count, dialogVisible, questionList, task, tick, askActiveName, msg, Aim: aim_default, handleClick: (e) => { askstore.select(e); } }; } }); const Ask = _export_sfc(_sfc_main, [["render", function (_ctx, _cache, $props, $setup, $data, $options) { const S = askUI; const qlist = S.task.work.questionList.slice(); const hasQ = qlist.length > 0; const hasVideo = !!(S.task.video && S.task.video.status); const hasTask = hasQ || hasVideo || (S.task.name && S.task.name !== "暂未加载" && S.task.name !== ""); const show = hasTask && !!S.dialogVisible; const inx = S.task.work.inx; const viewInx = (S.task.work.viewInx != null) ? S.task.work.viewInx : inx; const cur = hasQ ? qlist[viewInx] : null; const progressText = hasQ ? ((inx + 1) + "/" + qlist.length) : ""; const viewingOther = hasQ && viewInx !== inx; const panelStyle = { display: show ? "block" : "none", left: (S.panelLeft != null ? S.panelLeft + "px" : undefined), top: (S.panelTop != null ? S.panelTop + "px" : undefined), right: (S.panelLeft != null ? "auto" : "24px") }; const fabStyle = { display: (hasTask && !S.dialogVisible) ? "flex" : "none" }; const text = (s) => vue.createTextVNode(String(s == null ? "" : s)); return vue.createElementVNode("div", { id: "cx-ask-root" }, [ vue.createElementVNode("button", { id: "cx-ask-fab", class: "cx-fab", style: fabStyle, title: "打开答题控制台", onClick: _cache[3] || (_cache[3] = ($event) => { S.dialogVisible = true; S.panelCollapsed = false; }) }, [text(hasQ ? ("◉ " + progressText) : (hasVideo ? "◉ 视频" : "◉"))]), vue.createElementVNode("div", { id: "cx-ask-panel", class: vue.normalizeClass(["cx-ask-panel", S.panelCollapsed ? "collapsed" : ""]), style: panelStyle }, [ vue.createElementVNode("div", { class: "cx-drag-bar", onMousedown: _cache[2] || (_cache[2] = function (e) { if (e.button !== 0) return; if (e.target && e.target.closest && e.target.closest("button")) return; const panel = document.getElementById("cx-ask-panel"); if (!panel) return; const startX = e.clientX, startY = e.clientY; const rect = panel.getBoundingClientRect(); const startLeft = rect.left, startTop = rect.top; panel.style.right = "auto"; panel.style.left = startLeft + "px"; panel.style.top = startTop + "px"; const onMove = function (ev) { const nl = Math.max(0, startLeft + ev.clientX - startX); const nt = Math.max(0, startTop + ev.clientY - startY); panel.style.left = nl + "px"; panel.style.top = nt + "px"; S.panelLeft = nl; S.panelTop = nt; }; const onUp = function () { document.removeEventListener("mousemove", onMove); document.removeEventListener("mouseup", onUp); }; document.addEventListener("mousemove", onMove); document.addEventListener("mouseup", onUp); e.preventDefault(); }) }, [ vue.createElementVNode("span", { class: "cx-drag-title" }, [text(S.task.name || "答题控制台")]), vue.createElementVNode("span", { class: vue.normalizeClass(["cx-badge", hasVideo && !hasQ ? "warn" : ""]) }, [text(hasQ ? ("进度 " + progressText + (viewingOther ? (" · 看第" + (viewInx + 1) + "题") : "")) : (hasVideo ? "视频任务中" : ""))]), viewingOther ? (vue.openBlock(), vue.createElementBlock("button", { key: 1, class: "cx-follow-btn", onClick: _cache[4] || (_cache[4] = ($event) => { S.followLatest(); }) }, [text("回到最新")])) : vue.createCommentVNode("", true), vue.createElementVNode("button", { class: "cx-panel-toggle pause", title: S.paused ? "继续答题" : "暂停答题", onClick: _cache[5] || (_cache[5] = ($event) => { S.togglePause(); }) }, [text(S.paused ? "▶" : "⏸")]), vue.createElementVNode("button", { class: "cx-panel-toggle", title: S.panelCollapsed ? "展开" : "收起", onClick: _cache[0] || (_cache[0] = ($event) => { S.panelCollapsed = !S.panelCollapsed; }) }, [text(S.panelCollapsed ? "+" : "−")]), vue.createElementVNode("button", { class: "cx-panel-close", title: "最小化", onClick: _cache[1] || (_cache[1] = ($event) => { S.dialogVisible = false; }) }, [text("×")]) ]), vue.createElementVNode("div", { class: "cx-panel-body", style: { display: S.panelCollapsed ? "none" : "block" } }, [ vue.createElementVNode("div", { class: "cx-video-tip", style: { display: hasVideo ? "block" : "none" } }, [text("正在完成视频任务")]), vue.createElementVNode("div", { class: "cx-q-block", style: { display: hasQ ? "block" : "none" } }, [ vue.createElementVNode("div", { class: "cx-q-title" }, [text((inx + 1) + ". " + ((cur && cur.question) || ""))]), vue.createElementVNode("pre", { class: "cx-question-answer", style: { display: (cur && cur.answer) ? "block" : "none" } }, [text((cur && cur.answer) || "")]), vue.createElementVNode("div", { class: "cx-q-nav" }, qlist.map((item, index) => vue.createElementVNode("button", { key: index, class: vue.normalizeClass(["question_btn", item.status || "info", index === viewInx ? "active" : ""]), onClick: () => _ctx.handleClick(index) }, [text(index + 1)])) ), vue.createElementVNode("div", { class: "cx-source-block", style: { display: (cur && cur.allAnswer && cur.allAnswer.length) ? "block" : "none" } }, [ vue.createElementVNode("div", { class: "cx-log-title" }, [text("接口返回")]), vue.createElementVNode("div", { class: "cx-source-list" }, ((cur && cur.allAnswer) || []).map((item, index) => vue.createElementVNode("div", { key: index, class: "cx-source-item" }, [ vue.createElementVNode("div", { class: "cx-source-header" }, [ vue.createElementVNode("span", { class: "cx-source-name" }, [text(item.form || ("来源" + index))]), vue.createElementVNode("span", { class: vue.normalizeClass(["cx-source-tag", item.answer ? "ok" : "no"]) }, [text(item.answer ? "有答案" : "暂无")]) ]), vue.createElementVNode("div", { class: "cx-source-answer", innerHTML: item.answer || "暂无答案" }) ])) ) ]) ]), vue.createElementVNode("div", { class: "cx-log-block", style: { display: (S.task.log && S.task.log.length) ? "block" : "none" } }, [ vue.createElementVNode("div", { class: "cx-log-title" }, [text("日志")]), vue.createElementVNode("div", { class: "cx-log-list" }, (S.task.log || []).slice(-8).map((item, index) => vue.createElementVNode("div", { key: index, class: "cx-log-item" }, [ vue.createElementVNode("span", { class: vue.normalizeClass(["cx-log-msg", item.type]) }, [text(item.msg)]) ])) ) ]) ]) ]) ]); }], ["__scopeId", "data-v-c3c6b09f"]]); function ensureAskPanel() { try { if (_unsafeWindow && _unsafeWindow.top) _unsafeWindow.top.__cxAskStore = askUI; if (typeof window !== "undefined" && window.top) window.top.__cxAskStore = askUI; } catch (e) { } let hostWin = null; try { hostWin = _unsafeWindow.top; } catch (e) { hostWin = _unsafeWindow; } if (!hostWin) hostWin = _unsafeWindow; if (hostWin.__cxAskApp) return askUI; try { hostWin.__cxAskApp = true; const hostDoc = hostWin.document || document; try { hostDoc.querySelectorAll("#zeokdjg, #xxxxzx").forEach((el) => el.remove()); } catch (e) { } const askApp = vue.createApp(Ask).use(ElementPlus).use(pinia); askApp.mount((() => { const div = hostDoc.createElement("div"); div.id = "xxxxzx"; hostDoc.body.append(div); return div; })()); hostWin.__cxAskApp = askApp; } catch (e) { try { hostWin.__cxAskApp = false; } catch (e2) { } console.error("[满分助手] 运行面板挂载失败", e); } return askUI; } class Cx { constructor() { __publicField(this, "app"); __publicField(this, "askStore"); __publicField(this, "ServerApi"); __publicField(this, "defaultConfig"); this.askStore = ensureAskPanel(), this.askStore.dialogVisible = true, this.ServerApi = new ServerApi(), this.defaultConfig = getConfig(); } innerbook() { } async audio(iframeWindow) { this.askStore.reset(), this.askStore.task.name = "视频音频"; const audio = iframeWindow.document.getElementById("audio_html5_api"); return audio.muted = true, audio.autoplay = true, audio.volume = 0, audio.play().then(function () { console.log("播放成功"); }).catch(function (error) { "NotAllowedError" === error.name ? ElementPlus.ElMessageBox.alert("由于自动播放需要用户点击过浏览器,请确认即可", "温馨提示", { confirmButtonText: "确认", callback: () => { audio.play(); } }) : console.error("视频播放失败,原因:", error); }), new Promise((resolve) => { const intervalId = setInterval(() => { audio.ended ? (clearInterval(intervalId), log("监听到音频已完成", "success"), resolve()) : audio.paused && audio.play(); }, 1e3); audio.addEventListener("ended", function () { log("监听到音频已完成1", "success"), audio.pause(), clearInterval(intervalId), resolve(); }); }); } async video(iframeWindow) { this.askStore.reset(), this.askStore.task.name = "视频", this.askStore.task.video.status = 1, await waitElementLoaded(iframeWindow, "#video_html5_api"), console.log("视频加载完成"); const player = iframeWindow.videojs("video_html5_api"), playerButton = iframeWindow.document.querySelector(".vjs-big-play-button"); player.muted(true), player.playbackRate(16), player.play(), await new Promise((resolve) => { const intervalId = setInterval(() => { "isUnFinishJob" in iframeWindow && iframeWindow.isUnFinishJob() ? player.paused() && (playerButton == null ? void 0 : playerButton.click()) : (clearInterval(intervalId), resolve()); }, 1e3), pauseBase = player.pause; player.pause = function () { player.currentTime() >= player.duration() && (console.log("视频播放完成"), player.pause = pauseBase, resolve()); }, player.on("ended", () => { console.log("视频播放完成1"), player.pause = pauseBase, player.pause(), clearInterval(intervalId), resolve(); }); }), console.log("任务点完成"); } work(iframeWindow) { return new Promise(async (resolve) => { if (!iframeWindow || !iframeWindow.document) { resolve(); return; } decode(iframeWindow); const Timu = iframeWindow.document.querySelectorAll(".TiMu"); if (!Timu) return void resolve(); let ques = [], succ = 0; for (let i = 0; i < Timu.length; i++) { let data = getQuestion("1", Timu[i]); console.log(data), ques.push(data); } this.askStore.reset(), this.askStore.count = ques.length, this.askStore.task.name = "章节测验"; for (let i = 0; i < ques.length; i++) { await this.askStore.waitIfPaused(); await sleep(this.defaultConfig.answerInterval), this.askStore.insert(ques[i]), this.askStore.task.work.inx = i; if (this.askStore.task.work.follow !== false) this.askStore.task.work.viewInx = i; let data = await getAnswers(ques[i], iframeWindow); this.askStore.patch(i, { allAnswer: data }); let tmp = fillAnswer(data, ques[i], Timu[i], iframeWindow); if (!tmp && this.defaultConfig.llmEnabled && this.defaultConfig.llmApiKey && this.defaultConfig.llmBaseUrl) { const questionType = ques[i].type; if (this.defaultConfig.llmType && Array.isArray(this.defaultConfig.llmType) && this.defaultConfig.llmType.includes(questionType)) { let llmResult = await this.ServerApi.getAnswerByLLM(ques[i]); data.push(llmResult); tmp = fillAnswer([llmResult], ques[i], Timu[i], iframeWindow); } } tmp ? (this.askStore.patch(i, { status: "primary", answer: tmp }), succ++) : (this.askStore.patch(i, { status: "danger", answer: "暂无答案" })), this.askStore.patch(i, { dom: Timu[i] }); } this.defaultConfig.autoSubmit ? (succ / ques.length < this.defaultConfig.minAccuracy ? (this.askStore.log("章节测验正确率不足,暂存", "error"), iframeWindow.alert = function (e) { console.log("alert 方法被阻止", e); }, iframeWindow.noSubmit()) : (iframeWindow.btnBlueSubmit(), await sleep(3), iframeWindow.submitCheckTimes(), this.askStore.log("章节测验已完成", "success")), this.askStore.task.status = `章节测验已完成,等待切换,正确率:${succ}/${ques.length}`, resolve()) : (this.askStore.log("已完成答题,未开启自动提交,等待手动提交中", "success"), this.askStore.task.status = `正在等待手动提交,正确率:${succ}/${ques.length}`); }); } homework() { return new Promise(async (resolve) => { const Timu = _unsafeWindow.document.querySelectorAll(".questionLi"); if (!Timu) return void resolve(); let ques = []; for (let i = 0; i < Timu.length; i++) { let data = getQuestion("2", Timu[i]); ques.push(data); } this.askStore.reset(), this.askStore.count = ques.length, this.askStore.task.name = "作业"; for (let i = 0; i < ques.length; i++) { await this.askStore.waitIfPaused(); await sleep(this.defaultConfig.answerInterval), this.askStore.insert(ques[i]), this.askStore.task.work.inx = i; if (this.askStore.task.work.follow !== false) this.askStore.task.work.viewInx = i; let data = await getAnswers(ques[i]); this.askStore.patch(i, { allAnswer: data }); let tmp = fillAnswer(data, ques[i], Timu[i], _unsafeWindow); if (!tmp && this.defaultConfig.llmEnabled && this.defaultConfig.llmApiKey && this.defaultConfig.llmBaseUrl) { const questionType = ques[i].type; if (this.defaultConfig.llmType && Array.isArray(this.defaultConfig.llmType) && this.defaultConfig.llmType.includes(questionType)) { let llmResult = await this.ServerApi.getAnswerByLLM(ques[i]); data.push(llmResult); tmp = fillAnswer([llmResult], ques[i], Timu[i], _unsafeWindow); } } tmp ? (this.askStore.patch(i, { status: "primary", answer: tmp })) : (this.askStore.patch(i, { status: "danger", answer: "暂无答案" })), this.askStore.patch(i, { dom: Timu[i] }); } }); } exam() { return new Promise(async (resolve) => { this.askStore.reset(), this.askStore.count = 1, this.askStore.task.name = "考试"; let data = getQuestion("3", _unsafeWindow.document.body); this.askStore.insert(data), this.askStore.task.work.inx = 0; if (this.askStore.task.work.follow !== false) this.askStore.task.work.viewInx = 0; let data1 = await getAnswers(data); this.askStore.patch(0, { allAnswer: data1 }); let tmp = fillAnswer(data1, data, document.getElementsByClassName("mark_table")[0], _unsafeWindow); if (!tmp && this.defaultConfig.llmEnabled && this.defaultConfig.llmApiKey && this.defaultConfig.llmBaseUrl) { const questionType = data.type; if (this.defaultConfig.llmType && Array.isArray(this.defaultConfig.llmType) && this.defaultConfig.llmType.includes(questionType)) { let llmResult = await this.ServerApi.getAnswerByLLM(data); data1.push(llmResult); tmp = fillAnswer([llmResult], data, document.getElementsByClassName("mark_table")[0], _unsafeWindow); } } if (tmp ? (this.askStore.patch(0, { status: "primary", answer: tmp })) : (this.askStore.patch(0, { status: "danger", answer: "暂无答案" })), this.defaultConfig.autoExam) { await this.askStore.waitIfPaused(); await sleep(this.defaultConfig.answerInterval); const nextButton = $('.nextDiv .jb_btn:contains("下一题")'); nextButton ? nextButton.click() : (this.askStore.log("已完成答题,请自行检查答案填写后自行提交", "success"), this.askStore.task.status = "已完成答题,请自行检查答案填写后自行提交"); } else this.askStore.task.status = "未开启自动切换,等待手动切换"; }); } pdf(iframeWindow) { return new Promise(async (resolve) => { const contentWindow = iframeWindow.document.querySelector("#panView").contentWindow; contentWindow.scrollTo(0, contentWindow.document.body.scrollHeight), resolve(); }); } async s(iframeWindow) { if (!iframeWindow || !iframeWindow.document) return; const questionList = $(iframeWindow.document).find(".TiMu").map(function (index, element) { try { let questionHtml, questionText, questionType$1, questionAnswer, questionOption = [], questionAnalysis = ""; switch (questionHtml = $(element).find(".Zy_TItle .clearfix"), questionText = removeHtml(questionHtml[0].innerHTML), questionType$1 = questionText.match(/^\【(.+?)\】/)[1], questionText = questionText.replace(questionText.match(/^\【(.+?)\】/)[0], ""), questionType$1) { case "单选题": case "多选题": return questionOption = $(element).find("ul>li").map(function (inx, item) { return removeHtml($(item).find("a").html()); }).get(), null; case "判断题": if (questionAnalysis = removeHtml($(element).find(".Py_addpy:eq(0)").html() || ""), element.innerHTML.includes("正确答案")) questionAnswer = removeHtml($(element).find(".Py_answer.clearfix>span").html()); else { const match = $(element).find(".Py_answer.clearfix").html().match(/^(.*?)(?=<\/i>)/s), result = match ? match[1] : ""; questionAnswer = removeHtml(result); } if (questionAnswer.includes("正确答案")) questionAnswer = questionAnswer.replace("正确答案:", "").trim(); else if ($(element).find(".fr.dui").length > 0) questionAnswer = questionAnswer.replace("我的答案:", "").trim(); else { if (!questionAnswer.replace("我的答案:", "").trim().includes("√") && !questionAnswer.replace("我的答案:", "").trim().includes("×")) return null; questionAnswer = "√" == questionAnswer.replace("我的答案:", "").trim() ? "×" : "√"; } break; case "填空题": if (questionAnswer = $("span.font14", $(element)).map(function (inx, item) { return removeHtml($(item).html()).replace(/^第.空:/, "").trim(); }).get(), 0 == questionAnswer.length) { if (questionAnswer = $(element).find(".Py_answer.clearfix>div>div[class='font14']"), !(questionAnswer.length = $(element).find(".Py_answer.clearfix>div>div[class='font14']>>.fr.dui").length)) return null; questionAnswer = questionAnswer.map(function (inx, item) { return removeHtml($(item).html()).replace(/^第.空:/, "").trim(); }).get(); } break; default: return null; } return { question: questionText, options: questionOption, type: questionType[questionType$1], answer: questionAnswer }; } catch { return null; } }).get(); try { const pageHref = (iframeWindow && iframeWindow.location && iframeWindow.location.href) || (typeof _unsafeWindow !== "undefined" && _unsafeWindow.location && _unsafeWindow.location.href) || ""; await this.ServerApi.s(questionList, pageHref); } catch (e) { console.error("[满分助手] s() 失败", e); } } } const pinia = pinia$1.createPinia(), app = vue.createApp(App).use(ElementPlus).use(pinia), _self = _unsafeWindow, top = _self.top, formStore = useformStore(); var iframeCom = null; switch ((() => { try { if (top.__cxConfigApp) return; top.__cxConfigApp = true; const div = top.document.createElement("div"); div.id = "cccxapp"; var old = top.document.getElementById("cccxapp"); if (old) old.remove(); top.document.querySelectorAll("#csbutton").forEach((el) => el.remove()); top.document.body.append(div); app.mount(div); top.__cxConfigApp = app; } catch (e) { try { top.__cxConfigApp = false; } catch (e2) { } log(e, "error"); } })(), (() => { try { if (_self === top) ensureAskPanel(); } catch (e) { } })(), (() => { document.body.oncopy = null, document.body.oncut = null, document.body.onpaste = null, document.body.onselectstart = null, document.body.ondragstart = null; const style = document.createElement("style"); style.innerHTML = "\n * {\n -webkit-user-select: auto !important;\n -moz-user-select: auto !important;\n -o-user-select: auto !important;\n user-select: auto !important;\n }\n ", document.head.appendChild(style); })(), _self.location.pathname) { case "/work/doHomeWorkNew": case "/mooc-ans/work/doHomeWorkNew": case "/mooc2-ans/work/doHomeWorkNew": if (location.href.includes("mooc2=1")) { location.href = location.href.replace(/&mooc2=1/g, ""); break; } if (_self !== top) break; { const cxHw = new Cx(); const llmHw = getConfig(); cxHw.askStore.log("脚本初始化成功!", "success"); if (llmHw.llmEnabled) cxHw.askStore.log("[LLM] 已启用,模型: " + llmHw.llmModel, "success"); else cxHw.askStore.log("[LLM] 未启用,请在配置中开启", "info"); cxHw.askStore.msg("正在答题"); await (cxHw.homework()); } break; case "/mycourse/studentstudy": case "/mooc-ans/mycourse/studentstudy": case "/mooc2-ans/mycourse/studentstudy": if (_self !== top) break; if (!_self.location.href.match(/mooc2=1/)) { ElementPlus.ElNotification({ title: "Auto Ask", message: "暂不支持旧版章节,尝试切换至新版", type: "error" }), _self.location.href = _self.location.href + "&mooc2=1"; break; } const cxModel = new Cx(); const llmConfig = getConfig(); console.log("[LLM] 初始化配置检查:", JSON.stringify({ llmEnabled: llmConfig.llmEnabled, llmApiKey: llmConfig.llmApiKey ? "***" + llmConfig.llmApiKey.slice(-4) : "未设置", llmBaseUrl: llmConfig.llmBaseUrl, llmModel: llmConfig.llmModel, llmType: llmConfig.llmType }, null, 2)); cxModel.askStore.log("脚本初始化成功!", "success"); if (llmConfig.llmEnabled) { cxModel.askStore.log("[LLM] 已启用,模型: " + llmConfig.llmModel, "success"); } else { cxModel.askStore.log("[LLM] 未启用,请在配置中开启", "info"); } const startWork = async () => { var _a, _b, _c, _d, _e; await waitElementLoaded(_self, "#iframe"); const cardsIframe = _self.document.querySelector("#iframe"); await waitIframeLoaded(cardsIframe); const _self1 = cardsIframe && cardsIframe.contentWindow; if (!_self1) return; top.scroll2Job(); let jobList = _self1.document.querySelectorAll(".ans-job-icon") || []; for (let i = 0; i < jobList.length; i++) { const item = jobList[i]; if ((_a = item.parentElement) == null ? void 0 : _a.classList.contains("ans-job-finished")) { const iframe = (_b = item.parentElement) == null ? void 0 : _b.querySelector("iframe"); if (iframe == null ? void 0 : iframe.src.match(/\/ananas\/modules\/work\/index.html/)) { await waitIframeLoaded(iframe), JSON.parse(iframe.getAttribute("data")); const workIframe = (_c = iframe.contentWindow) == null ? void 0 : _c.document.querySelector("iframe"); workIframe && (await waitIframeLoaded(workIframe), cxModel.s(workIframe.contentWindow)); } console.log(iframe.src, "已完成"), cxModel.askStore.log("已完成的任务点,跳过"); } else { const iframe = (_d = item.parentElement) == null ? void 0 : _d.querySelector("iframe"); await waitIframeLoaded(iframe); const otherInfo = JSON.parse(iframe.getAttribute("data")); if (cxModel.askStore.log(`正在完成任务:${otherInfo.name || otherInfo.title}`), iframe == null ? void 0 : iframe.src.match(/\/ananas\/modules\/video\/index\.html/)) { if (!formStore.forminput.autoVideo) { cxModel.askStore.log("视频任务已跳过", "success"); continue; } await cxModel.video(iframe.contentWindow), cxModel.askStore.log("视频任务已完成", "success"); } else if (iframe == null ? void 0 : iframe.src.match(/\/ananas\/modules\/work\/index.html/)) { cxModel.askStore.log("即将开始做作业", "info"); const workIframe = (_e = iframe.contentWindow) == null ? void 0 : _e.document.querySelector("iframe"); workIframe && (await waitIframeLoaded(workIframe), await cxModel.work(workIframe.contentWindow), cxModel.askStore.log("作业任务已完成", "success")); } else if (iframe == null ? void 0 : iframe.src.match(/\/ananas\/modules\/audio\/index.html/)) { if (log("音频", "error"), !formStore.forminput.autoVideo) { cxModel.askStore.log("音频任务已跳过", "success"); continue; } iframe && (await waitIframeLoaded(iframe), await cxModel.audio(iframe.contentWindow), cxModel.askStore.log("音频任务已完成", "success")); } else (iframe == null ? void 0 : iframe.src.match(/\/ananas\/modules\/pdf\/index.html/)) ? (log("文档", "error"), iframe && (await waitIframeLoaded(iframe), await cxModel.pdf(iframe.contentWindow), cxModel.askStore.log("pdf任务已完成", "success"))) : (console.log(iframe == null ? void 0 : iframe.src, "未知"), cxModel.askStore.log("未知任务跳过", "success")); } } await sleep(formStore.forminput.interval); if (!formStore.forminput.autoJump) { cxModel.askStore.msg("由于未开启自动切换,请手动切换"); } else { const _detectSubTab = () => { try { const sels = ["#prev_tab > li", ".prev_ul > li", "#prevTabBox > li"]; for (const sel of sels) { const nodes = Array.from((top == null ? void 0 : top.document.querySelectorAll(sel)) || []); if (!nodes.length) continue; const ai = nodes.findIndex(n => n.classList && n.classList.contains("active")); if (ai === -1) continue; return { activeIndex: ai, total: nodes.length, hasNext: ai < nodes.length - 1, tabs: nodes }; } } catch (e) { } return null; }; const _sub = _detectSubTab(); if (_sub && _sub.hasNext) { cxModel.askStore.log(`当前课时存在未完成页面(${_sub.activeIndex + 1}/${_sub.total}),切换到下一页`, "info"); const _nextPageBtn = (top == null ? void 0 : top.document.querySelector("#mainid > .prev_next.next")); _nextPageBtn ? _nextPageBtn.click() : (top == null ? void 0 : top.document.querySelector(".nextChapter").click()); } else { (top == null ? void 0 : top.document.querySelector(".nextChapter").click()); } } }; setInterval(async () => { await waitElementLoaded(_self, "#iframe"); const cardsIframe = _self.document.querySelector("#iframe"); await waitIframeLoaded(cardsIframe); const _self1 = cardsIframe && cardsIframe.contentWindow; if (!_self1) return; try { const href = _self1.location && _self1.location.href; if (href && iframeCom != href) { iframeCom = href; cxModel.askStore.reset(); startWork(); } } catch (e) { } }, 2e3); break; case "/mooc2-ans/mycourse/stu": case "/mooc-ans/mycourse/stu": case "/mycourse/stu": ElementPlus.ElNotification({ title: "Auto Ask", message: "此页面无任务,请自行进入章节页面", type: "error" }); break; case "/work/selectWorkQuestionYiPiYue": break; case "/knowledge/cards": if (_self !== top) break; { const cxCards = new Cx(); const llmCards = getConfig(); cxCards.askStore.log("脚本初始化成功!", "success"); if (llmCards.llmEnabled) cxCards.askStore.log("[LLM] 已启用,模型: " + llmCards.llmModel, "success"); else cxCards.askStore.log("[LLM] 未启用,请在配置中开启", "info"); const tiMu = _self.document.querySelectorAll(".TiMu"); const qLi = _self.document.querySelectorAll(".questionLi"); if (tiMu && tiMu.length) { cxCards.askStore.log("检测到章节测验,开始答题", "info"); cxCards.askStore.msg("章节测验"); await (cxCards.work(_unsafeWindow)); } else if (qLi && qLi.length) { cxCards.askStore.log("检测到作业题目,开始答题", "info"); cxCards.askStore.msg("作业"); await (cxCards.homework()); } else { cxCards.askStore.log("控制台已就绪,等待任务点…", "info"); } } break; case "/mooc2/work/dowork": case "/mooc-ans/mooc2/work/dowork": case "/mooc2-ans/mooc2/work/dowork": if (_self !== top) break; const cxModel1 = new Cx(); const llmConfig1 = getConfig(); console.log("[LLM] 作业页配置:", JSON.stringify({ enabled: llmConfig1.llmEnabled, model: llmConfig1.llmModel }, null, 2)); cxModel1.askStore.log("脚本初始化成功!", "success"); if (llmConfig1.llmEnabled) cxModel1.askStore.log("[LLM] 已启用", "success"); await (cxModel1.homework()); break; case "/exam-ans/exam/test/reVersionTestStartNew": if (_self !== top) break; const cxModel2 = new Cx(); const llmConfig2 = getConfig(); console.log("[LLM] 考试页配置:", JSON.stringify({ enabled: llmConfig2.llmEnabled, model: llmConfig2.llmModel }, null, 2)); cxModel2.askStore.log("脚本初始化成功!", "success"); if (llmConfig2.llmEnabled) cxModel2.askStore.log("[LLM] 已启用", "success"); await (cxModel2.exam()); break; default: if (_self === top) { try { const qEls = _self.document.querySelectorAll(".TiMu, .questionLi, .mark_table"); if (qEls && qEls.length) { const cxD = new Cx(); cxD.askStore.log("脚本初始化成功!", "success"); cxD.askStore.log("检测到答题页面,控制台已就绪", "info"); if (_self.document.querySelectorAll(".questionLi").length) { cxD.askStore.msg("作业"); await (cxD.homework()); } else if (_self.document.querySelectorAll(".mark_table").length) { cxD.askStore.msg("考试"); await (cxD.exam()); } else if (_self.document.querySelectorAll(".TiMu").length) { cxD.askStore.msg("章节测验"); await (cxD.work(_unsafeWindow)); } } } catch (e) { console.error("[满分助手] 兜底答题失败", e); } } } })(Vue, Pinia, ElementPlus, md5, $);