// ==UserScript== // @name 知库学习助手 // @namespace zhiku // @version 1.0.1 // @author 知库工作空间 // @description 知库学习助手:在课程页识别题目、查询题库并核对选项后自动答题;本地缓存可免费复用,个人空间统一管理积分、贡献与账户。查询顺序支持本地缓存 → 知库官方题库 → 可选外部题库 → 个人/公共AI。适配作业、考试与章节测验等常见场景。已适配【超星学习通、智慧树、中国大学MOOC、智慧职教/职教云、云班课、UMU、青书学堂、168网校、国家开放大学及分站、广东开放大学、上海开放大学、江苏开放大学、云南开放大学、安徽继续教育、河南开放相关站点、优课在线UOOC、西财在线、华医网、柠檬文才、21tb、出头系统、芯位教育、learnin 等】共计 40+ 学习平台,持续补充中。 // @homepage https://zhiku.ahzsksw.cn/ // @supportURL https://zhiku.ahzsksw.cn/space // @antifeature payment 联网题库有效查询可能消耗积分;个人AI需自备密钥 // @icon data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2264%22%20height%3D%2264%22%20viewBox%3D%220%200%2064%2064%22%20fill%3D%22none%22%3E%0A%20%20%3Cdefs%3E%0A%20%20%20%20%3ClinearGradient%20id%3D%22ink%22%20x1%3D%225%22%20y1%3D%222%22%20x2%3D%2260%22%20y2%3D%2265%22%20gradientUnits%3D%22userSpaceOnUse%22%3E%3Cstop%20stop-color%3D%22%237165EA%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%23393184%22%2F%3E%3C%2FlinearGradient%3E%0A%20%20%20%20%3ClinearGradient%20id%3D%22leaf%22%20x1%3D%2239%22%20y1%3D%2230%22%20x2%3D%2247%22%20y2%3D%2253%22%20gradientUnits%3D%22userSpaceOnUse%22%3E%3Cstop%20stop-color%3D%22%23A1F7DE%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%2347CBB5%22%2F%3E%3C%2FlinearGradient%3E%0A%20%20%3C%2Fdefs%3E%0A%20%20%3Crect%20x%3D%221%22%20y%3D%221%22%20width%3D%2262%22%20height%3D%2262%22%20rx%3D%2219%22%20fill%3D%22url%28%23ink%29%22%2F%3E%0A%20%20%3Crect%20x%3D%221.5%22%20y%3D%221.5%22%20width%3D%2261%22%20height%3D%2261%22%20rx%3D%2218.5%22%20stroke%3D%22white%22%20stroke-opacity%3D%22.18%22%2F%3E%0A%20%20%3Cpath%20d%3D%22M16%2018H41C43.2%2018%2045%2019.8%2045%2022V24L23%2043H45V48H20C17.8%2048%2016%2046.2%2016%2044V42L38%2023H16V18Z%22%20fill%3D%22white%22%2F%3E%0A%20%20%3Cpath%20d%3D%22M34%2037L49%2029V47L34%2055V37Z%22%20fill%3D%22url%28%23leaf%29%22%2F%3E%0A%20%20%3Cpath%20d%3D%22M39%2039L44%2036M39%2044L44%2041%22%20stroke%3D%22%23245A65%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20opacity%3D%22.6%22%2F%3E%0A%20%20%3Cpath%20d%3D%22M48%2010L49.8%2014.2L54%2016L49.8%2017.8L48%2022L46.2%2017.8L42%2016L46.2%2014.2L48%2010Z%22%20fill%3D%22%23A1F7DE%22%2F%3E%0A%3C%2Fsvg%3E%0A // @match *://*.wxic.edu.cn/* // @match *://*.chaoxing.com/* // @match *://*.cnzx.info/* // @match *://*.ketangx.net/* // @match *://course.ougd.cn/* // @match *://chat.deepseek.com/* // @match *://www.51xinwei.com/* // @match *://*.edu-edu.com.cn/* // @match *://*.icve.com.cn/* // @match *://*.cqie.cn/* // @match *://*.ahjxjy.cn/* // @match *://teach.ynou.edu.cn/* // @match *://*.jijiaox.com/* // @match *://www.icourse163.org/* // @match *://ks.cqsdx.cn/* // @match *://*.hbcjpt.com/* // @match *://*.wwwwsoft.com/* // @match https://m.umu.cn/* // @match *://*.jsnu.edu.cn/* // @match *://*.web2.superchutou.com/* // @match *://www.beeline-ai.com/* // @match *://*.168wangxiao.com/* // @match https://new.oberyun.com/* // @match *://mooc1.ceduacad.ahut.edu.cn/* // @match *://*.zhihuishu.com/* // @match *://*.hlju.edu.cn/* // @match *://*.courshare.cn/* // @match https://zhiku.ahzsksw.cn/demo* // @match *://study.ouchn.cn/* // @match *://*.wencaischool.net/* // @match *://moodle.syxy.ouchn.cn/* // @match *://*.exam-cloud.cn/* // @match *://zice.cnzx.info/* // @match *://*.learnin.com.cn/* // @match *://*.ecust.edu.cn/* // @match *://*.chinaedu.net/* // @match *://*.dufe.edu.cn/* // @match *://*.swufe-online.com/* // @match *://whkpc.hnqtyq.cn:5678/* // @match *://lhycjy.cloudwis.tech/* // @match *://*.edu-edu.com/* // @match *://*.jijiaool.com/* // @match *://*.sclecb.cn/* // @match *://*.ytccr.com/* // @match *://*.csmu.edu.cn/* // @match *://gdrtvu.exam-cloud.cn/* // @match *://*.lut.edu.cn/* // @match *://cce.org.uooconline.com/* // @match *://*.geovisearth.com/* // @match *://any.cnzx.info:81/* // @match *://*.whut.edu.cn/* // @match *://lms.ouchn.cn/* // @match *://*.jxjypt.cn/* // @match *://elearning.bjou.edu.cn/* // @match *://*.tongyi.com/* // @match *://*.lsedu.vip/* // @match *://*.91huayi.com/* // @match *://*.open.ha.cn/* // @match *://moodle.qwbx.ouchn.cn/* // @match *://*.ouchn.cn/* // @match *://*.cfyedu.com/* // @match *://*.21tb.com/* // @match *://*.shou.org.cn/* // @match *://*.webtrn.cn/* // @match *://*.qau.edu.cn/* // @match *://*.ouchn.edu.cn/* // @match *://*.xust.edu.cn/* // @match *://*.cj-edu.com/* // @match *://*.gdufemooc.cn/* // @match *://sdrz.gxk.yxlearning.com/* // @match *://www.asklib.com/* // @match *://*.mynep.com/* // @match *://*.cep.webtrn.cn/* // @match *://*.cjnep.net/* // @match *://*.crjxjy.net/* // @match *://*.aufe.edu.cn/* // @match *://lms.cjzx.hblll.com/* // @match *://*.lygtc.edu.cn/* // @match *://*.bgzk-edu.cn/* // @match *://*.w-ling.cn/* // @match *://*.qingshuxuetang.com/* // @match *://*.ls365.net/* // @match *://*.iwdjy.com/* // @match *://*.yxbyun.com/* // @match *://*.ouc-online.com.cn/* // @match *://*.wdjycj.com/* // @match *://xuexi.jsou.cn/* // @match *://xczxzdbf.moodle.qwbx.ouchn.cn/* // @match *://*.telfri-edu.com/* // @match *://www.mosoteach.cn/* // @require https://cdn.jsdelivr.net/npm/vue@3.4.27/dist/vue.global.prod.js // @require https://cdn.jsdelivr.net/npm/vue-demi@0.14.6/lib/index.iife.js // @require data:application/javascript,%3Bwindow.Vue%3DVue%3B // @require https://cdn.jsdelivr.net/npm/@iconify/vue@5.0.0/dist/iconify.js // @require https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js // @require https://cdn.jsdelivr.net/npm/dompurify@3.1.6/dist/purify.min.js // @require https://cdn.jsdelivr.net/npm/crypto-js@4.2.0/crypto-js.js // @require https://cdn.jsdelivr.net/npm/pinia@2.2.4/dist/pinia.iife.prod.js // @connect elearning.bjou.edu.cn // @connect wxic.edu.cn // @connect web2.superchutou.com // @connect ark.cn-beijing.volces.com // @connect mooc1.ceduacad.ahut.edu.cn // @connect lut.edu.cn // @connect qau.edu.cn // @connect wdjycj.com // @connect jsdelivr.net // @connect ecust.edu.cn // @connect cqie.cn // @connect open.ha.cn // @connect cep.webtrn.cn // @connect wencaischool.net // @connect new.oberyun.com // @connect chaoxing.com // @connect dashscope.aliyuncs.com // @connect moodle.qwbx.ouchn.cn // @connect api.hunyuan.cloud.tencent.com // @connect www.icourse163.org // @connect aufe.edu.cn // @connect ouchn.edu.cn // @connect sclecb.cn // @connect m.umu.cn // @connect ls365.net // @connect hbcjpt.com // @connect gdufemooc.cn // @connect vxo.im // @connect swufe-online.com // @connect ketangx.net // @connect zhihuishu.com // @connect lsedu.vip // @connect lms.cjzx.hblll.com // @connect jsnu.edu.cn // @connect whkpc.hnqtyq.cn // @connect icve.com.cn // @connect shou.org.cn // @connect api.groq.com // @connect api.longcat.chat // @connect study.ouchn.cn // @connect openrouter.ai // @connect api.anthropic.com // @connect cjnep.net // @connect chat.deepseek.com // @connect geovisearth.com // @connect jxjypt.cn // @connect cj-edu.com // @connect www.beeline-ai.com // @connect edu-edu.com.cn // @connect generativelanguage.googleapis.com // @connect ouc-online.com.cn // @connect csmu.edu.cn // @connect crjxjy.net // @connect ytccr.com // @connect tongyi.com // @connect lygtc.edu.cn // @connect open.bigmodel.cn // @connect any.cnzx.info // @connect xust.edu.cn // @connect gdrtvu.exam-cloud.cn // @connect wwwwsoft.com // @connect zice.cnzx.info // @connect xuexi.jsou.cn // @connect api.together.ai // @connect moodle.syxy.ouchn.cn // @connect chinaedu.net // @connect cnzx.info // @connect jsdmirror.cn // @connect courshare.cn // @connect api.siliconflow.cn // @connect exam-cloud.cn // @connect lhycjy.cloudwis.tech // @connect 21tb.com // @connect api.openai.com // @connect hlju.edu.cn // @connect forestpolice.org // @connect 168wangxiao.com // @connect edu-edu.com // @connect zhiku.ahzsksw.cn // @connect xczxzdbf.moodle.qwbx.ouchn.cn // @connect learnin.com.cn // @connect whut.edu.cn // @connect 91huayi.com // @connect cce.org.uooconline.com // @connect www.asklib.com // @connect jijiaool.com // @connect bgzk-edu.cn // @connect qingshuxuetang.com // @connect api.moonshot.ai // @connect www.51xinwei.com // @connect w-ling.cn // @connect mynep.com // @connect ouchn.cn // @connect qianfan.baidubce.com // @connect course.ougd.cn // @connect webtrn.cn // @connect cfyedu.com // @connect teach.ynou.edu.cn // @connect yxbyun.com // @connect www.mosoteach.cn // @connect ahjxjy.cn // @connect iwdjy.com // @connect dufe.edu.cn // @connect jijiaox.com // @connect lms.ouchn.cn // @connect sdrz.gxk.yxlearning.com // @connect api.mistral.ai // @connect ks.cqsdx.cn // @connect api.deepseek.com // @connect telfri-edu.com // @grant GM.xmlHttpRequest // @grant GM_deleteValue // @grant GM_getValue // @grant GM_info // @grant GM_listValues // @grant GM_setValue // @grant GM_xmlhttpRequest // @grant unsafeWindow // @run-at document-start // ==/UserScript== (function (vue, vue$1, pinia, M, j, O) { 'use strict'; var e = Object.defineProperty, __publicField = (t, n, a) => ((t, n, a) => n in t ? e(t, n, { enumerable: true, configurable: true, writable: true, value: a }) : t[n] = a)(t, "symbol" != typeof n ? n + "" : n, a); const z = new Set([ "preparing", "searching", "matched", "published", "rendering", "filling" ]), D = { todo: "\u672a\u7b54", run: "\u67e5\u627e\u4e2d", done: "\u5df2\u7b54", none: "\u65e0\u7b54\u6848", wait: "AI \u5f85\u786e\u8ba4" }; function tallyMarks(e) { const t = { done: 0, none: 0, wait: 0, todo: 0 }; for (const n of e) "run" === n ? t.todo++ : t[n]++; return t; } const F = "\u672c\u5730\u7f13\u5b58", isAiForm = (e = "") => /AI/i.test(e), hasAnswer = e => { if (e.needLogin) return false; const t = e.answer; return Array.isArray(t) ? t.length > 0 : t && "object" == typeof t ? Object.keys(t).length > 0 : "string" == typeof t ? t.trim().length > 0 : !!t; }; var X = (() => "undefined" != typeof GM_deleteValue ? GM_deleteValue : void 0)(), ee = (() => "undefined" != typeof GM_getValue ? GM_getValue : void 0)(), te = (() => "undefined" != typeof GM_info ? GM_info : void 0)(), ne = (() => "undefined" != typeof GM_listValues ? GM_listValues : void 0)(), ae = (() => "undefined" != typeof GM_setValue ? GM_setValue : void 0)(), re = (() => "undefined" != typeof GM_xmlhttpRequest ? GM_xmlhttpRequest : void 0)(), ie = (() => "undefined" != typeof unsafeWindow ? unsafeWindow : void 0)(); const se = "PrivateStudy_"; class Cache { static set(e, t, n = 0) { e = se + e; const a = { value: t, expire: n > 0 ? Date.now() + 1e3 * n : 0 }; return ae(e, a), ee(e); } static get(e, t = null) { const n = ee(e = se + e); return n && n.expire && n.expire < Date.now() ? (X(e), t) : n ? n.value : t; } static match(e) { return e = se + e, ne().filter((t => t.startsWith(e))); } static matchGet(e) { const t = se + e; let n = ne().filter((e => e.startsWith(t))).map((e => function(e, t, n) { if (t && t.expire && t.expire < Date.now()) return n(e), null; const a = t ? t.value : null; return a && (a.key = e.replace("PrivateStudy_", "")), a; }(e, ee(e, { value: null, expire: 0 }), X))).filter((e => null !== e)); return n.sort(((e, t) => (t.createTime || 0) - (e.createTime || 0))), n; } static remove(e) { X(se + e); } static clear() { ne().filter((e => e.startsWith(se))).forEach(X); } static matchRemove(e) { e = se + e, ne().filter((t => t.startsWith(e))).forEach(X); } } let oe = null; function log$1(...e) {} let panelNotification = null; const addLog = (content, type = "info") => { const app = oe?.(); if (app) app.addLog({time: new Date().toLocaleString(), type, content}); }; function msg(content, type = "info") { addLog(content, type); if (panelNotification) panelNotification(cleanQuestionText(content), type); } async function encrypt(e = "", t = "asdgdfghfghfghfg", n = "1234567890123456") { try { if (!e) return ""; if (t = t.substring(0, 16), n = n.substring(0, 16), !window.crypto || !window.crypto.subtle) { const a = j.enc.Utf8.parse(t), r = j.enc.Utf8.parse(n); return j.AES.encrypt(e, a, { iv: r, mode: j.mode.CBC, padding: j.pad.Pkcs7 }).toString(); } const r = new TextEncoder, i = r.encode(e), s = r.encode(t), o = r.encode(n), l = await crypto.subtle.importKey("raw", s, { name: "AES-CBC" }, !1, [ "encrypt" ]), c = await crypto.subtle.encrypt({ name: "AES-CBC", iv: o }, l, i), u = new Uint8Array(c), p = 1024; let d, m = ""; for (let e = 0; e < u.length; e += p) { const t = u.slice(e, Math.min(e + p, u.length)); m += String.fromCharCode.apply(null, Array.from(t)); } try { d = btoa(m); } catch (a) { d = m.split("").map((e => ("0" + e.charCodeAt(0).toString(16)).slice(-2))).join(""); } return d; } catch (r) { return addLog(`\u52a0\u5bc6\u5f02\u5e38: ${r instanceof Error ? r.message : "\u672a\u77e5\u9519\u8bef"}`, "error"), ""; } } async function decrypt(e = "", t = "asdgdfghfghfghfg", n = "1234567890123456") { try { if (!e) return ""; if (t = t.substring(0, 16), n = n.substring(0, 16), !window.crypto || !window.crypto.subtle) { const a = j.enc.Utf8.parse(t), r = j.enc.Utf8.parse(n); return j.AES.decrypt(e, a, { iv: r, mode: j.mode.CBC, padding: j.pad.Pkcs7 }).toString(j.enc.Utf8); } /^[A-Za-z0-9+/]*={0,2}$/.test(e); const r = new TextEncoder, i = r.encode(t), s = r.encode(n); let o; try { o = atob(e); } catch (a) { throw new Error("Base64 \u89e3\u7801\u5931\u8d25\uff0c\u6570\u636e\u683c\u5f0f\u4e0d\u6b63\u786e"); } const l = new Uint8Array(o.length); for (let e = 0; e < o.length; e++) l[e] = o.charCodeAt(e); if (l.length % 16 != 0) throw new Error("\u52a0\u5bc6\u6570\u636e\u957f\u5ea6\u4e0d\u6b63\u786e\uff0c\u4e0d\u662f16\u7684\u500d\u6570"); const c = await crypto.subtle.importKey("raw", i, { name: "AES-CBC" }, !1, [ "decrypt" ]), u = await crypto.subtle.decrypt({ name: "AES-CBC", iv: s }, c, l); return new TextDecoder("utf-8", { fatal: !0 }).decode(u); } catch (r) { return addLog(`\u89e3\u5bc6\u5f02\u5e38: ${r instanceof Error ? r.message : "\u672a\u77e5\u9519\u8bef"}`, "error"), ""; } } function md5(e) { return j.MD5(e).toString(); } function somd5(e) { return md5(e); } const isPlainObject$1 = e => "object" == typeof e && null !== e && !Array.isArray(e), flattenForSignature = (e, t = "") => { const n = []; return Object.keys(e).sort().forEach((a => { if (!t && "html" === a) return; const r = t ? `${t}.${a}` : a, i = e[a]; (e => null == e || !(!Array.isArray(e) || 0 !== e.length) || !(!isPlainObject$1(e) || 0 !== Object.keys(e).length))(i) || (Array.isArray(i) ? n.push(`${r}=${(e => e.every((e => "object" != typeof e)) ? [ ...e ].sort().join(",") : JSON.stringify(e))(i)}`) : isPlainObject$1(i) ? n.push(...flattenForSignature(i, r)) : n.push(`${r}=${String(i)}`)); })), n; }; function get_t(e = {}) { return md5(flattenForSignature(e).join("&")); } const getImageSrc = e => { const t = String(e).match(/(?:^|\s)src\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i); return t && (t[1] || t[2] || t[3]) || ""; }, stripImageSrcQuery = e => e.replace(/[?#].*$/, ""), cleanQuestionText = (e, t = false) => String(e ?? "").replace(/]*)>/gi, ((e, t) => getImageSrc(t))).replace(//gi, "\n").replace(/<(\/)?(p|div).*?>/gi, "\n").replace(/<[^>]+>/g, "").replace(t ? /[\r\xa0]/g : /[\t\r\xa0]/g, " ").replace(/[\u2000-\u200a]/g, " ").replace(/ {2,}/g, " ").replace(/\n{2,}/g, "\n").replace(t ? /^[^\S\t]+|[^\S\t]+$/g : /^\s+|\s+$/g, ""), cleanQuestionTextWithImageHtml = (e, t = false) => { const n = []; return String(e ?? "").replace(/]*)>/gi, ((e, t) => { const a = getImageSrc(t); if (!a) return ""; const r = `\0AAH_IMAGE_PLACEHOLDER_${n.length}\0`; return n.push(`/g, ">"))(a)}">`), r; })).replace(//gi, "\n").replace(/<(\/)?(p|div).*?>/gi, "\n").replace(/<[^>]+>/g, "").replace(/\u0000AAH_IMAGE_PLACEHOLDER_(\d+)\u0000/g, ((e, t) => n[Number(t)] || "")).replace(t ? /[\r\xa0]/g : /[\t\r\xa0]/g, " ").replace(/[\u2000-\u200a]/g, " ").replace(/ {2,}/g, " ").replace(/\n{2,}/g, "\n").replace(t ? /^[^\S\t]+|[^\S\t]+$/g : /^\s+|\s+$/g, ""); }, cleanQuestionTitle = (e, t = false) => e.replace(/^[.*?]\s*/, "").replace(/^\u3010.*?\u3011\s*/, "").replace(/\s*[\uff08(]\s*\d+(?:\.\d+)?\s*\u5206?\s*[\uff09)]\s*$/, "").replace(/^\d+\./, "").replace(t ? /^[^\S\t]+|[^\S\t]+$/g : /^\s+|\s+$/g, "").replace(/^\d+\uff0e/, "").replace(t ? /^[^\S\t]+|[^\S\t]+$/g : /^\s+|\s+$/g, ""), normalizeComparableText = e => (e => { if (/^[+-]?\d+(\.\d+)?$/.test(e)) return e; const t = e.replace(/\s+/g, ""); return t.replace(new RegExp("\\p{P}", "gu"), "") || t; })((e => String(e ?? "").replace(/]*)>/gi, ((e, t) => stripImageSrcQuery(getImageSrc(t)))).replace(/<[^>]*>/g, ""))(e)).trim(), removeOptionPrefixes = (e, {removeBareLetter: t = false} = {}) => e.map(((e, n) => { const a = String.fromCharCode(65 + n), r = t ? `^${a}(?:\\s*[.\u3001\uff0e)\uff09:\uff1a]\\s*|\\s+)?` : `^${a}\\s*[.\u3001\uff0e)\uff09:\uff1a]\\s*`; return e.replace(new RegExp(r), "").trim(); })), normalizeHashText = e => String(e ?? "").replace(/]*)>/gi, ((e, t) => { const n = getImageSrc(t); return n ? `` : ""; })), questionHash = (e, t, n, a = true) => { if (("15" === e || 15 === e) && Array.isArray(n) && n.length > 0 && "object" == typeof n[0]) { const r = n.map((e => { if (e.question && e.options) { const t = Array.from(e.options).map(normalizeHashText); a && t.sort(); const n = t.join(""); return `${e.type || "0"}${normalizeHashText(e.question)}${n}`; } return ""; })).filter(Boolean); let i = `${e}${normalizeHashText(t)}${r.join("")}`; return i = i.replace(/\s/g, ""), md5(i); } const r = Array.from(n).map(normalizeHashText); a && r.sort(); const i = r.join(""); let s = `${e}${normalizeHashText(t)}${i}`; return s = s.replace(/\s/g, ""), md5(s); }, sanitizeHtml = (e, t, n) => { const a = M.sanitize; return "function" == typeof a ? a(e, { ALLOWED_TAGS: t, ALLOWED_ATTR: n, ALLOW_DATA_ATTR: false, KEEP_CONTENT: true }) : ((e, t, n) => { const a = new Set(t), r = new Set(n); return e.replace(/]*>[\s\S]*?<\/script>/gi, "").replace(/]*>[\s\S]*?<\/style>/gi, "").replace(/\son\w+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?/gi, "").replace(/<([/]?)([a-z][\w:-]*)([^>]*)>/gi, ((e, t, n, i) => { const s = String(n).toLowerCase(); if (!a.has(s)) return ""; if (t) return ``; const o = []; return String(i).replace(/([:\w-]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/g, ((e, t, n, a, i) => { const s = String(t).toLowerCase(), l = String(n ?? a ?? i ?? ""); return r.has(s) && ("href" !== s && "src" !== s || (c = l.trim(), /^(https?:|mailto:|tel:|data:image\/|\/|\.\/|\.\.\/|#)/i.test(c))) ? (o.push(`${s}="${l.replace(/"/g, """)}"`), "") : ""; var c; })), `<${s}${o.length ? ` ${o.join(" ")}` : ""}>`; })); })(e, t, n); }; function removeHtml(e, t = true) { if (e = (e = (e = (e = (e => { if ("undefined" != typeof document) { const t = document.createElement("textarea"); return t.innerHTML = e, t.value; } const t = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: " " }; return e.replace(/&(#\d+|#x[\da-f]+|[a-z]+);/gi, ((e, n) => { const a = String(n).toLowerCase(); return a.startsWith("#x") ? String.fromCharCode(parseInt(a.slice(2), 16)) : a.startsWith("#") ? String.fromCharCode(parseInt(a.slice(1), 10)) : t[a] ?? e; })); })(e)).replace(/[\t\r\xa0]/g, " ")).replace(/[\u2000-\u200a]/g, " ")).replace(//g, "\n"), t && (e = e.replace(/<(\/)?(p|div).*?>/g, "\n")), e = (e = (e = (e = e.replace(/ {2,}/g, " ")).replace(/\n{2,}/g, "\n")).replace(//g, "
")).replace(/<\/xmp>/g, "
"), e = sanitizeHtml(e, [ "img", "br", "sub", "sup" ], [ "src", "href" ]), "undefined" != typeof document && "undefined" != typeof location) { const t = //g, n = e.match(t); n && n.forEach((t => { const n = t.match(/src="(.*?)"/); if (n && -1 === n[1].indexOf("http") && !n[1].includes("data:image")) if (n[1].startsWith("/")) e = e.replace(n[1], location.origin + n[1]); else { const t = new URL(n[1], document.baseURI).href; e = e.replace(n[1], t); } })); } return e.trim(); } const escapeHtml = e => e.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); function createSafeMarkdownHtml(e) { if (!e) return ""; let t = e; const n = [], a = `AAHMDPLACEHOLDER${"undefined" != typeof crypto && "randomUUID" in crypto ? crypto.randomUUID().replace(/[^a-z0-9]/gi, "") : `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`.replace(/[^a-z0-9]/gi, "")}`, protect = e => { const t = `${a}X${n.length}Z`; return n.push(e), t; }; return t = t.replace(/```(\w*)\n([\s\S]*?)```/g, ((e, t, n) => protect(`
${escapeHtml(String(n).trim())}
`))), t = t.replace(/`([^`]+)`/g, ((e, t) => protect(`${escapeHtml(String(t))}`))), t = t.replace(/\[([^\]]+)\]\(([^)]+)\)/g, ((e, t, n) => { const a = String(n).trim(); return /^https?:\/\//i.test(a) ? protect(`${t}`) : t; })), t = t.replace(/\*\*(.+?)\*\*/g, "$1"), t = t.replace(/__(.+?)__/g, "$1"), t = t.replace(/\*(.+?)\*/g, "$1"), t = t.replace(/_(.+?)_/g, "$1"), t = t.replace(/^### (.+)$/gm, "

$1

"), t = t.replace(/^## (.+)$/gm, "

$1

"), t = t.replace(/^# (.+)$/gm, "

$1

"), t = t.replace(/^\- (.+)$/gm, "
  • $1
  • "), t = t.replace(/(
  • .*<\/li>\n?)+/g, "
      $&
    "), t = t.replace(/^\d+\. (.+)$/gm, "
  • $1
  • "), t = t.replace(/\n/g, "
    "), t = t.replace(/
    <(pre|h1|h2|h3|ul|ol)/g, "<$1"), t = t.replace(/<\/(pre|h1|h2|h3|ul|ol)>
    /g, ""), (e => sanitizeHtml(e, [ "a", "br", "code", "em", "h1", "h2", "h3", "img", "li", "ol", "pre", "strong", "sub", "sup", "ul" ], [ "class", "href", "rel", "src", "target" ]))(t.replace(new RegExp(`${(e => e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))(a)}X(\\d+)Z`, "g"), ((e, t) => n[Number(t)] || ""))); } function titleClean(e) { return cleanQuestionTitle(e); } function isFalse(e) { return "string" == typeof e && /(\u4e0d\u6b63\u786e|\u9519\u8bef|\u5426|\u9519|\xd7|F|wr|false)/i.test(e); } function isTrue(e) { return "string" == typeof e && (!isFalse(e) && /(\u6b63\u786e|\u662f|\u5bf9|\u221a|T|ri|true)/i.test(e)); } function judgeAnswer(e) { return isTrue(e) ? [ "\u6b63\u786e" ] : isFalse(e) ? [ "\u9519\u8bef" ] : []; } function removeStartChar(e) { return removeOptionPrefixes(e, { removeBareLetter: true }); } function removeKnownOptionPrefix(e, t) { const n = String(e ?? "").trim(), a = String(t ?? "").trim(); return "" === a ? n : n.replace(new RegExp(`^${r = a, r.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*`), "").trim(); var r; } function removeOptionsStartChar(e) { for (let t = 0; t < e.length; t += 1) { const n = String.fromCharCode(65 + t) + ".", a = String.fromCharCode(65 + t) + "\u3001", r = String.fromCharCode(65 + t) + "\uff0e", i = String.fromCharCode(65 + t), s = new RegExp(`^${n}|^${a}|^${r}|^${i}`); if (!e[t].match(s)) return false; e[t] = e[t].replace(s, "").trim(); } return e; } const de = { "\u5355\u9009\u9898": "0", "\u591a\u9009\u9898": "1", "\u586b\u7a7a\u9898": "2", "\u5224\u65ad\u9898": "3", "\u7b80\u7b54\u9898": "4", "\u95ee\u7b54\u9898": "4", "\u540d\u8bcd\u89e3\u91ca": "5", "\u8bba\u8ff0\u9898": "6", "\u8ba1\u7b97\u9898": "7", "\u5206\u5f55\u9898": "9", "\u8d44\u6599\u9898": "10", "\u8fde\u7ebf\u9898": "11", "\u5339\u914d\u9898": "11", "\u6392\u5e8f\u9898": "13", "\u5b8c\u578b\u586b\u7a7a": "14", "\u5b8c\u5f62\u586b\u7a7a\u9898": "14", "\u9605\u8bfb\u7406\u89e3": "15", "\u7a0b\u5e8f\u9898": "17", "\u53e3\u8bed\u9898": "18", "\u542c\u529b\u9898": "19", "\u5171\u7528\u9009\u9879\u9898": "20", "\u6d4b\u8bc4\u9898": "21", "\u949f\u8868\u9898": "23", "\u9009\u8bcd\u586b\u7a7a": "24", "\u9009\u505a\u9898": "25", "\u5176\u5b83": "8" }; function typeConvert(e, t = true) { return t ? de[e] || "8" : Object.keys(de).find((t => de[t] === e)) || "\u5176\u5b83"; } function typeMatch(e) { const t = { 0: [ "\u5355\u9009", "\u5355\u9879\u9009\u62e9", "\u8bcd\u6c47\u4e0e\u7ed3\u6784", "A2", "A1" ], 1: [ "\u591a\u9009", "\u591a\u9879\u9009\u62e9" ], 2: [ "\u586b\u7a7a" ], 3: [ "\u5224\u65ad" ], 4: [ "\u7b80\u7b54", "\u95ee\u7b54", "\u7efc\u5408\u9898" ], 5: [ "\u540d\u8bcd\u89e3\u91ca" ], 6: [ "\u8bba\u8ff0", "\u4e3b\u89c2" ], 7: [ "\u8ba1\u7b97" ], 9: [ "\u5206\u5f55" ], 14: [ "\u5b8c\u5f62\u586b\u7a7a" ], 15: [ "\u9605\u8bfb\u7406\u89e3" ], 24: [ "\u9009\u8bcd\u586b\u7a7a" ] }; return Object.keys(t).find((n => t[n].some((t => e.includes(t))))) || "8"; } function sleep(e) { return new Promise((t => setTimeout(t, e))); } const waitUntil = (e, t) => { const n = void 0 === t || "number" == typeof t, a = "number" == typeof t ? { interval: t } : t ?? {}, r = a.interval ?? 50, i = !n && Object.prototype.hasOwnProperty.call(a, "timeout") && "number" == typeof a.timeout, s = a.timeout, o = a.timeoutMessage ?? "\u7b49\u5f85\u9875\u9762\u6761\u4ef6\u8d85\u65f6", l = Date.now(); return new Promise(((t, a) => { const check = () => { try { if (e()) return t(), true; } catch (r) { if (!n) return a(r), true; } if (i && Date.now() - l >= s) return a(new Error(o)), true; return false; }; if (check()) return; const c = setInterval((() => { check() && clearInterval(c); }), r); })); }; function isExist(e) { return O(e).length > 0; } function getUrl() { return location.href; } const me = [ "AI_CONFIG_MISSING", "AI_PROVIDER_DISABLED", "AI_CREDENTIAL_MISSING", "AI_AUTH_FAILED", "AI_REQUEST_TIMEOUT", "AI_NETWORK_FAILED", "AI_RESPONSE_PARSE_FAILED", "AI_SSE_PARSE_FAILED", "AI_OUTPUT_SCHEMA_INVALID", "AI_ANSWER_NOT_MATCHED", "AI_QUESTION_TYPE_UNSUPPORTED", "AI_IMAGE_UNSUPPORTED", "AI_PROXY_UNAVAILABLE", "AI_PROXY_RATE_LIMITED", "AI_PROXY_LOGIN_REQUIRED", "AI_CHANNEL_UNKNOWN", "AI_MODEL_REJECTED", "AI_DIRECT_BLOCKED" ], he = { AI_CONFIG_MISSING: "AI \u914d\u7f6e\u4e0d\u5b58\u5728\uff0c\u8bf7\u5148\u5b8c\u6210\u914d\u7f6e", AI_PROVIDER_DISABLED: "AI \u5e73\u53f0\u5df2\u505c\u7528\uff0c\u8bf7\u542f\u7528\u540e\u91cd\u8bd5", AI_CREDENTIAL_MISSING: "AI \u51ed\u8bc1\u7f3a\u5931\uff0c\u8bf7\u586b\u5199 API Key \u6216\u6388\u6743\u4fe1\u606f", AI_AUTH_FAILED: "AI \u9274\u6743\u5931\u8d25\uff0c\u8bf7\u68c0\u67e5\u51ed\u8bc1\u662f\u5426\u6709\u6548", AI_REQUEST_TIMEOUT: "AI \u8bf7\u6c42\u8d85\u65f6\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5", AI_NETWORK_FAILED: "AI \u8bf7\u6c42\u7f51\u7edc\u5f02\u5e38\uff0c\u8bf7\u68c0\u67e5\u7f51\u7edc\u540e\u91cd\u8bd5", AI_RESPONSE_PARSE_FAILED: "AI \u54cd\u5e94\u89e3\u6790\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5", AI_SSE_PARSE_FAILED: "AI \u6d41\u5f0f\u54cd\u5e94\u89e3\u6790\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5", AI_OUTPUT_SCHEMA_INVALID: "AI \u8f93\u51fa\u683c\u5f0f\u4e0d\u7b26\u5408\u8981\u6c42\uff0c\u8bf7\u91cd\u8bd5", AI_ANSWER_NOT_MATCHED: "AI \u7b54\u6848\u672a\u80fd\u5339\u914d\u5f53\u524d\u9898\u76ee", AI_QUESTION_TYPE_UNSUPPORTED: "AI \u6682\u4e0d\u652f\u6301\u5f53\u524d\u9898\u578b", AI_IMAGE_UNSUPPORTED: "AI \u6682\u4e0d\u652f\u6301\u56fe\u7247\u9898\u76ee", AI_PROXY_UNAVAILABLE: "AI \u4ee3\u7406\u6682\u65f6\u4e0d\u53ef\u7528\uff0c\u6b63\u5728\u5c1d\u8bd5\u76f4\u8fde", AI_PROXY_RATE_LIMITED: "AI \u4ee3\u7406\u989d\u5ea6\u5df2\u7528\u5b8c\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5", AI_PROXY_LOGIN_REQUIRED: "\u4f7f\u7528 AI \u4ee3\u7406\u9700\u8981\u5148\u767b\u5f55\uff0c\u672a\u767b\u5f55\u53ef\u9009\u62e9\u652f\u6301\u76f4\u8fde\u7684\u6e20\u9053", AI_CHANNEL_UNKNOWN: "\u8be5 AI \u6e20\u9053\u5df2\u4e0b\u7ebf\uff0c\u8bf7\u91cd\u65b0\u9009\u62e9", AI_MODEL_REJECTED: "\u6240\u9009\u6a21\u578b\u4e0d\u53ef\u7528\uff0c\u8bf7\u5728\u8bbe\u7f6e\u4e2d\u91cd\u9009", AI_DIRECT_BLOCKED: "\u8be5\u6e20\u9053\u65e0\u6cd5\u76f4\u8fde\u4e14\u4ee3\u7406\u6682\u4e0d\u53ef\u7528\uff1b\u6d77\u5916\u6e20\u9053\u9700\u81ea\u5907\u4ee3\u7406" }; function createAiError(e, t = {}) { const n = t.userMessage || he[e], a = new Error(`[${e}] ${n}`, void 0 === t.cause ? void 0 : { cause: t.cause }); return a.name = "AiError", a.code = e, a.userMessage = n, void 0 !== t.detail && (a.detail = t.detail), a; } const isAiError = e => "object" == typeof e && null !== e && "AiError" === e.name && "string" == typeof e.code && me.includes(e.code) && "string" == typeof e.message && "string" == typeof e.userMessage, getAiErrorMessage = e => isAiError(e) ? e.userMessage : e instanceof Error && e.message ? e.message : "AI \u8bf7\u6c42\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5", parseSsePackets = e => { const t = []; for (const a of e.split(/\r?\n/)) { const e = a.trim(); if (!e.startsWith("data:")) continue; const r = e.slice(5).trim(); if (r && "[DONE]" !== r) try { t.push(JSON.parse(r)); } catch (n) { throw createAiError("AI_SSE_PARSE_FAILED", { detail: { payload: r }, cause: n }); } } return t; }, createSsePacketParser = () => { let e = ""; return { push: t => (e += t, (() => { const t = [], n = e.split(/\r?\n\r?\n/); e = n.pop() || ""; for (const e of n) t.push(...parseSsePackets(e)); return t; })()), flush: () => { if (!e.trim()) return e = "", []; const t = e; return e = "", parseSsePackets(t); } }; }, getRuntime = () => globalThis, getRuntimeGmXmlhttpRequest = () => { var e; const t = "function" == typeof GM_xmlhttpRequest ? GM_xmlhttpRequest : "undefined" != typeof GM && "function" == typeof GM.xmlHttpRequest ? GM.xmlHttpRequest : void 0; if (t) return t; const n = getRuntime(); return n.GM_xmlhttpRequest || (null == (e = n.GM) ? void 0 : e.xmlHttpRequest); }, isHttpErrorStatus = e => !e || e < 200 || e >= 300, readStream = async (e, t) => { if (!e || "function" != typeof e.getReader) return; const n = e.getReader(), a = new TextDecoder; for (;;) { const {done: e, value: r} = await n.read(); if (e) break; r && t(a.decode(r, { stream: true })); } const r = a.decode(); r && t(r); }, truncate = e => e.length > 200 ? `${e.slice(0, 200)}\u2026` : e, createHttpStatusError = e => { const t = { status: e.status, statusText: e.statusText, responseText: e.responseText }; if (401 === e.status || 403 === e.status) return createAiError("AI_AUTH_FAILED", { detail: t }); if (isHttpErrorStatus(e.status)) { const n = (e => { if (!e) return ""; try { const t = JSON.parse(e), n = "object" == typeof t && null !== t ? t.error : void 0; if ("object" == typeof n && null !== n) { const e = n.message; if ("string" == typeof e && e.trim()) return truncate(e.trim()); } const a = "object" == typeof t && null !== t ? t.message : void 0; if ("string" == typeof a && a.trim()) return truncate(a.trim()); } catch { return truncate(e.trim()); } return ""; })(e.responseText), a = `AI \u63a5\u53e3\u8fd4\u56de ${e.status} ${e.statusText || ""}`.trim(); return createAiError("AI_NETWORK_FAILED", { detail: t, userMessage: n ? `${a}\uff1a${n}` : `${a}\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5` }); } }, stringifyHeaders = e => { const t = []; return e.forEach(((e, n) => t.push(`${n}: ${e}`))), t.join("\r\n"); }, createAiTransportRequest = e => { var t; const n = (null == (t = e.resolveGmXmlhttpRequest) ? void 0 : t.call(e)) || getRuntimeGmXmlhttpRequest(); if (!n) { const t = (() => { const e = getRuntime(); if ("function" == typeof e.fetch) return e.fetch.bind(e); })(); return t ? ((e, t) => { const n = "function" == typeof AbortController ? new AbortController : void 0; let r, i, rejectTransport = () => {}; const createBaseResponse = (t, n, a = "") => ({ finalUrl: t.url || e.url, response: n, responseHeaders: stringifyHeaders(t.headers), responseText: a, status: t.status, statusText: t.statusText }); return { promise: new Promise(((s, o) => { rejectTransport = o, e.timeout && n && (i = setTimeout((() => { r = "timeout", n.abort(); }), e.timeout)), (async () => { try { const r = await t(e.url, { method: e.method, headers: e.headers, body: e.data ?? void 0, signal: null == n ? void 0 : n.signal }); if (isHttpErrorStatus(r.status)) { const e = await r.text().catch((() => "")), t = createHttpStatusError(createBaseResponse(r, void 0, e)); if (t) return void o(t); } if ("stream" === e.responseType && e.onStreamChunk) { try { await readStream(r.body, e.onStreamChunk); } catch (a) { return void o(createAiError("AI_NETWORK_FAILED", { userMessage: "AI \u6d41\u5f0f\u54cd\u5e94\u8bfb\u53d6\u5931\u8d25", cause: a })); } return void s(createBaseResponse(r, r.body)); } if ("arraybuffer" === e.responseType) { const e = await r.arrayBuffer(); return void s(createBaseResponse(r, e)); } const i = await r.text(); s(createBaseResponse(r, i, i)); } catch (a) { if ("timeout" === r) return void o(createAiError("AI_REQUEST_TIMEOUT")); if ("manual" === r) return void o(createAiError("AI_NETWORK_FAILED", { userMessage: "AI \u8bf7\u6c42\u5df2\u53d6\u6d88" })); o(createAiError("AI_NETWORK_FAILED", { cause: a })); } finally { i && clearTimeout(i); } })(); })), abort: () => { r = "manual", null == n || n.abort(), rejectTransport(createAiError("AI_NETWORK_FAILED", { userMessage: "AI \u8bf7\u6c42\u5df2\u53d6\u6d88" })); } }; })(e, t) : (a = createAiError("AI_NETWORK_FAILED", { userMessage: "\u5f53\u524d\u8fd0\u884c\u73af\u5883\u4e0d\u652f\u6301 GM_xmlhttpRequest" }), { promise: Promise.reject(a), abort: () => {} }); } var a; let r, i, s, rejectTransport = () => {}, o = false, l = false, c = false, u = ""; const p = new Promise(((t, a) => { const rejectOnce = e => { o || (o = true, a(e)); }; rejectTransport = rejectOnce; const beginStreamRead = t => i || (i = readStream(t.response, (t => { var n; u.length < 8192 && (u += t), null == (n = e.onStreamChunk) || n.call(e, t); })).then((() => { l = true; })).catch((e => { l = true, c = true, s = e; })), i), rejectWithStatusError = e => { (i ? Promise.race([ i.then((() => u)), new Promise((e => setTimeout((() => e(u)), 500))) ]) : Promise.resolve("")).then((t => { const n = createHttpStatusError({ ...e, responseText: e.responseText || t }); rejectOnce(n || createAiError("AI_NETWORK_FAILED")); })); }, resolveOnce = e => { o || (isHttpErrorStatus(e.status) ? rejectWithStatusError(e) : (o = true, t(e))); }; r = n({ method: e.method, url: e.url, headers: e.headers, data: e.data, timeout: e.timeout, responseType: e.responseType, onloadstart: t => { "stream" === e.responseType && beginStreamRead(t); }, onload: t => { if (isHttpErrorStatus(t.status)) return void rejectWithStatusError(t); if ("stream" !== e.responseType || !e.onStreamChunk) return void resolveOnce(t); const n = beginStreamRead(t); if (l) return c ? void rejectOnce(createAiError("AI_NETWORK_FAILED", { userMessage: "AI \u6d41\u5f0f\u54cd\u5e94\u8bfb\u53d6\u5931\u8d25", cause: s })) : void resolveOnce(t); n.then((() => { c ? rejectOnce(createAiError("AI_NETWORK_FAILED", { userMessage: "AI \u6d41\u5f0f\u54cd\u5e94\u8bfb\u53d6\u5931\u8d25", cause: s })) : resolveOnce(t); })); }, onabort: () => rejectOnce(createAiError("AI_NETWORK_FAILED", { userMessage: "AI \u8bf7\u6c42\u5df2\u53d6\u6d88" })), ontimeout: () => rejectOnce(createAiError("AI_REQUEST_TIMEOUT")), onerror: e => rejectOnce(createAiError("AI_NETWORK_FAILED", { cause: e })) }); })); return { promise: p, abort: () => { null == r || r.abort(), rejectTransport(createAiError("AI_NETWORK_FAILED", { userMessage: "AI \u8bf7\u6c42\u5df2\u53d6\u6d88" })); } }; }, trimTrailingSlash = e => e.replace(/\/+$/, ""), contentToText = e => "string" == typeof e ? e : e.filter((e => "text" === e.type)).map((e => e.text)).join("\n"), assertConfigAvailable = e => { var t; if (!e.enabled) throw createAiError("AI_PROVIDER_DISABLED"); if (!(null == (t = e.credential) ? void 0 : t.value.trim())) throw createAiError("AI_CREDENTIAL_MISSING"); }, parseJsonResponse = e => { try { if ("string" == typeof e.response) { if (!e.response) return; return JSON.parse(e.response); } return void 0 !== e.response && null !== e.response ? e.response : e.responseText ? JSON.parse(e.responseText) : void 0; } catch (t) { throw createAiError("AI_RESPONSE_PARSE_FAILED", { cause: t }); } }, bindAbortSignal = (e, t) => { if (!e) return; const abortRequest = () => t(); if (!e.aborted) return e.addEventListener("abort", abortRequest, { once: true }), () => e.removeEventListener("abort", abortRequest); abortRequest(); }, createAnthropicBody = e => { const t = e.messages.filter((e => "system" === e.role)).map((e => contentToText(e.content))).join("\n"), n = { model: e.config.model, messages: e.messages.filter((e => "system" !== e.role)).map((e => ({ role: e.role, content: contentToText(e.content) }))), stream: false }; return t && (n.system = t), void 0 !== e.config.temperature && (n.temperature = e.config.temperature), n.max_tokens = e.config.maxTokens ?? 1024, n; }, isMultimodalContent = e => Array.isArray(e), hasMultimodalMessage = e => e.some((e => isMultimodalContent(e.content))), isLongCatConfig = e => "longcat" === e.providerId, toDataImageUrl = e => "url" === e.source ? e.data : `data:${e.mimeType || "image/png"};base64,${e.data}`, serializeMultimodalContent = (e, t) => e.map((e => isLongCatConfig(t) ? (e => "text" === e.type ? { type: "text", text: e.text } : { type: "input_image", input_image: { type: e.source, data: [ e.data ] } })(e) : (e => "text" === e.type ? { type: "text", text: e.text } : { type: "image_url", image_url: { url: toDataImageUrl(e) } })(e))), serializeOpenAiMessages = (e, t) => { if (isLongCatConfig(t) && hasMultimodalMessage(e)) { const n = e.filter((e => "system" === e.role)).map((e => contentToText(e.content))).filter(Boolean).join("\n"), a = []; for (const t of e.filter((e => "system" !== e.role))) "string" == typeof t.content ? a.push({ type: "text", text: t.content }) : a.push(...t.content.map((e => ({ ...e })))); if (n) { const e = a.find((e => "text" === e.type)); e ? e.text = `${n}\n\n${e.text}` : a.unshift({ type: "text", text: n }); } return [ { role: "user", content: serializeMultimodalContent(a, t) } ]; } return e.map((e => ({ role: e.role, content: isMultimodalContent(e.content) ? serializeMultimodalContent(e.content, t) : e.content }))); }, createOpenAiBody = (e, t = true) => { const n = { ...t ? e.config.disableThinkingParams : void 0, model: e.config.model, messages: serializeOpenAiMessages(e.messages, e.config), stream: e.stream }; return isLongCatConfig(e.config) && hasMultimodalMessage(e.messages) && (n.output_modalities = [ "text" ]), void 0 !== e.config.temperature && (n.temperature = e.config.temperature), void 0 !== e.config.maxTokens && (n.max_tokens = e.config.maxTokens), n; }, fe = [ 400, 422 ], normalizeOpenAiChunk = e => { const t = null == e ? void 0 : e.choices; return Array.isArray(t) ? t.map((e => { var t; return null == (t = e.delta) ? void 0 : t.content; })).filter((e => "string" == typeof e)).join("") : ""; }, ge = ((e = {}) => { const t = e.transport || createAiTransportRequest; return { id: e.id || "openai-compatible", chat: async e => { var n; assertConfigAvailable(e.config); const a = Date.now(), r = e.endpoint ?? { url: `${trimTrailingSlash(e.config.baseUrl)}/chat/completions`, headers: { Authorization: `Bearer ${(null == (n = e.config.credential) ? void 0 : n.value) || ""}`, "Content-Type": "application/json", Accept: "application/json" }, timeout: e.config.timeout }; let i = false; const attempt = async n => { let s = ""; const o = createSsePacketParser(), emit = t => { var n; s += t, i = true, null == (n = e.onToken) || n.call(e, t); }, l = t({ method: "POST", url: r.url, headers: r.headers, data: JSON.stringify(createOpenAiBody(e, n)), timeout: r.timeout, responseType: e.stream ? "stream" : "json", onStreamChunk: e.stream ? e => { const t = o; for (const n of t.push(e)) { const e = normalizeOpenAiChunk(n); e && emit(e); } } : void 0 }), c = bindAbortSignal(e.signal, l.abort); try { const t = await l.promise; if (e.stream) { for (const e of o.flush()) { const t = normalizeOpenAiChunk(e); t && emit(t); } if (!s) throw createAiError("AI_RESPONSE_PARSE_FAILED"); } else s = (e => { var t, n, a; const r = null == (a = null == (n = null == (t = null == e ? void 0 : e.choices) ? void 0 : t[0]) ? void 0 : n.message) ? void 0 : a.content; if ("string" != typeof r || !r) throw createAiError("AI_RESPONSE_PARSE_FAILED"); return r; })(parseJsonResponse(t)); return { text: s, raw: t.response, duration: Date.now() - a }; } finally { null == c || c(); } }; try { return await attempt(!0); } catch (s) { if (!((e, t, n) => { var a; if (n) return false; if (!t.config.disableThinkingParams) return false; if (!isAiError(e)) return false; const r = null == (a = e.detail) ? void 0 : a.status; return "number" == typeof r && fe.includes(r); })(s, e, i)) throw s; return attempt(false); } } }; })(), ve = ((e = {}) => { const t = e.transport || createAiTransportRequest; return { id: "anthropic-messages", chat: async e => { var n; assertConfigAvailable(e.config); const a = Date.now(), r = e.endpoint ?? { url: `${trimTrailingSlash(e.config.baseUrl)}/messages`, headers: { "x-api-key": (null == (n = e.config.credential) ? void 0 : n.value) || "", "anthropic-version": "2023-06-01", "Content-Type": "application/json" }, timeout: e.config.timeout }, i = t({ method: "POST", url: r.url, headers: r.headers, data: JSON.stringify(createAnthropicBody(e)), timeout: r.timeout, responseType: "json" }), s = bindAbortSignal(e.signal, i.abort); try { const e = await i.promise, t = (e => { const t = null == e ? void 0 : e.content; if (!Array.isArray(t)) throw createAiError("AI_RESPONSE_PARSE_FAILED"); const n = t.map((e => e.text)).filter((e => "string" == typeof e)).join(""); if (!n) throw createAiError("AI_RESPONSE_PARSE_FAILED"); return n; })(parseJsonResponse(e)); return { text: t, raw: e.response, duration: Date.now() - a }; } finally { null == s || s(); } } }; })(), ye = { 0: '\u4f60\u53ea\u4f5c\u4e3a\u201cJSON \u8f93\u51fa\u673a\u5668\u201d\u5de5\u4f5c\uff0c\u56de\u7b54\u65f6\u4ec5\u8f93\u51fa\u4e00\u884c JSON\uff0c\u7981\u6b62\u51fa\u73b0\u9664 JSON \u4ee5\u5916\u7684\u4efb\u4f55\u7b26\u53f7\u3001\u8bf4\u660e\u6216\u7a7a\u884c\u3002\n\n\u3010\u9898\u578b\u3011\u5355\u9009\u9898\n\n\u3010\u552f\u4e00\u5141\u8bb8\u7684\u8f93\u51fa\u683c\u5f0f\u3011\n{"answer":["\u9009\u9879\u5b57\u6bcd"]}\n\n\u3010\u5f3a\u5236\u89c4\u5219\u3011\n1. \u9009\u9879\u5b57\u6bcd\u5fc5\u987b\u5927\u5199\uff0c\u6570\u7ec4\u4e2d\u53ea\u80fd\u6709 1 \u4e2a\u5143\u7d20\u3002\n2. \u4e0d\u591f\u786e\u5b9a\u65f6\u8fd4\u56de\u7a7a\u6570\u7ec4\uff1a{"answer":[]}\n3. \u8f93\u51fa\u4f1a\u88ab JSON.parse \u76f4\u63a5\u89e3\u6790\uff0c\u51fa\u73b0\u4efb\u4f55\u975e JSON \u5185\u5bb9\u89c6\u4e3a\u5931\u8d25\u3002', 1: '\u4f60\u53ea\u4f5c\u4e3a\u201cJSON \u8f93\u51fa\u673a\u5668\u201d\u5de5\u4f5c\uff0c\u56de\u7b54\u65f6\u4ec5\u8f93\u51fa\u4e00\u884c JSON\uff0c\u7981\u6b62\u51fa\u73b0\u9664 JSON \u4ee5\u5916\u7684\u4efb\u4f55\u7b26\u53f7\u3001\u8bf4\u660e\u6216\u7a7a\u884c\u3002\n\n\u3010\u9898\u578b\u3011\u591a\u9009\u9898\n\n\u3010\u552f\u4e00\u5141\u8bb8\u7684\u8f93\u51fa\u683c\u5f0f\u3011\n{"answer":["\u9009\u9879\u5b57\u6bcd"]}\n\n\u3010\u5f3a\u5236\u89c4\u5219\u3011\n1. \u9009\u9879\u5b57\u6bcd\u5fc5\u987b\u5927\u5199\uff0c\u5e76\u6309\u5b57\u6bcd\u5347\u5e8f\u6392\u5e8f\u3002\n2. \u81f3\u5c11\u4e24\u4e2a\u9009\u9879\u624d\u7b97\u6709\u6548\uff0c\u4e0d\u786e\u5b9a\u65f6\u8fd4\u56de\u7a7a\u6570\u7ec4\uff1a{"answer":[]}\n3. \u8f93\u51fa\u4f1a\u88ab JSON.parse \u76f4\u63a5\u89e3\u6790\uff0c\u51fa\u73b0\u4efb\u4f55\u975e JSON \u5185\u5bb9\u89c6\u4e3a\u5931\u8d25\u3002', 2: '\u4f60\u53ea\u4f5c\u4e3a\u201cJSON \u8f93\u51fa\u673a\u5668\u201d\u5de5\u4f5c\uff0c\u56de\u7b54\u65f6\u4ec5\u8f93\u51fa\u4e00\u884c JSON\uff0c\u7981\u6b62\u51fa\u73b0\u9664 JSON \u4ee5\u5916\u7684\u4efb\u4f55\u7b26\u53f7\u3001\u8bf4\u660e\u6216\u7a7a\u884c\u3002\n\n\u3010\u9898\u578b\u3011\u586b\u7a7a\u9898\n\n\u3010\u552f\u4e00\u5141\u8bb8\u7684\u8f93\u51fa\u683c\u5f0f\u3011\n{"answer":["\u7b54\u68481","\u7b54\u68482"]}\n\n\u3010\u5f3a\u5236\u89c4\u5219\u3011\n1. \u7b54\u6848\u6570\u91cf\u5fc5\u987b\u5339\u914d\u9898\u76ee\u7a7a\u683c\u6570\uff0c\u4e0d\u5f97\u7f3a\u5931\u6216\u591a\u586b\u3002\n2. \u4e0d\u591f\u786e\u5b9a\u65f6\u8fd4\u56de\u7a7a\u6570\u7ec4\uff1a{"answer":[]}\n3. \u8f93\u51fa\u4f1a\u88ab JSON.parse \u76f4\u63a5\u89e3\u6790\uff0c\u51fa\u73b0\u4efb\u4f55\u975e JSON \u5185\u5bb9\u89c6\u4e3a\u5931\u8d25\u3002', 3: '\u4f60\u53ea\u4f5c\u4e3a\u201cJSON \u8f93\u51fa\u673a\u5668\u201d\u5de5\u4f5c\uff0c\u56de\u7b54\u65f6\u4ec5\u8f93\u51fa\u4e00\u884c JSON\uff0c\u7981\u6b62\u51fa\u73b0\u9664 JSON \u4ee5\u5916\u7684\u4efb\u4f55\u7b26\u53f7\u3001\u8bf4\u660e\u6216\u7a7a\u884c\u3002\n\n\u3010\u9898\u578b\u3011\u5224\u65ad\u9898\n\n\u3010\u552f\u4e00\u5141\u8bb8\u7684\u8f93\u51fa\u683c\u5f0f\u3011\n{"answer":"\u6b63\u786e"}\n\u6216\n{"answer":"\u9519\u8bef"}\n\n\u3010\u5f3a\u5236\u89c4\u5219\u3011\n1. answer \u53ea\u80fd\u662f\u201c\u6b63\u786e\u201d\u6216\u201c\u9519\u8bef\u201d\uff0c\u4e0d\u786e\u5b9a\u65f6\u8f93\u51fa\u7a7a\u5b57\u7b26\u4e32\uff1a{"answer":""}\n2. \u8f93\u51fa\u4f1a\u88ab JSON.parse \u76f4\u63a5\u89e3\u6790\uff0c\u51fa\u73b0\u4efb\u4f55\u975e JSON \u5185\u5bb9\u89c6\u4e3a\u5931\u8d25\u3002', 4: '\u4f60\u53ea\u4f5c\u4e3a\u201cJSON \u8f93\u51fa\u673a\u5668\u201d\u5de5\u4f5c\uff0c\u56de\u7b54\u65f6\u4ec5\u8f93\u51fa\u4e00\u884c JSON\uff0c\u7981\u6b62\u51fa\u73b0\u9664 JSON \u4ee5\u5916\u7684\u4efb\u4f55\u7b26\u53f7\u3001\u8bf4\u660e\u6216\u7a7a\u884c\u3002\n\n\u3010\u9898\u578b\u3011\u7b80\u7b54\u9898\n\n\u3010\u552f\u4e00\u5141\u8bb8\u7684\u8f93\u51fa\u683c\u5f0f\u3011\n{"answer":"\u7cbe\u7b80\u7684\u7b54\u6848"}\n\n\u3010\u5f3a\u5236\u89c4\u5219\u3011\n1. \u76f4\u63a5\u7ed9\u51fa\u7cbe\u7b80\u7b54\u6848\uff0c\u4e0d\u8981\u8d58\u8ff0\u3002\n2. \u4e0d\u591f\u786e\u5b9a\u65f6\u8f93\u51fa\u7a7a\u5b57\u7b26\u4e32\uff1a{"answer":""}\n3. \u8f93\u51fa\u4f1a\u88ab JSON.parse \u76f4\u63a5\u89e3\u6790\uff0c\u51fa\u73b0\u4efb\u4f55\u975e JSON \u5185\u5bb9\u89c6\u4e3a\u5931\u8d25\u3002', 15: '\u4f60\u53ea\u4f5c\u4e3a\u201cJSON \u8f93\u51fa\u673a\u5668\u201d\u5de5\u4f5c\uff0c\u56de\u7b54\u65f6\u4ec5\u8f93\u51fa\u4e00\u884c JSON\uff0c\u7981\u6b62\u51fa\u73b0\u9664 JSON \u4ee5\u5916\u7684\u4efb\u4f55\u7b26\u53f7\u3001\u8bf4\u660e\u6216\u7a7a\u884c\u3002\n\n\u3010\u9898\u578b\u3011\u9605\u8bfb\u7406\u89e3\n\n\u3010\u552f\u4e00\u5141\u8bb8\u7684\u8f93\u51fa\u683c\u5f0f\u3011\n{"answer":[["A"],["B"]]}\n\n\u3010\u5f3a\u5236\u89c4\u5219\u3011\n1. answer \u5fc5\u987b\u662f\u4e8c\u7ef4\u6570\u7ec4\uff0c\u5916\u5c42\u6570\u7ec4\u6570\u91cf\u5fc5\u987b\u7b49\u4e8e\u5b50\u9898\u6570\u91cf\u3002\n2. \u5355\u9009\u9898\u5b50\u9898\u586b\u5199 1 \u4e2a\u9009\u9879\u5b57\u6bcd\uff0c\u591a\u9009\u9898\u5b50\u9898\u53ef\u586b\u5199\u591a\u4e2a\u9009\u9879\u5b57\u6bcd\u3002\n3. \u5224\u65ad\u9898\u5b50\u9898\u586b\u5199\u201c\u6b63\u786e\u201d\u6216\u201c\u9519\u8bef\u201d\uff0c\u4e0d\u8981\u586b\u5199\u9009\u9879\u5b57\u6bcd\u3002\n4. \u9009\u9879\u5b57\u6bcd\u5fc5\u987b\u5927\u5199\uff0c\u591a\u9009\u9898\u6309\u5b57\u6bcd\u5347\u5e8f\u6392\u5e8f\u3002\n5. \u67d0\u4e2a\u5b50\u9898\u4e0d\u786e\u5b9a\u65f6\uff0c\u8be5\u5b50\u9898\u8fd4\u56de\u7a7a\u6570\u7ec4\uff0c\u4f8b\u5982 {"answer":[[],["B"]]}\u3002\n6. \u8f93\u51fa\u4f1a\u88ab JSON.parse \u76f4\u63a5\u89e3\u6790\uff0c\u51fa\u73b0\u4efb\u4f55\u975e JSON \u5185\u5bb9\u89c6\u4e3a\u5931\u8d25\u3002' }, be = [ "api.deepseek.com", "dashscope.aliyuncs.com", "open.bigmodel.cn", "qianfan.baidubce.com", "ark.cn-beijing.volces.com", "api.hunyuan.cloud.tencent.com", "api.longcat.chat", "api.moonshot.ai", "api.siliconflow.cn", "api.openai.com", "api.anthropic.com", "generativelanguage.googleapis.com", "openrouter.ai", "api.groq.com", "api.together.ai", "api.mistral.ai" ], canDirectConnect = e => { if (!e.directConnect) return false; let t; try { t = new URL(e.baseUrl).hostname; } catch { return false; } return be.some((e => t === e || t.endsWith(`.${e}`))); }, toThrownError = e => { const t = (e => e && me.includes(e) ? e : "AI_NETWORK_FAILED")(e.code); return isAiError(e.error) && e.error.code === t ? e.error : createAiError(t); }, we = "https://zhiku.ahzsksw.cn", trimSlash = e => e.replace(/\/+$/, ""), xe = { "anthropic-messages": e => ({ "x-api-key": e, "anthropic-version": "2023-06-01", "Content-Type": "application/json" }), "openai-compatible": e => ({ Authorization: `Bearer ${e}`, "Content-Type": "application/json", Accept: "application/json" }) }, codeFor = (e, t) => "upstream" === e ? 401 === t || 403 === t ? "AI_AUTH_FAILED" : "AI_NETWORK_FAILED" : 401 === t ? "AI_PROXY_LOGIN_REQUIRED" : 429 === t ? "AI_PROXY_RATE_LIMITED" : "AI_PROXY_UNAVAILABLE"; function randomString(e) { let t = ""; for (;t.length < e; t += Math.random().toString(36).substring(2)) ; return t.substring(0, e); } const runAiScene = async (e, t, n, a = {}) => { var r; if (!t) return (() => { const e = createAiError("AI_CONFIG_MISSING", { userMessage: "AI \u914d\u7f6e\u7f3a\u5931\uff0c\u8bf7\u5148\u5b8c\u6210\u914d\u7f6e" }); return { success: false, text: "", duration: 0, error: e, displayMessage: getAiErrorMessage(e) }; })(); try { const i = a.provider || (null == (r = a.resolveProvider) ? void 0 : r.call(a, t)) || (e => { switch (e) { case "openai-compatible": return ge; case "anthropic-messages": return ve; } })(t.providerKind), s = ((e, t, n = "4") => [ { role: "system", content: "ask" === e ? ye[n] || ye[4] : "repair" === e ? "\u4f60\u662f\u4e00\u4e2a\u4e13\u4e1a\u7684\u7b54\u9898\u52a9\u624b\uff0c\u8bf7\u4fee\u590d\u7b54\u6848\u4e2d\u7f3a\u5931\u3001\u683c\u5f0f\u9519\u8bef\u6216\u8868\u8ff0\u4e0d\u6e05\u7684\u5185\u5bb9\u3002\u8f93\u51fa\u5e94\u4ee5\u4fee\u590d\u7b54\u6848\u4e3a\u4e3b\uff0c\u4fdd\u6301\u51c6\u786e\u3001\u7b80\u6d01\uff0c\u5e76\u907f\u514d\u65e0\u5173\u89e3\u91ca\u3002" : "\u4f60\u662f\u4e00\u4e2a\u4e13\u4e1a\u7684\u7b54\u9898\u52a9\u624b\uff0c\u8bf7\u6839\u636e\u7528\u6237\u63d0\u4f9b\u7684\u9898\u76ee\u8fdb\u884c\u89e3\u7b54\u3002\u56de\u7b54\u5e94\u51c6\u786e\u3001\u7b80\u6d01\uff0c\u5fc5\u8981\u65f6\u7ed9\u51fa\u7b80\u8981\u7406\u7531\u3002" }, { role: "user", content: t } ])(e, n, a.questionType), o = a.stream ?? t.stream; if (!a.route) { const e = await i.chat({ config: t, messages: s, stream: o, onToken: a.onToken, signal: a.signal }); return { success: !0, text: e.text, duration: e.duration }; } const l = Date.now(), c = await (async e => { const t = canDirectConnect(e.channel), runDirect = async t => { const n = await e.callDirect(e.channel, (t => { var n; return null == (n = e.onToken) ? void 0 : n.call(e, t); })); if (!n.ok) throw toThrownError(n); return { servedBy: "direct", fallbackUsed: t, text: n.text || "" }; }; if (!e.loggedIn || "auto" !== e.transport) { if (!t) throw createAiError("AI_DIRECT_BLOCKED"); return runDirect(!1); } let n = !1; const a = await e.callProxy(e.channel, (t => { var a; n = !0, null == (a = e.onToken) || a.call(e, t); })); if (a.ok) return { servedBy: "proxy", fallbackUsed: !1, text: a.text || "" }; if ("upstream" === a.stage) throw toThrownError(a); if (n) throw toThrownError(a); if (!t) throw createAiError("AI_DIRECT_BLOCKED"); return runDirect(!0); })({ channel: a.route.channel, loggedIn: Boolean(a.route.apiKey), transport: a.route.transport, onToken: a.onToken, callProxy: async () => ({ok: false, stage: "proxy", error: createAiError("AI_PROXY_UNAVAILABLE")}), callDirect: async (e, n) => { var r; const l = ((e, t) => ({ url: "anthropic-messages" === e.providerKind ? `${trimSlash(e.baseUrl)}/messages` : `${trimSlash(e.baseUrl)}/chat/completions`, headers: xe[e.providerKind](t), timeout: e.timeout }))(e, (null == (r = t.credential) ? void 0 : r.value) || ""); try { return { ok: !0, text: (await i.chat({ config: t, messages: s, stream: o, onToken: n, signal: a.signal, endpoint: l })).text }; } catch (c) { return { ok: !1, code: isAiError(c) ? c.code : void 0, error: c }; } } }); return { success: !0, text: c.text, duration: Date.now() - l, servedBy: c.servedBy, fallbackUsed: c.fallbackUsed }; } catch (i) { const e = isAiError(i) ? i : createAiError("AI_NETWORK_FAILED", { cause: i }); return { success: false, text: "", duration: 0, error: e, displayMessage: getAiErrorMessage(e) }; } }, ke = new Set([ "\u6682\u65e0KEY", "\u65e0KEY", "\u6682\u65e0APIKEY", "\u65e0APIKEY", "\u672a\u914d\u7f6eKEY", "\u672a\u914d\u7f6eAPIKEY", "\u672a\u586b\u5199KEY", "\u672a\u586b\u5199APIKEY", "APIKEY\u7f3a\u5931", "\u8bf7\u586b\u5199KEY", "\u8bf7\u586b\u5199APIKEY", "\u8bf7\u914d\u7f6eKEY", "\u8bf7\u914d\u7f6eAPIKEY", "\u6682\u65e0\u7b54\u6848", "\u6682\u65e0\u7b54\u6848\u4fe1\u606f", "\u65e0\u7b54\u6848", "\u6ca1\u6709\u7b54\u6848", "\u672a\u627e\u5230\u7b54\u6848", "\u672a\u67e5\u8be2\u5230\u7b54\u6848", "\u672a\u68c0\u7d22\u5230\u7b54\u6848", "\u67e5\u8be2\u4e0d\u5230\u7b54\u6848", "\u8bf7\u767b\u5f55", "\u8bf7\u5148\u767b\u5f55", "\u672a\u767b\u5f55", "\u9274\u6743\u5931\u8d25", "\u672a\u6388\u6743", "\u65e0\u6743\u9650", "\u8bf7\u6c42\u5931\u8d25", "\u7f51\u7edc\u5f02\u5e38", "\u7f51\u7edc\u8bf7\u6c42\u5931\u8d25", "\u54cd\u5e94\u89e3\u6790\u5931\u8d25", "\u63a5\u53e3\u5f02\u5e38", "\u63a5\u53e3\u8bf7\u6c42\u5931\u8d25", "\u63a5\u53e3\u8bf7\u6c42\u8d85\u65f6", "\u8bf7\u6c42\u8d85\u65f6", "\u6b21\u6570\u4e0d\u8db3", "\u4f59\u989d\u4e0d\u8db3", "\u989d\u5ea6\u4e0d\u8db3" ]), qe = [ /^\u6682\u672a(\u6536\u5f55|\u627e\u5230|\u67e5\u8be2\u5230|\u68c0\u7d22\u5230)(\u53c2\u8003)?\u7b54\u6848(\u4fe1\u606f)?$/, /^\u672a(\u627e\u5230|\u67e5\u8be2\u5230|\u68c0\u7d22\u5230)(\u53c2\u8003)?\u7b54\u6848(\u4fe1\u606f)?$/, /^\u6ca1\u6709(\u627e\u5230|\u67e5\u8be2\u5230|\u68c0\u7d22\u5230)?(\u53c2\u8003)?\u7b54\u6848(\u4fe1\u606f)?$/, /^\u8bf7(\u5148)?\u767b\u5f55\u540e(\u518d)?(\u67e5\u770b|\u4f7f\u7528|\u641c\u7d22|\u67e5\u8be2).*$/, /^\u767b\u5f55\u540e\u624d\u53ef\u4ee5\u4f7f\u7528.*$/, /^AI(\u51ed\u8bc1|\u914d\u7f6e|\u54cd\u5e94|\u8bf7\u6c42).*(\u7f3a\u5931|\u5f02\u5e38|\u5931\u8d25|\u9519\u8bef).*$/, /^API\s*KEY\s*(\u7f3a\u5931|\u672a\u586b\u5199|\u672a\u914d\u7f6e|\u65e0\u6548).*$/i, /^(\u8bf7\u6c42|\u63a5\u53e3|\u7f51\u7edc).*(\u5931\u8d25|\u5f02\u5e38|\u8d85\u65f6).*$/, /^(\u6b21\u6570|\u4f59\u989d|\u989d\u5ea6).*(\u4e0d\u8db3|\u5df2\u7528\u5b8c).*$/ ], isNonAnswerText = e => { if ("string" != typeof e) return false; const t = e.trim(); return !!t && (!!ke.has((e => e.trim().replace(/\s+/g, "").toUpperCase())(t)) || qe.some((e => e.test(t)))); }, findNonAnswerText = e => { if ("string" == typeof e && isNonAnswerText(e)) return e.trim(); if (Array.isArray(e)) for (const t of e) { const e = findNonAnswerText(t); if (e) return e; } }, Ae = new Set([ "\u5bf9", "\u6b63\u786e", "\u771f", "true", "t", "\u221a", "\u2713", "1", "\u662f", "yes", "y", "right", "correct", "ri" ]), _e = new Set([ "\u9519", "\u9519\u8bef", "\u5047", "\u4e0d\u6b63\u786e", "false", "f", "\xd7", "\u2715", "x", "0", "\u5426", "no", "n", "wrong", "incorrect", "wr" ]), splitAnswerText = (e, t) => e.split(t).map((e => e.trim())).filter(Boolean), normalizeJudgeAnswer = e => { const t = normalizeComparableText(e).toLowerCase(); return Ae.has(t) ? "\u6b63\u786e" : _e.has(t) ? "\u9519\u8bef" : null; }, isJudgeChoiceOptions = e => { if (2 !== e.length || !e.every((e => "string" == typeof e))) return false; const t = e.map((e => normalizeComparableText(e).toLowerCase())); if (!t.every((e => /^(?:\u5bf9|\u9519|\u6b63\u786e|\u9519\u8bef|\u771f|\u5047|\u221a|\u2713|\xd7|\u2715|\u662f|\u5426|true|false|t|f|yes|no)$/.test(e)))) return false; const n = t.map(normalizeJudgeAnswer); return n.includes("\u6b63\u786e") && n.includes("\u9519\u8bef"); }, flattenAnswerTexts = e => null == e ? [] : Array.isArray(e) ? e.flatMap(flattenAnswerTexts) : "object" == typeof e ? Object.values(e).flatMap(flattenAnswerTexts) : [ String(e) ], mapChoiceLetterToOption = (e, t) => { var n; const a = e.trim().toUpperCase(); if (/^[A-Z]$/.test(a)) return (null == (n = t[a.charCodeAt(0) - 65]) ? void 0 : n.trim()) || void 0; }, resolveJudgeAnswer = (e, t) => { const n = "string" == typeof e && t.every((e => "string" == typeof e)) && isJudgeChoiceOptions(t) ? mapChoiceLetterToOption(e, t) : void 0; return normalizeJudgeAnswer(n ?? e); }, mapChoiceValueToOption = (e, t) => { var n; const a = mapChoiceLetterToOption(e, t); if (a) return a; const r = e.trim(); return null == (n = t.find((e => e.trim() === r))) ? void 0 : n.trim(); }, Te = new Set([ "4", "5", "6", "7" ]), invalid = (e, t, n) => ({ valid: false, answer: [], raw: t, error: createAiError(e, { detail: n }) }), extractCodeBlockJson = e => { var t; const n = e.match(/```(?:json)?\s*([\s\S]*?)```/i); return null == (t = null == n ? void 0 : n[1]) ? void 0 : t.trim(); }, findJsonObjectText = e => { const t = e.indexOf("{"); if (t < 0) return; let n = 0, a = false, r = false; for (let i = t; i < e.length; i++) { const s = e[i]; if (r) r = false; else if ("\\" !== s) if ('"' !== s) { if (!a && ("{" === s && n++, "}" === s && n--, 0 === n)) return e.slice(t, i + 1); } else a = !a; else r = true; } return e.slice(t); }, normalizeTextAnswer = e => { if ("string" != typeof e) return; return e.trim() || void 0; }, normalizeTextArray = e => { if (!Array.isArray(e)) return; const t = e.map((e => "string" == typeof e ? e.trim() : "")).filter(Boolean); return t.length === e.length ? t : void 0; }, getChoiceOptions = e => e.filter((e => "string" == typeof e)), parseSingleChoice = (e, t, n) => { const a = Array.isArray(e) ? normalizeTextArray(e) : [ normalizeTextAnswer(e) ].filter((e => Boolean(e))); if (!a || 1 !== a.length) return invalid("AI_OUTPUT_SCHEMA_INVALID", t); const r = mapChoiceValueToOption(a[0], getChoiceOptions(n.options)); return r ? { valid: true, answer: [ r ], raw: t } : invalid("AI_ANSWER_NOT_MATCHED", t, { answer: a[0] }); }, parseMultipleChoice = (e, t, n) => { const a = normalizeTextArray(e) || (e => { const t = normalizeTextAnswer(e); if (!t) return; const n = splitAnswerText(t, /[\n,\uff0c\u3001;\uff1b]+/); return n.length > 1 ? n : void 0; })(e); if (!a || a.length < 2) return invalid("AI_OUTPUT_SCHEMA_INVALID", t); if (new Set(a.map((e => e.trim().toUpperCase()))).size !== a.length) return invalid("AI_ANSWER_NOT_MATCHED", t, { answer: a }); const r = a.map((e => mapChoiceValueToOption(e, getChoiceOptions(n.options)))); return r.some((e => !e)) ? invalid("AI_ANSWER_NOT_MATCHED", t, { answer: a }) : { valid: true, answer: r, raw: t }; }, parseBlank = (e, t, n) => { const a = normalizeTextArray(e); return a ? n.blankCount > 0 && a.length !== n.blankCount || 0 === n.blankCount && 0 === a.length || a.some(isNonAnswerText) ? invalid("AI_OUTPUT_SCHEMA_INVALID", t) : { valid: true, answer: a, raw: t } : invalid("AI_OUTPUT_SCHEMA_INVALID", t); }, parseJudgement = (e, t) => { const n = normalizeTextAnswer(e); return "\u6b63\u786e" !== n && "\u9519\u8bef" !== n ? invalid("AI_OUTPUT_SCHEMA_INVALID", t) : { valid: true, answer: [ n ], raw: t }; }, parseSubjective = (e, t) => { const n = normalizeTextAnswer(e); return n ? isNonAnswerText(n) ? invalid("AI_OUTPUT_SCHEMA_INVALID", t) : { valid: true, answer: [ n ], raw: t } : invalid("AI_OUTPUT_SCHEMA_INVALID", t); }, isSubQuestionMeta = e => "object" == typeof e && null !== e && Array.isArray(e.options), parseReadingChoice = (e, t, n) => { if (Array.isArray(e) && 0 === e.length) return { valid: true, answer: [], raw: t }; const a = { type: n.type || "0", options: n.options || [], blankCount: 0 }; if ("1" === a.type) return parseMultipleChoice(e, t, a); if ("3" === a.type) { const [n] = normalizeTextArray(e) || []; return parseJudgement(n, t); } if ("2" === a.type) return parseBlank(e, t, a); if (Te.has(a.type)) { const [n] = normalizeTextArray(e) || []; return parseSubjective(n, t); } return parseSingleChoice(e, t, a); }, parseAiAnswer = (e, t) => { const n = (e => { const t = [ e.trim(), extractCodeBlockJson(e), findJsonObjectText(e) ].filter((e => Boolean(e))); for (const a of t) try { return { ok: !0, value: JSON.parse(a) }; } catch (n) { if (a === t[t.length - 1]) return { ok: false, cause: n }; } return { ok: false }; })(e); if (!n.ok) return { valid: false, answer: [], error: createAiError("AI_RESPONSE_PARSE_FAILED", { cause: n.cause }) }; const a = n.value, r = (e => { if ("object" == typeof e && null !== e && "answer" in e) return e.answer; })(a); return void 0 === r ? invalid("AI_OUTPUT_SCHEMA_INVALID", a) : "0" === t.type ? parseSingleChoice(r, a, t) : "1" === t.type ? parseMultipleChoice(r, a, t) : "2" === t.type ? parseBlank(r, a, t) : "3" === t.type ? parseJudgement(r, a) : Te.has(t.type) ? parseSubjective(r, a) : "15" === t.type ? ((e, t, n) => { const a = n.options.filter(isSubQuestionMeta); if (!Array.isArray(e) || 0 === a.length || e.length !== a.length) return invalid("AI_OUTPUT_SCHEMA_INVALID", t); const r = []; for (let i = 0; i < a.length; i++) { const n = parseReadingChoice(e[i], t, a[i]); if (!n.valid) return n; if (n.answer.some(Array.isArray)) return invalid("AI_OUTPUT_SCHEMA_INVALID", t); r.push(n.answer); } return { valid: true, answer: r, raw: t }; })(r, a, t) : invalid("AI_QUESTION_TYPE_UNSUPPORTED", a, { type: t.type }); }, hasUnsupportedMedia = e => { const t = (e => e.replace(/<[^>]*>/g, " "))(e); return /<\s*img\b/i.test(e) || /<\s*(?:svg|image)\b/i.test(e) || /<\s*math\b/i.test(e) || /<\s*script\b[^>]*type\s*=\s*["']?math\/tex/i.test(e) || hasUnsupportedMathClass(e) || /!\[[^\]]*]\([^)]*\)/.test(t) || /\$\$/.test(t) || /(^|[^\w\d])\$[^\s$][^$\n]*\$(?!\d)/.test(t) || /\\\(/.test(t) || /\\\[/.test(t); }, hasUnsupportedMathClass = e => { for (const t of e.matchAll(/class\s*=\s*["']([^"']*)["']/g)) { if (t[1].split(/\s+/).filter(Boolean).some((e => "MathJax" === e || e.startsWith("MathJax_") || "katex" === e || e.startsWith("katex-") || e.startsWith("mjx-")))) return true; } return false; }, Ce = /\uff08[^\S\r\n]*\uff09|\([^\S\r\n]*\)|\[[^\S\r\n]*\]|[_\uff3f]{2,}|[-\uff0d]{2,}|[\u2014\u2015\u2500\u2501]+|\t+/g, countBlankPlaceholders = e => Array.from(e.matchAll(Ce)).length, normalizeQuestionWhitespace = e => e.replace(/[^\S\t]+/g, " ").replace(/^ +| +$/g, ""), Se = /^([A-Ha-h\uff21-\uff28\uff41-\uff48])(?:\s*[.\uff0e\u3002\u3001)\uff09]\s*|\s+)(.+)$/, Ie = /^(\u7b54\u6848|\u89e3\u6790|\u63d0\u793a)\s*[:\uff1a]/, Ee = /^((\d+|[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07]+)[\s.\uff0e\u3002\u3001)\uff09]+)+/, cleanQuestionPrefix = e => normalizeQuestionWhitespace(e.replace(Ee, "")), Ue = { thinking: { type: "disabled" } }, withKeyHelp = e => ({ ...e, keyHelp: e.keyHelp || `\u767b\u5f55 ${e.name} \u63a7\u5236\u53f0\uff0c\u5728 API Key \u9875\u9762\u521b\u5efa\u6216\u590d\u5236 API Key\u3002` }), $e = [ withKeyHelp({ id: "deepseek", name: "DeepSeek", providerKind: "openai-compatible", baseUrl: "https://api.deepseek.com", defaultModel: "deepseek-v4-flash", models: [ "deepseek-v4-flash", "deepseek-v4-pro" ], stream: true, credentialType: "api-key", docUrl: "https://api-docs.deepseek.com/quick_start/pricing", keyUrl: "https://platform.deepseek.com/api_keys", region: "domestic" }), withKeyHelp({ id: "qwen-dashscope", name: "\u901a\u4e49\u5343\u95ee / \u767e\u70bc", providerKind: "openai-compatible", baseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1", defaultModel: "qwen3.7-plus", models: [ "qwen3.7-plus", "qwen3.7-flash", "qwen3.8-max", "qwen3.5-omni-plus" ], modelCapabilities: { "qwen3.7-plus": { text: true, image: true }, "qwen3.7-flash": { text: true, image: true }, "qwen3.8-max": { text: true, image: true }, "qwen3.5-omni-plus": { text: true, image: true } }, stream: true, credentialType: "api-key", docUrl: "https://help.aliyun.com/zh/model-studio/models", keyUrl: "https://help.aliyun.com/zh/model-studio/get-api-key", region: "domestic" }), withKeyHelp({ id: "zhipu-glm", name: "\u667a\u8c31 GLM", providerKind: "openai-compatible", baseUrl: "https://open.bigmodel.cn/api/paas/v4", defaultModel: "glm-4.7", models: [ "glm-4.7", "glm-4.7-flash", "glm-4.7-flashx", "glm-5", "glm-5-turbo", "glm-4.6", "glm-4.5-flash", "glm-4v-flash" ], modelCapabilities: { "glm-4v-flash": { text: true, image: true } }, stream: true, credentialType: "api-key", docUrl: "https://docs.bigmodel.cn/api-reference", keyUrl: "https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys", region: "domestic", disableThinkingParams: Ue }), withKeyHelp({ id: "baidu-qianfan", name: "\u767e\u5ea6\u5343\u5e06", providerKind: "openai-compatible", baseUrl: "https://qianfan.baidubce.com/v2", defaultModel: "ernie-5.0", models: [ "ernie-5.0", "ernie-5.1", "ernie-5.0-thinking-latest", "ernie-x1.1", "ernie-4.5-turbo-128k", "deepseek-v3.2", "ernie-4.5-turbo-vl-32k" ], modelCapabilities: { "ernie-5.0": { text: true, image: true }, "ernie-4.5-turbo-vl-32k": { text: true, image: true } }, timeout: 6e4, stream: true, credentialType: "api-key", docUrl: "https://cloud.baidu.com/doc/qianfan-docs/s/7m95lyy43", keyUrl: "https://console.bce.baidu.com/qianfan/ais/console/applicationConsole/application", region: "domestic", disableThinkingParams: Ue }), withKeyHelp({ id: "volc-ark", name: "\u706b\u5c71\u65b9\u821f / \u8c46\u5305", providerKind: "openai-compatible", baseUrl: "https://ark.cn-beijing.volces.com/api/v3", defaultModel: "doubao-seed-2-0-pro-260215", models: [ "doubao-seed-2-0-pro-260215", "doubao-seed-2-0-mini-260428", "doubao-seed-2-0-lite-260428" ], modelCapabilities: { "doubao-seed-2-0-pro-260215": { text: true, image: true }, "doubao-seed-2-0-mini-260428": { text: true, image: true }, "doubao-seed-2-0-lite-260428": { text: true, image: true } }, timeout: 6e4, stream: true, credentialType: "api-key", docUrl: "https://www.volcengine.com/docs/82379/1330310", keyUrl: "https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey", keyHelp: "\u767b\u5f55\u706b\u5c71\u65b9\u821f\u63a7\u5236\u53f0\u521b\u5efa API Key\u3002\u82e5\u8c03\u7528\u62a5\u6a21\u578b\u4e0d\u5b58\u5728\uff0c\u9700\u5148\u5728\u300c\u5728\u7ebf\u63a8\u7406\u300d\u521b\u5efa\u63a8\u7406\u63a5\u5165\u70b9\uff0c\u5e76\u628a\u6a21\u578b\u540d\u6362\u6210\u63a5\u5165\u70b9 ID\uff08ep- \u5f00\u5934\uff09\u3002", region: "domestic", disableThinkingParams: Ue }), withKeyHelp({ id: "tencent-hunyuan", name: "\u817e\u8baf\u6df7\u5143", providerKind: "openai-compatible", baseUrl: "https://api.hunyuan.cloud.tencent.com/v1", defaultModel: "hunyuan-turbos-latest", models: [ "hunyuan-turbos-latest", "hunyuan-a13b", "hunyuan-t1-latest", "hunyuan-translation" ], stream: true, credentialType: "api-key", docUrl: "https://cloud.tencent.com/document/product/1729/111007", keyUrl: "https://console.cloud.tencent.com/hunyuan/api-key", region: "domestic" }), withKeyHelp({ id: "longcat", name: "LongCat", providerKind: "openai-compatible", baseUrl: "https://api.longcat.chat/openai/v1", defaultModel: "LongCat-2.0", models: [ "LongCat-2.0" ], stream: true, credentialType: "api-key", docUrl: "https://longcat.chat/platform/docs/zh/", keyUrl: "https://longcat.chat/platform/api_keys", keyHelp: "\u767b\u5f55 LongCat API \u5f00\u653e\u5e73\u53f0\uff0c\u5728 API Keys \u9875\u9762\u70b9\u51fb\u201c\u521b\u5efa API Key\u201d\u751f\u6210\u5bc6\u94a5\u3002", region: "domestic" }), withKeyHelp({ id: "kimi", name: "Kimi / Moonshot", providerKind: "openai-compatible", baseUrl: "https://api.moonshot.ai/v1", defaultModel: "kimi-k3", models: [ "kimi-k3", "kimi-k2.7-code", "kimi-k2.6", "kimi-k2.5", "moonshot-v1-128k" ], stream: true, credentialType: "api-key", docUrl: "https://platform.kimi.ai/docs/api/chat", keyUrl: "https://platform.kimi.ai/console/api-keys", keyHelp: "\u767b\u5f55 platform.kimi.ai \u521b\u5efa API Key\u3002\u6ce8\u610f\uff1a\u56fd\u5185\u7ad9 platform.moonshot.cn \u7684 Key \u5728 api.moonshot.ai \u4e0a\u4e0d\u53ef\u7528\uff0c\u4e24\u8fb9\u8d26\u53f7\u72ec\u7acb\u3002", region: "domestic" }), withKeyHelp({ id: "siliconflow", name: "SiliconFlow", providerKind: "openai-compatible", baseUrl: "https://api.siliconflow.cn/v1", defaultModel: "deepseek-ai/DeepSeek-V3.2", models: [ "deepseek-ai/DeepSeek-V3.2", "Pro/deepseek-ai/DeepSeek-V3.2", "zai-org/GLM-5.2", "Pro/zai-org/GLM-5.1", "Qwen/Qwen3.5-397B-A17B", "Qwen/Qwen3.5-35B-A3B", "zai-org/GLM-4.5V" ], modelCapabilities: { "Qwen/Qwen3.5-397B-A17B": { text: true, image: true }, "Qwen/Qwen3.5-35B-A3B": { text: true, image: true }, "zai-org/GLM-4.5V": { text: true, image: true } }, stream: true, credentialType: "api-key", docUrl: "https://docs.siliconflow.cn/cn/api-reference/chat-completions/chat-completions", keyUrl: "https://cloud.siliconflow.cn/account/ak", region: "domestic" }), withKeyHelp({ id: "openai", name: "OpenAI", providerKind: "openai-compatible", baseUrl: "https://api.openai.com/v1", defaultModel: "gpt-5.6", models: [ "gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna" ], stream: true, credentialType: "api-key", docUrl: "https://developers.openai.com/api/docs/models", keyUrl: "https://platform.openai.com/api-keys", region: "global" }), withKeyHelp({ id: "anthropic", name: "Anthropic Claude", providerKind: "anthropic-messages", baseUrl: "https://api.anthropic.com/v1", defaultModel: "claude-sonnet-5", models: [ "claude-sonnet-5", "claude-opus-5", "claude-haiku-4-5-20251001", "claude-fable-5" ], stream: true, credentialType: "api-key", docUrl: "https://platform.claude.com/docs/en/about-claude/models/overview", keyUrl: "https://console.anthropic.com/settings/keys", region: "global" }), withKeyHelp({ id: "gemini", name: "Google Gemini", providerKind: "openai-compatible", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", defaultModel: "gemini-3.7-flash", models: [ "gemini-3.7-flash", "gemini-3.6-flash", "gemini-3.1-pro-preview", "gemini-2.5-flash", "gemini-2.5-pro" ], stream: true, credentialType: "api-key", docUrl: "https://ai.google.dev/gemini-api/docs/models", keyUrl: "https://aistudio.google.com/app/apikey", region: "global" }), withKeyHelp({ id: "openrouter", name: "OpenRouter", providerKind: "openai-compatible", baseUrl: "https://openrouter.ai/api/v1", defaultModel: "openai/gpt-5.6-luna", models: [ "openai/gpt-5.6-luna", "openai/gpt-5.6-terra", "anthropic/claude-sonnet-5", "google/gemini-3.7-flash", "deepseek/deepseek-v4-flash-0731", "moonshotai/kimi-k3" ], stream: true, credentialType: "api-key", docUrl: "https://openrouter.ai/docs/api-reference/chat-completion", keyUrl: "https://openrouter.ai/settings/keys", region: "global" }), withKeyHelp({ id: "groq", name: "Groq", providerKind: "openai-compatible", baseUrl: "https://api.groq.com/openai/v1", defaultModel: "openai/gpt-oss-120b", models: [ "openai/gpt-oss-120b", "openai/gpt-oss-20b", "llama-3.3-70b-versatile", "llama-3.1-8b-instant" ], stream: true, credentialType: "api-key", docUrl: "https://console.groq.com/docs/models", keyUrl: "https://console.groq.com/keys", region: "global" }), withKeyHelp({ id: "together", name: "Together AI", providerKind: "openai-compatible", baseUrl: "https://api.together.ai/v1", defaultModel: "moonshotai/Kimi-K3", models: [ "moonshotai/Kimi-K3", "zai-org/GLM-5.2", "openai/gpt-oss-120b", "deepseek-ai/DeepSeek-V4-Flash-0731", "Qwen/Qwen3.7-Plus" ], stream: true, credentialType: "api-key", docUrl: "https://docs.together.ai/docs/serverless-models", keyUrl: "https://api.together.ai/settings/api-keys", region: "global" }), withKeyHelp({ id: "mistral", name: "Mistral AI", providerKind: "openai-compatible", baseUrl: "https://api.mistral.ai/v1", defaultModel: "mistral-medium-3-5-26-04", models: [ "mistral-medium-3-5-26-04", "mistral-large-3-25-12", "mistral-small-4-0-26-03", "ministral-3-8b-25-12" ], stream: true, credentialType: "api-key", docUrl: "https://docs.mistral.ai/models/overview", keyUrl: "https://console.mistral.ai/api-keys/", region: "global" }) ], getAiProviderPreset = e => $e.find((t => t.id === e)), He = $e.map(((e, t) => ({ id: e.id, name: e.name, providerKind: e.providerKind, baseUrl: e.baseUrl, models: e.models.map((t => { var n; return { id: t, capabilities: (null == (n = e.modelCapabilities) ? void 0 : n[t]) ?? { text: true, image: false } }; })), defaultModelId: e.defaultModel, stream: e.stream, timeout: e.timeout ?? 3e4, disableThinkingParams: e.disableThinkingParams, region: e.region, order: 10 * t, recommended: false, signupUrl: e.keyUrl, docUrl: e.docUrl, keyHelp: e.keyHelp, status: "active", directConnect: true }))), Pe = [ "openai-compatible", "anthropic-messages" ], isRecord$2 = e => "object" == typeof e && null !== e, str = e => "string" == typeof e ? e : "", normalizeModel = e => { if (!isRecord$2(e) || !str(e.id)) return null; const t = isRecord$2(e.capabilities) ? e.capabilities : {}; return { id: str(e.id), label: str(e.label) || void 0, capabilities: { text: "boolean" != typeof t.text || t.text, image: "boolean" == typeof t.image && t.image } }; }, Le = [ "model", "messages", "stream" ], normalizeRequestParams = e => { if (!isRecord$2(e) || Array.isArray(e)) return; const t = Object.entries(e).filter((([e]) => !Le.includes(e))); return t.length ? Object.fromEntries(t) : void 0; }, normalizeChannel = e => { if (!isRecord$2(e)) return null; const t = str(e.id), n = str(e.baseUrl), a = Pe.includes(e.providerKind) ? e.providerKind : null, r = Array.isArray(e.models) ? e.models.map(normalizeModel).filter((e => null !== e)) : [], i = str(e.defaultModelId); if (!(t && n && a && r.length)) return null; if (!r.some((e => e.id === i))) return null; const s = "deprecated" === e.status || "hidden" === e.status ? e.status : "active"; return { id: t, name: str(e.name) || t, providerKind: a, baseUrl: n, models: r, defaultModelId: i, stream: "boolean" != typeof e.stream || e.stream, timeout: "number" == typeof e.timeout && e.timeout > 0 ? e.timeout : 3e4, region: "global" === e.region ? "global" : "domestic", order: "number" == typeof e.order ? e.order : 0, recommended: true === e.recommended, promoText: str(e.promoText) || void 0, signupUrl: str(e.signupUrl), docUrl: str(e.docUrl), keyHelp: str(e.keyHelp), status: s, directConnect: true === e.directConnect, disableThinkingParams: normalizeRequestParams(e.disableThinkingParams) }; }, Me = "ai_channel_catalog", je = "ai_channel_catalog_last_good", readState = e => { if (!isRecord$2(e) || !Array.isArray(e.channels)) return null; const t = e.channels.map(normalizeChannel).filter((e => null !== e)); return t.length ? { seq: "number" == typeof e.seq ? e.seq : 0, fetchedAt: "number" == typeof e.fetchedAt ? e.fetchedAt : 0, channels: t } : null; }, fetchCatalog = async e => { const t = readState(e.cacheGet(Me)); if (t && e.now() - t.fetchedAt < 216e5) return t; try { const t = await e.request(), n = isRecord$2(t) ? readState({ ...t, fetchedAt: e.now() }) : null; if (n) return e.cacheSet(Me, n), e.cacheSet(je, n), n; } catch {} return readState(e.cacheGet(je)) || t || { seq: 0, fetchedAt: 0, channels: He }; }, resolveChannel = (e, t, n) => e.channels.find((e => e.id === n)) || He.find((e => e.id === n)) || t.find((e => e.id === n)), Oe = { text: true, image: false }, ze = [ "openai-compatible", "anthropic-messages" ], De = [ "direct", "conservative", "preview" ], isRecord$1 = e => "object" == typeof e && null !== e, normalizeCapabilities = (e, t, n) => { const a = ((e, t) => { const n = e.toLowerCase(), a = t.toLowerCase(); return "longcat" === n && a.includes("omni") || a.includes("vision") || a.includes("vl"); })(t, n); return isRecord$1(e) ? { text: "boolean" != typeof e.text || e.text, image: "boolean" == typeof e.image ? e.image : a } : { text: true, image: a }; }, isRemovedCookieProviderValue = e => "glm-cookie" === e || "spark-cookie" === e || "cookie-glm" === e || "cookie-spark" === e || "legacy-glm" === e || "legacy-spark" === e, isAdoptionStrategy = e => "string" == typeof e && De.includes(e), normalizeCredentialValue = e => { if ("string" != typeof e) return; const t = e.trim(); return t && !isNonAnswerText(t) ? t : void 0; }, normalizeCredential$1 = e => { if (!isRecord$1(e)) return; const t = normalizeCredentialValue(e.value); return t ? { type: "api-key", value: t, updatedAt: "number" == typeof e.updatedAt ? e.updatedAt : void 0 } : void 0; }, normalizeAiConfig = e => { if (!isRecord$1(e) || "string" != typeof e.id || !e.id) return null; if (isRemovedCookieProviderValue(e.id) || isRemovedCookieProviderValue(e.providerId) || isRemovedCookieProviderValue(e.providerKind)) return null; const t = "string" == typeof e.providerId ? getAiProviderPreset(e.providerId) : getAiProviderPreset(e.id), n = (e => "string" == typeof e && ze.includes(e))(e.providerKind) ? e.providerKind : (null == t ? void 0 : t.providerKind) || "openai-compatible", a = (null == t ? void 0 : t.id) || "string" == typeof e.providerId && e.providerId || e.id, r = "string" == typeof e.model && e.model ? e.model : (null == t ? void 0 : t.defaultModel) || "", i = "number" == typeof e.timeout && Number.isFinite(e.timeout) && e.timeout > 0 ? e.timeout : 3e4; return { id: e.id, name: "string" == typeof e.name && e.name ? e.name : (null == t ? void 0 : t.name) || e.id, providerId: a, providerKind: n, baseUrl: "string" == typeof e.baseUrl && e.baseUrl ? e.baseUrl : (null == t ? void 0 : t.baseUrl) || "", model: r, enabled: "boolean" != typeof e.enabled || e.enabled, stream: "boolean" == typeof e.stream ? e.stream : (null == t ? void 0 : t.stream) ?? true, capabilities: normalizeCapabilities(e.capabilities, a, r), credential: normalizeCredential$1(e.credential), timeout: i, temperature: "number" == typeof e.temperature ? e.temperature : void 0, maxTokens: "number" == typeof e.maxTokens ? e.maxTokens : void 0 }; }, normalizeLegacyBaseUrl = e => e.trim().split(/[?#]/)[0].replace(/\/+$/, "").replace(/\/chat\/completions$/, "").replace(/\/+$/, ""), migrateLegacyAiSettings = e => { var t, n; const a = { configs: [], defaultConfigId: "", defaultVisionConfigId: "", enabledForAsk: false, adoptionStrategy: "conservative", sceneOverrides: { enabled: false } }; if (!(null == (t = e.gpt) ? void 0 : t.length)) return a; const r = {}, i = e.gpt.map(((e, t) => ({ item: e, index: t }))).filter((({item: e}) => !(e => /glm|spark|\u661f\u706b/i.test(e.name))(e))); if (!i.length) return { ...a, enabledForAsk: false }; const s = i.map((({item: e, index: t}) => { var n; const a = "deepseek", i = ((e, t) => { const n = t[e] || 0; return t[e] = n + 1, 0 === n ? e : `${e}-${n}`; })(((e, t) => `legacy-ai-${t}`)(0, t), r), s = normalizeCredentialValue(e.key); return ((e, t = {}) => { var n; const a = getAiProviderPreset(e); if (!a) throw new Error(`\u672a\u77e5 AI \u5e73\u53f0\u9884\u8bbe: ${e}`); return { id: t.id || a.id, name: t.name || a.name, providerId: a.id, providerKind: a.providerKind, baseUrl: t.baseUrl || a.baseUrl, model: t.model || a.defaultModel, enabled: t.enabled ?? true, stream: t.stream ?? a.stream, capabilities: (r = t.capabilities || (null == (n = a.modelCapabilities) ? void 0 : n[t.model || a.defaultModel]) || Oe, { text: r.text, image: r.image }), credential: t.credential, timeout: t.timeout || 3e4, temperature: t.temperature, maxTokens: t.maxTokens }; var r; })(a, { id: i, name: e.desc || e.name, baseUrl: normalizeLegacyBaseUrl(e.api) || (null == (n = getAiProviderPreset(a)) ? void 0 : n.baseUrl), model: e.model, enabled: true, credential: s ? { type: "api-key", value: s } : void 0 }); })), o = s[Math.min(Math.max(e.gptIndex || 0, 0), s.length - 1)]; return { configs: s, defaultConfigId: (null == o ? void 0 : o.id) || a.defaultConfigId, defaultVisionConfigId: "", enabledForAsk: !!e.askGpt && !!(null == (n = null == o ? void 0 : o.credential) ? void 0 : n.value), adoptionStrategy: "conservative", sceneOverrides: { enabled: false } }; }, matchChannel = (e, t) => { const n = normalizeLegacyBaseUrl(e.baseUrl || ""); return n ? t.find((e => normalizeLegacyBaseUrl(e.baseUrl) === n)) : t.find((t => t.id === e.providerId || t.id === e.id)); }, toCustomChannel = (e, t = "") => ({ id: `custom-${e.id}`, name: e.name, baseUrl: e.baseUrl || t, providerKind: e.providerKind, model: e.model }), Fe = "ai_settings", Ne = "ai_settings_backup_v1", isRecord = e => "object" == typeof e && null !== e, normalizeCredential = e => { if (!isRecord(e)) return; const t = "string" == typeof e.value ? e.value.trim() : ""; return t ? { type: "api-key", value: t, updatedAt: "number" == typeof e.updatedAt ? e.updatedAt : void 0 } : void 0; }, normalizeInstance = e => isRecord(e) && "string" == typeof e.channelId && e.channelId ? { channelId: e.channelId, credential: normalizeCredential(e.credential), enabled: false !== e.enabled, modelId: "string" == typeof e.modelId && e.modelId ? e.modelId : void 0 } : null, normalizeCustomChannel = e => isRecord(e) && "string" == typeof e.id && e.id && "string" == typeof e.baseUrl && e.baseUrl ? { id: e.id, name: "string" == typeof e.name ? e.name : e.id, baseUrl: e.baseUrl, providerKind: "anthropic-messages" === e.providerKind ? "anthropic-messages" : "openai-compatible", model: "string" == typeof e.model ? e.model : "" } : null, normalizeAiSettingsV2 = e => { if (!isRecord(e) || 2 !== e.version) return null; const t = Array.isArray(e.instances) ? e.instances.map(normalizeInstance).filter((e => null !== e)) : [], n = Array.isArray(e.customChannels) ? e.customChannels.map(normalizeCustomChannel).filter((e => null !== e)) : [], a = isRecord(e.sceneOverrides) ? e.sceneOverrides : {}; return { version: 2, instances: t, customChannels: n, defaultChannelId: "string" == typeof e.defaultChannelId ? e.defaultChannelId : "", defaultVisionChannelId: "string" == typeof e.defaultVisionChannelId ? e.defaultVisionChannelId : "", enabledForAsk: true === e.enabledForAsk, adoptionStrategy: "direct" === e.adoptionStrategy || "preview" === e.adoptionStrategy ? e.adoptionStrategy : "conservative", sceneOverrides: { enabled: true === a.enabled, search: "string" == typeof a.search ? a.search : void 0, ask: "string" == typeof a.ask ? a.ask : void 0, repair: "string" == typeof a.repair ? a.repair : void 0 }, transport: "direct" === e.transport ? "direct" : "auto" }; }, loadAiSettingsFrom = (e, t, n) => { const a = e.get(Fe), r = normalizeAiSettingsV2(a); if (r) return r; a && !e.get(Ne) && e.set(Ne, a); const i = (e => { var t, n; if (!isRecord$1(e) || !Array.isArray(e.configs)) return null; const a = e.configs.map(normalizeAiConfig).filter((e => null !== e)), r = "string" == typeof e.defaultConfigId && a.some((t => t.id === e.defaultConfigId)) ? e.defaultConfigId : (null == (t = a.find((e => e.enabled))) ? void 0 : t.id) || (null == (n = a[0]) ? void 0 : n.id) || "", i = "string" == typeof e.defaultVisionConfigId && a.some((t => { var n; return t.id === e.defaultVisionConfigId && (null == (n = t.capabilities) ? void 0 : n.image); })) ? e.defaultVisionConfigId : "", s = isRecord$1(e.sceneOverrides) ? e.sceneOverrides : {}; return { configs: a, defaultConfigId: r, defaultVisionConfigId: i, enabledForAsk: a.length > 0 && "boolean" == typeof e.enabledForAsk && e.enabledForAsk, adoptionStrategy: isAdoptionStrategy(e.adoptionStrategy) ? e.adoptionStrategy : "conservative", sceneOverrides: { enabled: "boolean" == typeof s.enabled && s.enabled, search: "string" == typeof s.search ? s.search : void 0, ask: "string" == typeof s.ask ? s.ask : void 0, repair: "string" == typeof s.repair ? s.repair : void 0 } }; })(a) ?? (() => { try { return migrateLegacyAiSettings(n()); } catch { return null; } })(), s = i ? ((e, t) => { var n, a, r, i, s, o, l; if ("object" == typeof (l = e) && null !== l && 2 === l.version) return e; const c = [], u = [], p = new Map, adoptCustom = (e, t) => { c.push({ channelId: e.id, credential: t.credential, enabled: t.enabled }); }; for (const d of e.configs) { const e = matchChannel(d, t); if (!e) { if (null == (n = d.credential) ? void 0 : n.value) { const e = toCustomChannel(d); u.push(e), adoptCustom(e, d), p.set(d.id, e.id); } continue; } const o = e.models.some((e => e.id === d.model)) ? d.model : void 0, l = c.find((t => t.channelId === e.id)); if (l) if ((null == (a = l.credential) ? void 0 : a.value) || !(null == (r = d.credential) ? void 0 : r.value)) { if ((null == (i = l.credential) ? void 0 : i.value) && (null == (s = d.credential) ? void 0 : s.value) && l.credential.value !== d.credential.value) { const t = toCustomChannel(d, e.baseUrl); u.push(t), adoptCustom(t, d), p.set(d.id, t.id); } } else p.set(d.id, e.id), l.credential = d.credential, l.enabled = d.enabled, l.modelId = o; else p.set(d.id, e.id), c.push({ channelId: e.id, credential: d.credential, enabled: d.enabled, modelId: o }); } return { version: 2, instances: c, customChannels: u, defaultChannelId: p.get(e.defaultConfigId) || (null == (o = c[0]) ? void 0 : o.channelId) || "", defaultVisionChannelId: p.get(e.defaultVisionConfigId) || "", enabledForAsk: e.enabledForAsk, adoptionStrategy: e.adoptionStrategy, sceneOverrides: e.sceneOverrides, transport: "auto" }; })(i, t) : { version: 2, instances: [], customChannels: [], defaultChannelId: "", defaultVisionChannelId: "", enabledForAsk: false, adoptionStrategy: "conservative", sceneOverrides: { enabled: false }, transport: "auto" }; return e.set(Fe, s), s; }, asChannel = e => (e => !("models" in e))(e) ? { id: e.id, name: e.name, providerKind: e.providerKind, baseUrl: e.baseUrl, models: [ { id: e.model, capabilities: { text: true, image: false } } ], defaultModelId: e.model, stream: true, timeout: 3e4, region: "domestic", order: 0, recommended: false, signupUrl: "", docUrl: "", keyHelp: "", status: "active", directConnect: true } : e, resolveModel = (e, t) => e.models.find((e => e.id === t.modelId)) ?? e.models.find((t => t.id === e.defaultModelId)) ?? e.models[0], synthesizeAiConfig = (e, t) => { const n = resolveModel(e, t); return { id: e.id, name: e.name, providerId: e.id, providerKind: e.providerKind, baseUrl: e.baseUrl, model: (null == n ? void 0 : n.id) ?? e.defaultModelId, enabled: t.enabled, stream: e.stream, capabilities: (null == n ? void 0 : n.capabilities) ?? { text: true, image: false }, credential: t.credential, timeout: e.timeout, disableThinkingParams: e.disableThinkingParams }; }, resolveAiTarget = (e, t, n, a = "text") => { var r; const build = n => { var r; if (!n.enabled || !(null == (r = n.credential) ? void 0 : r.value)) return; const i = resolveChannel(t, e.customChannels, n.channelId); if (!i) return; const s = asChannel(i); return ((e, t) => e.models.some((e => e.capabilities[t])))(s, a) ? { channel: s, instance: n, config: synthesizeAiConfig(s, n) } : void 0; }, pick = t => { const n = e.instances.find((e => e.channelId === t)); return n ? build(n) : void 0; }, i = (null == (r = e.sceneOverrides) ? void 0 : r.enabled) ? e.sceneOverrides[n] : void 0; if ("image" === a) { const t = e.defaultVisionChannelId && pick(e.defaultVisionChannelId); if (t) return t; } const s = i && pick(i); if (s) return s; const o = pick(e.defaultChannelId); if (o) return o; for (const l of e.instances) { const e = build(l); if (e) return e; } }, channelTags = e => { const t = []; return e.recommended && t.push({ label: "\u63a8\u8350", cls: "aah-tag-primary" }), e.promoText && t.push({ label: "\u6709\u514d\u8d39\u989d\u5ea6", cls: "aah-tag-success" }), "global" === e.region ? t.push({ label: "\u9700\u81ea\u5907\u4ee3\u7406", cls: "aah-tag-warning" }) : canDirectConnect(e) ? t.push({ label: "\u56fd\u5185\u76f4\u8fde", cls: "" }) : t.push({ label: "\u9700\u767b\u5f55\u4e2d\u8f6c", cls: "aah-tag-warning" }), hasVisionModel(e) && t.push({ label: "\u53ef\u9009\u89c6\u89c9\u6a21\u578b", cls: "" }), t; }, hasVisionModel = e => e.models.some((e => e.capabilities.image)), imageReadiness = (e, t) => { const n = resolveModel(e, t), a = (null == n ? void 0 : n.id) ?? e.defaultModelId; if (null == n ? void 0 : n.capabilities.image) return { state: "ready", modelId: a }; const r = e.models.find((e => e.capabilities.image)); return r ? { state: "switchable", modelId: a, suggestModelId: r.id } : { state: "unsupported", modelId: a }; }, Re = /]*\bsrc\s*=\s*["']([^"']+)["'][^>]*>/gi, Be = /(?:spacer|blank|transparent)\.(?:gif|png|webp)(?:[?#].*)?$/i, Ge = [ "data-src", "data-original", "data-lazy-src", "data-echo" ], resolveImageSrc = (e, t) => { if (!e) return ""; const n = e.trim().replace(/&/g, "&"); if (/^(?:data:|blob:)/i.test(n)) return n; const a = (e => { var t; return e || (null == (t = globalThis.location) ? void 0 : t.href) || ""; })(t); if (!a) return n; try { return new URL(n, a).href; } catch { return n; } }, shouldUseImageSrc = e => !!e && (!Be.test(e) && (!!/^(?:https?:|blob:)/i.test(e) || (/^data:/i.test(e) ? /^data:image\//i.test(e) : !/^[a-z][a-z0-9+.-]*:/i.test(e)))), getAttr = (e, t) => { const n = "function" == typeof (null == e ? void 0 : e.getAttribute) ? e.getAttribute(t) : null; return "string" == typeof n ? n : ""; }, pickElementSrc = e => { const t = (null == e ? void 0 : e.currentSrc) || (null == e ? void 0 : e.src) || getAttr(e, "src"); if (Number(null == e ? void 0 : e.naturalWidth) > 0) return t; for (const r of Ge) { const t = getAttr(e, r); if (t) return t; } return (n = getAttr(e, "srcset")) && (null == (a = n.split(",").map((e => e.trim())).filter(Boolean).map((e => { const [t, n = ""] = e.split(/\s+/); return { url: t, weight: Number(n.replace(/[wx]$/i, "")) || 0 }; })).sort(((e, t) => t.weight - e.weight))[0]) ? void 0 : a.url) || "" || t; var n, a; }, extractRefsFromString = (e, t) => { const n = []; for (const a of e.matchAll(Re)) { const e = resolveImageSrc(a[1], t); shouldUseImageSrc(e) && n.push({ src: e }); } return n; }, collectRefs = (e, t) => { return e ? "string" == typeof e ? extractRefsFromString(e, t) : (n = e) && "object" == typeof n && "function" == typeof n.querySelectorAll ? Array.from(e.querySelectorAll("img") || []).filter((e => !(e => { const t = Number(null == e ? void 0 : e.naturalWidth), n = Number(null == e ? void 0 : e.naturalHeight); return t > 0 && n > 0 && t < 32 && n < 32; })(e))).map((e => ({ src: resolveImageSrc(pickElementSrc(e), t), el: e }))).filter((e => shouldUseImageSrc(e.src))) : "string" == typeof e.outerHTML ? extractRefsFromString(e.outerHTML, t) : "string" == typeof e.innerHTML ? extractRefsFromString(e.innerHTML, t) : [] : []; var n; }, uniqueRefs = e => { const t = new Map; for (const n of e) { const e = t.get(n.src); (!e || !e.el && n.el) && t.set(n.src, n); } return Array.from(t.values()); }, extractQuestionImageRefs = (e, t = {}) => uniqueRefs([ ...collectRefs(e.question, t.baseUrl), ...collectRefs(e.html, t.baseUrl), ...Array.isArray(e.options) ? e.options.flatMap((e => collectRefs(e, t.baseUrl))) : [] ]), hasQuestionImages = (e, t = "") => { return (e => extractQuestionImageRefs(e).map((e => e.src)))(e).length > 0 || (n = t, uniqueRefs(collectRefs(n)).map((e => e.src))).length > 0; var n; }, toBytes = e => e instanceof ArrayBuffer ? new Uint8Array(e) : ArrayBuffer.isView(e) ? new Uint8Array(e.buffer, e.byteOffset, e.byteLength) : void 0, bytesToBase64 = e => { const t = toBytes(e); if (!t) throw createAiError("AI_RESPONSE_PARSE_FAILED"); if ("undefined" != typeof Buffer) return Buffer.from(t).toString("base64"); let n = ""; for (let a = 0; a < t.length; a += 8192) n += String.fromCharCode(...t.subarray(a, a + 8192)); return btoa(n); }, buildImagePart = (e, t, n, a = {}) => { const r = toBytes(t); if (!r || 0 === r.byteLength) throw new Error("\u56fe\u7247\u54cd\u5e94\u4f53\u4e3a\u7a7a"); const i = a.maxBytes || 4194304; if (r.byteLength > i) throw new Error(`\u56fe\u7247\u8fc7\u5927\uff08${Math.round(r.byteLength / 1024)}KB\uff0c\u4e0a\u9650 ${Math.round(i / 1024)}KB\uff09`); const s = (n || "").split(";")[0].trim().toLowerCase(); if (s && !s.startsWith("image/")) throw new Error(`\u54cd\u5e94\u4e0d\u662f\u56fe\u7247\uff08${s}\uff09\uff0c\u53ef\u80fd\u662f\u767b\u5f55\u6001\u5931\u6548\u8df3\u8f6c\u4e86\u767b\u5f55\u9875`); return { type: "image", source: "base64", data: bytesToBase64(r), mimeType: s || "image/png", url: e }; }, decodeDataUrl = e => { const t = e.match(/^data:([^;,]+);base64,(.+)$/i); if (!t) throw createAiError("AI_RESPONSE_PARSE_FAILED"); return { type: "image", source: "base64", data: t[2], mimeType: t[1], url: e }; }, defaultCreateCanvas = () => { if ("undefined" == typeof document) throw new Error("\u5f53\u524d\u73af\u5883\u6ca1\u6709 document\uff0c\u65e0\u6cd5\u4f7f\u7528\u753b\u5e03"); return document.createElement("canvas"); }, loadImagePartFromElement = async (e, t = {}) => { const n = e.el, a = Number(null == n ? void 0 : n.naturalWidth) || 0, r = Number(null == n ? void 0 : n.naturalHeight) || 0; if (!(a > 0 && r > 0)) throw new Error("\u56fe\u7247\u5c1a\u672a\u52a0\u8f7d\u5b8c\u6210"); const i = ((e, t, n = 1568) => { const a = Math.max(e, t); if (!(a > n)) return { width: e, height: t }; const r = n / a; return { width: Math.max(1, Math.round(e * r)), height: Math.max(1, Math.round(t * r)) }; })(a, r, t.maxEdge || 1568), s = (t.createCanvas || defaultCreateCanvas)(); s.width = i.width, s.height = i.height; const o = s.getContext("2d"); if (!o) throw new Error("\u753b\u5e03\u4e0a\u4e0b\u6587\u4e0d\u53ef\u7528"); o.fillStyle = "#ffffff", o.fillRect(0, 0, i.width, i.height), o.drawImage(n, 0, 0, i.width, i.height); const l = s.toDataURL(t.mimeType || "image/jpeg", t.quality ?? .85); if (!/^data:image\//i.test(l)) throw new Error("\u753b\u5e03\u5bfc\u51fa\u5931\u8d25"); return { ...decodeDataUrl(l), url: e.src }; }, loadImagePartFromFetch = async (e, t = {}) => { const n = t.fetchImpl || ("function" == typeof fetch ? fetch : void 0); if (!n) throw new Error("\u5f53\u524d\u73af\u5883\u4e0d\u652f\u6301 fetch"); return (async (e, t) => { const n = "function" == typeof AbortController ? new AbortController : void 0; let a; const r = new Promise(((e, r) => { a = setTimeout((() => { null == n || n.abort(), r(new Error(`\u53d6\u56fe\u8d85\u65f6\uff08${t}ms\uff09`)); }), t); })); try { return await Promise.race([ e(null == n ? void 0 : n.signal), r ]); } finally { clearTimeout(a); } })((async a => { var r, i; const s = await n(e, { credentials: "same-origin", signal: a }); if (!(null == s ? void 0 : s.ok)) throw new Error(`\u56fe\u7247\u8bf7\u6c42\u5931\u8d25 HTTP ${(null == s ? void 0 : s.status) ?? "\u672a\u77e5"}`); const o = await s.arrayBuffer(); return buildImagePart(e, o, (null == (i = null == (r = s.headers) ? void 0 : r.get) ? void 0 : i.call(r, "content-type")) || "", { maxBytes: t.maxBytes }); }), t.timeout || 2e4); }, loadQuestionImagePart = async (e, t = {}) => { if (/^data:/i.test(e.src)) return decodeDataUrl(e.src); const n = t.fromElement || (e => loadImagePartFromElement(e, t)), a = t.fromFetch || (e => loadImagePartFromFetch(e, t)), r = t.fromGm || (e => (async (e, t = {}) => { const n = t.transport || createAiTransportRequest, a = await n({ method: "GET", url: e, responseType: "arraybuffer", timeout: t.timeout || 2e4 }).promise; return buildImagePart(e, a.response, (e => { var t; const n = null == e ? void 0 : e.match(/content-type:\s*([^;\r\n]+)/i); return null == (t = null == n ? void 0 : n[1]) ? void 0 : t.trim(); })(a.responseHeaders), { maxBytes: t.maxBytes }); })(e, t)), i = []; e.el && i.push([ "canvas", () => n(e) ]), i.push([ "\u540c\u6e90\u8bf7\u6c42", () => a(e.src) ]), i.push([ "GM \u8bf7\u6c42", () => r(e.src) ]); const s = []; for (const [l, c] of i) try { return await c(); } catch (o) { s.push(`${l}\uff1a${(null == o ? void 0 : o.message) || o}`); } throw new Error(s.length ? s.join("\uff1b") : "\u6ca1\u6709\u53ef\u7528\u7684\u53d6\u56fe\u901a\u9053"); }, base64Bytes = e => { const t = e.endsWith("==") ? 2 : e.endsWith("=") ? 1 : 0; return Math.max(0, 3 * Math.floor(e.length / 4) - t); }, resolveQuestionImages = async (e, t = {}) => { const n = extractQuestionImageRefs(e, t); if (!n.length) return { parts: [], failures: [] }; const a = t.maxImages || 6, r = n.slice(0, a), i = n.slice(a).map((e => ({ src: e.src, reason: `\u8d85\u51fa\u5355\u9898\u56fe\u7247\u4e0a\u9650\uff08${a} \u5f20\uff09` }))), s = t.loadPart || (e => loadQuestionImagePart(e, t)), o = await (async (e, t, n) => { const a = new Array(e.length); let r = 0; const i = Array.from({ length: Math.max(1, Math.min(t, e.length)) }, (async () => { for (;r < e.length; ) { const t = r; r += 1, a[t] = await n(e[t]); } })); return await Promise.all(i), a; })(r, t.concurrency || 2, (async e => { try { return { ref: e, part: await s(e) }; } catch (t) { return { ref: e, reason: (null == t ? void 0 : t.message) || "\u53d6\u56fe\u5931\u8d25" }; } })), l = [], c = t.maxTotalBytes || 12582912; let u = 0; for (const p of o) { if (!p.part) { i.push({ src: p.ref.src, reason: p.reason || "\u53d6\u56fe\u5931\u8d25" }); continue; } const e = base64Bytes(p.part.data); u + e > c ? i.push({ src: p.ref.src, reason: `\u8d85\u51fa\u5355\u9898\u56fe\u7247\u603b\u91cf\u4e0a\u9650\uff08${Math.round(c / 1024)}KB\uff09` }) : (u += e, l.push(p.part)); } return { parts: l, failures: i }; }, Ke = { "\u5355\u9009\u9898": "0", "\u591a\u9009\u9898": "1", "\u586b\u7a7a\u9898": "2", "\u5224\u65ad\u9898": "3", "\u7b80\u7b54\u9898": "4", "\u95ee\u7b54\u9898": "4", "\u540d\u8bcd\u89e3\u91ca": "5", "\u8bba\u8ff0\u9898": "6", "\u8ba1\u7b97\u9898": "7", "\u5206\u5f55\u9898": "9", "\u8d44\u6599\u9898": "10", "\u8fde\u7ebf\u9898": "11", "\u5339\u914d\u9898": "11", "\u6392\u5e8f\u9898": "13", "\u5b8c\u578b\u586b\u7a7a": "14", "\u5b8c\u5f62\u586b\u7a7a\u9898": "14", "\u9605\u8bfb\u7406\u89e3": "15", "\u7a0b\u5e8f\u9898": "17", "\u53e3\u8bed\u9898": "18", "\u542c\u529b\u9898": "19", "\u5171\u7528\u9009\u9879\u9898": "20", "\u6d4b\u8bc4\u9898": "21", "\u949f\u8868\u9898": "23", "\u9009\u8bcd\u586b\u7a7a": "24", "\u9009\u505a\u9898": "25", "\u5176\u5b83": "8" }, Ve = randomString(9) + "_", We = te; function getAppStore() { return ie[Ve + "app"]; } function getAskStore() { return ie[Ve + "ask"]; } function isParentChecked(e) { return e.parent().parent().hasClass("is-checked"); } function qc(e) { O(e).find(".answerBg, .textDIV, .eidtDiv").each((function() { (O(this).find(".check_answer").length || O(this).find(".check_answer_dx").length) && O(this).click(); })), O(e).find(".answerBg, .textDIV, .eidtDiv").find("textarea").each((function() { ie.UE.getEditor(O(this).attr("name")).ready((function() { this.setContent(""); })); })), O(e).find(":radio, :checkbox").prop("checked", false), O(e).find("textarea").each((function() { ie.UE.getEditor(O(this).attr("name")).ready((function() { this.setContent(""); })); })); } function qc1(e) { O(e).find(".before-after,.before-after-checkbox, .textDIV, .eidtDiv").each((function() { (O(this).find(".check_answer").length || O(this).find(".check_answer_dx").length) && O(this).click(); })), O(e).find(".before-after, .textDIV, .eidtDiv").find("textarea").each((function() { ie.UE.getEditor(O(this).attr("name")).ready((function() { this.setContent(""); })); })), O(e).find(":radio, :checkbox").prop("checked", false), O(e).find("textarea").each((function() { ie.UE.getEditor(O(this).attr("name")).ready((function() { this.setContent(""); })); })); } oe = getAppStore; const Qe = [ { type: "hook", name: "\u4e91\u5e55\u5b66\u82d1hook", match: location.host.includes("w-ling.cn"), main: e => { observeVuePageChange(O("#app")[0], (() => O("#app")[0].__vue__.$route.path), { beforeChange: async e => { "homework-detail-container" === e && await waitUntil((function() { return 0 !== O(".selectDan").length; })); } }); } }, { type: "save", name: "\u4e91\u5e55\u5b66\u82d1\u6536\u5f55", match: () => location.host.includes("w-ling.cn") && location.href.includes("practiceRecord"), question: { html: ".selectDan >div >div", question: ".title", options: ".selectItem label .tagbq", type: ".question-box .tag", workType: "yunmuxueyuan", pageType: "yunmuxueyuan" }, init: async () => { await waitUntil((function() { return isExist(".selectDan >div >div"); })); }, answerHook: e => { const t = O(e.html).parent().find("h3").text().split("\u3001")[1]; e.question = e.question.replace(/^\d+\u3001/, ""), e.question = e.question.replace(/\(\d+\u5206\)$/, ""); let n = O(e.html).find(".anaylize > span:eq(0)").text().replace("\u4f5c\u7b54\u6b63\u786e\uff1a", ""); switch ("" === n && (n = O(e.html).find(".falsanaly > span:eq(1)").text().replace("\u6b63\u786e\u7b54\u6848\uff1a", "")), t) { case "\u5355\u9009\u9898": case "\u591a\u9009\u9898": let t = n.split(""); if (e.answer = t.map((t => e.options[t.charCodeAt(0) - 65])), 0 === e.answer.length) return; e.answer.length > 1 ? e.type = "1" : e.type = "0"; break; case "\u5224\u65ad\u9898": e.type = "3", "T" == n && (e.answer = [ "\u6b63\u786e" ]), "F" == n && (e.answer = [ "\u9519\u8bef" ]); break; case "\u586b\u7a7a\u9898": e.answer = O(e.html).find(".riganswer > span").first().nextAll("span").map(((e, t) => removeHtml(O(t).text()))).get(), e.type = "2"; } return e; } }, { type: "ask", name: "\u4e91\u5e55\u5b66\u82d1", tips: "", match: () => location.host.includes("w-ling.cn") && (location.href.includes("practicePaper") || location.href.includes("examIndex")), types: [ "0", "1", "3" ], question: { html: ".selectDan >div >div", question: ".title", options: ".selectItem label .tagbq", type: ".question-box .tag", workType: "yunmuxueyuan", pageType: "yunmuxueyuan" }, init: async () => { await waitUntil((function() { return 0 !== O(".selectDan >div >div").length; })); }, ischecked: isParentChecked, questionHook: e => { e.question = e.question.replace(/^\d+\u3001/, ""), e.question = e.question.replace(/\(\d+\u5206\)$/, ""); switch (O(e.html).parent().find("h4").text().split("\u3001")[1]) { case "\u5355\u9009\u9898": e.type = "0"; break; case "\u591a\u9009\u9898": e.type = "1"; break; case "\u5224\u65ad\u9898": e.type = "3", e.$options = O(e.html).find(".selectItem label"), e.options = e.$options.map(((e, t) => removeHtml(O(t).text()))).get(), e.$options; break; case "\u586b\u7a7a\u9898": e.type = "2"; } return e; }, setAnswer: e => { switch (e.type) { case "3": break; case "2": return O(e.html).find(".tiankong input").each(((t, n) => { let a = O(n).parent()[0].__vue__; O(n).val(e.answer[t]); const r = new Event("input"); n.dispatchEvent(r), a.$emit("change", e.answer[t]); })), false; } return true; } } ], Je = "\u7b54\u9898\u5df2\u53d6\u6d88", assertFillShouldContinue = e => { if ((null == e ? void 0 : e.shouldContinue) && !e.shouldContinue()) throw new Error(Je); }, fillPlanToLegacyAnswerData = e => "choice" === e.kind ? [ "xx", e.indexes ] : "judge" === e.kind ? [ "pd", e.value ] : "blank" === e.kind ? [ "jd", e.values ] : "link" === e.kind ? [ "lx", e.value ] : "reading" === e.kind ? [ "ydlj", e.subPlans.map((e => "choice" === e.kind ? e.indexes : "judge" === e.kind ? [ e.value ] : "blank" === e.kind ? e.values : [])) ] : [ "", [] ], rawFormForLegacyMatch = e => { if (!e || "object" != typeof e) return {}; const t = { ...e }; var n; return !("match" in t) || (n = t.match, Array.isArray(n) && n.every((e => "number" == typeof e || Array.isArray(e)))) || delete t.match, t; }, createLegacyMatchResult = e => { if (!e.haveAnswer || !e.source || !e.fillPlan) return { res: e.displayAnswers.map((e => e.raw || e)), haveAnswer: false }; const [, t] = fillPlanToLegacyAnswerData(e.fillPlan); return { res: e.displayAnswers.map((e => e.raw || e)), form: { ...rawFormForLegacyMatch(e.source.raw), form: e.source.source, answer: e.source.answer, ...void 0 !== e.source.duration ? { duration: e.source.duration } : {}, ...void 0 !== e.source.msg ? { msg: e.source.msg } : {}, ...void 0 !== e.source.needLogin ? { needLogin: e.source.needLogin } : {}, ...(n = e.fillPlan, "choice" === n.kind || "reading" === n.kind ? { match: t } : {}) }, haveAnswer: true }; var n; }, applyFillPlan = async (e, t, n, a, r) => { const [i, s] = fillPlanToLegacyAnswerData(e); if (!i) return { success: false, reason: "unsupported" === e.kind ? e.reason : "\u5f53\u524d\u9898\u578b\u6682\u4e0d\u652f\u6301\u586b\u5145" }; const o = (null == r ? void 0 : r.shouldContinue) ? { shouldContinue: () => (assertFillShouldContinue(r), true) } : void 0; try { return assertFillShouldContinue(r), await a(i, s, t, n, o), assertFillShouldContinue(r), { success: !0 }; } catch (l) { if ((e => e instanceof Error && e.message === Je)(l)) return { success: false, reason: Je }; throw l; } }, cloneOptions = e => Array.isArray(e) ? e.map((e => e && "object" == typeof e ? { ...e } : e)) : [], normalizeFlatOptions = (e, t = true) => { const n = t ? cleanQuestionTextWithImageHtml : cleanQuestionText, a = e.map((e => n(e))); return removeOptionPrefixes(a).map((e => e.trim())).filter(Boolean); }, normalizeBaseQuestion = e => { const t = false !== e.preserveImageHtml, n = t ? cleanQuestionTextWithImageHtml : cleanQuestionText, a = { ...e, question: cleanQuestionTitle(n(e.question, "2" == e.type), "2" == e.type), options: cloneOptions(e.options) }; return "15" == a.type ? (a.options = ((e, t = true) => { const n = t ? cleanQuestionTextWithImageHtml : cleanQuestionText; return e.map((e => e && "object" == typeof e ? { ...e, question: cleanQuestionTitle(n(e.question)), options: normalizeFlatOptions(cloneOptions(e.options), t) } : e)); })(a.options, t), a) : "11" == a.type ? (a.options = (r = e.options, Array.isArray(r) ? r.map((e => Array.isArray(e) ? e.slice() : e)) : r), a) : (a.options = normalizeFlatOptions(a.options, t), a); var r; }, normalizeQuestionForAsk = e => { const t = normalizeBaseQuestion(e); return "3" == t.type && (isJudgeChoiceOptions(t.options) && (t.judgeOptions = t.options), t.options = []), t; }, normalizeQuestionForSave = e => { const t = normalizeBaseQuestion(e); if ("11" != t.type && "15" != t.type && ((e, t) => { if (!Array.isArray(e.options) || 0 === e.options.length) return; if (!Array.isArray(t.options) || t.options.some((e => "string" != typeof e))) return; const n = false !== e.preserveImageHtml ? cleanQuestionTextWithImageHtml : cleanQuestionText, a = e.options.map((e => n(e))), r = removeOptionPrefixes(a).map((e => e.trim())), i = new Map; a.forEach(((e, t) => { const n = normalizeComparableText(e); n && r[t] && !i.has(n) && i.set(n, r[t]); })); const remap = e => "string" != typeof e ? e : i.get(normalizeComparableText(e)) ?? e; "string" == typeof t.answer ? t.answer = remap(t.answer) : Array.isArray(t.answer) && (t.answer = t.answer.map(remap)); })(e, t), "3" == t.type || "0" == t.type && isJudgeChoiceOptions(t.options)) { const remap = e => resolveJudgeAnswer(e, t.options) ?? e; t.answer = Array.isArray(t.answer) ? t.answer.map(remap) : remap(t.answer); } return null !== t.answer && void 0 !== t.answer && "object" != typeof t.answer && (t.answer = [ String(t.answer) ]), t; }, normalizeQuestionForHash = e => normalizeBaseQuestion(e), compatibleType = e => { if ("string" != typeof e.question) return ""; const t = String(e.type); return "0" === t && isJudgeChoiceOptions(normalizeQuestionForHash(e).options) ? "3" : "4" === t && countBlankPlaceholders(e.question) > 0 ? "2" : t; }, cachedQuestionAnswer = e => { if ("3" !== compatibleType(e)) return e.answer; const t = normalizeQuestionForHash(e).options; return (Array.isArray(e.answer) ? e.answer : [ e.answer ]).map((e => resolveJudgeAnswer(e, t) ?? e)); }, findCompatibleCachedQuestion = (e, t) => { const n = compatibleType(e); if ("2" !== n && "3" !== n) return; const comparable = e => { const t = "2" === n ? (e => e.replace(Ce, "\uff08\uff09"))(e.question) : e.question; return normalizeQuestionForHash({ ...e, question: t }).question.replace(/\s/g, ""); }, a = comparable(e); return a ? t().find((e => compatibleType(e) === n && comparable(e) === a)) : void 0; }, isLoggedInUserCache = e => Boolean(e && e.user && e.api_key), isPlainObject = e => "object" == typeof e && null !== e && !Array.isArray(e), cloneValue = e => { if (Array.isArray(e)) return e.map((e => cloneValue(e))); if (!isPlainObject(e)) return e; const t = {}; return Object.entries(e).forEach((([e, n]) => { t[e] = cloneValue(n); })), t; }, cloneWithLegacySignatureArraySort = (e, t = true, n = true) => { if (Array.isArray(e)) return t && e.every((e => "object" != typeof e)) ? [ ...e ].sort() : e.map((e => cloneValue(e))); if (!isPlainObject(e)) return e; const a = {}; return Object.entries(e).forEach((([e, r]) => { a[e] = cloneWithLegacySignatureArraySort(r, t && !(n && "html" === e), false); })), a; }; const Ze = new Set([ "authorization", "api_key", "x-anonymous-id", "x-device-fp", "anonymous_id", "device_fingerprint", "x-ai-credential" ]), redactValue = (e, t) => Ze.has(e.toLowerCase()) ? "***" : "string" == typeof t && /bearer\s+/i.test(t) ? "Bearer ***" : t, redactRequestLog = e => { if (Array.isArray(e)) return e.map((e => redactRequestLog(e))); if (!e || "object" != typeof e) return e; const t = {}; return Object.entries(e).forEach((([e, n]) => { if ("string" == typeof n && (n.trim().startsWith("{") || n.trim().startsWith("["))) try { return void (t[e] = JSON.stringify(redactRequestLog(JSON.parse(n)))); } catch { return void (t[e] = redactValue(e, n)); } t[e] = redactValue(e, redactRequestLog(n)); })), t; }, Ye = "https://zhiku.ahzsksw.cn", apiUrl = e => `${Ye}/api/client/v2/${e}`; // Public protocol boundary: the platform engine never defines wire field names. function toWorkspaceEntry(item) { return {kind: String(item.type ?? '8'), stem: item.question ?? '', choices: item.options ?? [], solutions: item.answer ?? [], explanation: item.analysis ?? '', origin: item.source ?? '', labels: item.tags ?? ''}; } function fromWorkspaceEntry(item) { return {id: item.id, type: String(item.kind), question: item.stem, options: item.choices, answer: item.solutions, analysis: item.explanation, source: item.origin, tags: item.labels}; } function engineProfile(profile) { return {id: profile.id, username: profile.displayName, nickname: profile.displayName, score: profile.points ?? profile.quota.remaining ?? 0, points: profile.points ?? 0, contributions: profile.contributions || 0, exchangeable: profile.exchangeable || 0, exchange: profile.exchange || {}, recharge: profile.recharge || {}, sources: profile.sources || {}, daily_limit: profile.quota.daily}; } function workspaceTransportError(operation, kind, status = 0) { const names = {profile: '账户信息', 'points/history': '积分明细', 'space-access': '个人空间登录', sessions: '账号登录', accounts: '注册账号', 'contributions/exchange': '贡献兑换', bulletin: '公告'}; const name = names[operation] || (operation.startsWith('imports') ? '导入记录' : operation.startsWith('captures') ? '题目同步' : '知库请求'); const reason = kind === 'timeout' ? '服务响应超时,请稍后重试' : kind === 'abort' ? '请求已取消,可重新操作' : kind === 'network' ? '网络连接失败,请检查网络或脚本连接权限' : status >= 400 ? `服务返回 HTTP ${status},请稍后重试` : '服务未返回有效数据,请稍后重试'; const error = new Error(`${name}加载失败:${reason}`); error.code = kind; error.status = status; return error; } function workspaceHttp(request, operation) { // Retry a transient read once. Writes must retain their own idempotency rules. return new Promise((resolve, reject) => { const send = attempt => { let finished = false; const fail = error => { if (finished) return; finished = true; if (request.method === 'GET' && attempt === 0 && ['network', 'timeout', 'unavailable'].includes(error.code)) setTimeout(() => send(1), 400); else reject(error); }; try { re({...request, onload: response => { if (finished) return; if (!response.status) { fail(workspaceTransportError(operation, 'network')); return; } if ([502, 503, 504].includes(response.status)) { // Preserve an actionable API error after the read retry, or on a write. let apiError = false; try { const wire = JSON.parse(response.responseText); apiError = wire?.ok === false && typeof wire.error?.message === 'string'; } catch {} if (!apiError || request.method === 'GET' && attempt === 0) { fail(workspaceTransportError(operation, 'unavailable', response.status)); return; } } finished = true; resolve(response); }, ontimeout: () => fail(workspaceTransportError(operation, 'timeout')), onerror: () => fail(workspaceTransportError(operation, 'network')), onabort: () => fail(workspaceTransportError(operation, 'abort'))}); } catch { fail(workspaceTransportError(operation, 'network')); } }; send(0); }); } function parseWorkspaceResponse(response, operation) { try { return JSON.parse(response.responseText); } catch { throw workspaceTransportError(operation, 'response', response.status); } } function workspaceRequest(operation, payload, timeout = 65000) { const user = Cache.get('user', {}) || {}; return workspaceHttp({url: apiUrl(operation), method: payload === undefined ? 'GET' : 'POST', timeout, headers: {'Content-Type': 'application/json', ...(user.api_key ? {Authorization: `Bearer ${user.api_key}`} : {})}, data: payload === undefined ? undefined : JSON.stringify(payload)}, operation).then(response => { const wire = parseWorkspaceResponse(response, operation); if (typeof wire?.ok !== 'boolean') throw workspaceTransportError(operation, 'response', response.status); if (response.status === 401 && user.api_key && Cache.get('user', {})?.api_key === user.api_key) window.dispatchEvent(new CustomEvent('zk-session-expired')); if (!wire?.ok) throw new Error(wire?.error?.message || '服务请求失败'); if (response.status < 200 || response.status >= 300) throw workspaceTransportError(operation, 'response', response.status); return wire.result; }); } function requestApi(url, method, data = {}, headers = {}, timeout = 8000) { const operation = new URL(url).pathname.split('/api/client/v2/')[1]; const user = Cache.get('user', {}) || {}; let payload = data || {}; if (operation === 'sessions') payload = data.login_type === 'apikey' ? {accessToken: data.api_key} : {account: data.username, secret: data.password}; if (operation === 'accounts') payload = {account: data.username, secret: data.password, email: data.email}; if (operation === 'answers/resolve') payload = {...toWorkspaceEntry(data), context: {platform: data.workType || data.pageType || ''}}; if (operation === 'catalog/search') payload = {text: data.question}; if (operation === 'captures' || operation === 'captures/platform') payload = {entries: (data.questionList || []).map(toWorkspaceEntry), context: {platform: data.pageType || ''}}; if (operation === 'captures/course') payload = {course: {key: data.hash, title: data.name, platform: data.platform, sections: (data.chapter || []).map(section => ({key: section.hash, title: section.name, entries: (section.question || []).map(toWorkspaceEntry)}))}}; if (operation === 'session') method = 'DELETE'; return (async () => { const start = Date.now(); const requestHeaders = {'Content-Type': 'application/json', ...headers}; if (isLoggedInUserCache(user)) requestHeaders.Authorization = `Bearer ${user.api_key}`; const response = await workspaceHttp({url, method, headers: requestHeaders, timeout, data: ['GET', 'DELETE'].includes(method) ? undefined : JSON.stringify(payload)}, operation); const wire = parseWorkspaceResponse(response, operation); if (response.status === 401 && user.api_key && Cache.get('user', {})?.api_key === user.api_key && !['sessions', 'accounts', 'bulletin'].includes(operation)) window.dispatchEvent(new CustomEvent('zk-session-expired')); if (!wire || typeof wire.ok !== 'boolean' || wire.ok && (response.status < 200 || response.status >= 300)) throw workspaceTransportError(operation, 'response', response.status); const value = wire.result || {}; let translated = value; if ((operation === 'sessions' || operation === 'accounts') && wire.ok) translated = {api_key: value.accessToken, user: engineProfile(value.profile)}; if (operation === 'profile' && wire.ok) translated = {user: engineProfile(value)}; if (operation === 'credentials/renew' && wire.ok) translated = {api_key: value.accessToken}; if (operation === 'bulletin' && wire.ok) translated = {notice: String(value.text || '')}; if (operation === 'answers/resolve' && wire.ok) translated = {answer: value.solutions, analysis: value.explanation, source: value.origin}; if (operation === 'catalog/search' && wire.ok) translated = (value.entries || []).map(fromWorkspaceEntry); if (operation.startsWith('captures') && wire.ok) translated = {published: value.published || 0, pending: value.queued, skipped: value.duplicates, errors: value.issues}; const message = wire.ok ? (operation === 'captures' ? '已同步' : operation.startsWith('captures/') ? '采集完成' : '请求完成') : (wire.error?.message || '服务请求失败'); // Only the retained engine consumes this internal compatibility object. return [{...response, responseText: JSON.stringify({code: wire.ok ? 200 : response.status || 500, message, data: translated})}, Date.now() - start]; })(); } function request(e, t, n = void 0, a = void 0, r = 5e3) { "GET" === t && n && (e += `?${new URLSearchParams(n).toString()}`), "POST" === t && (a = { ...a }); const i = { "User-Agent": ie.navigator.userAgent, "Content-Type": "application/json", referer: location.href, ...a }; return new Promise(((a, s) => { const o = Date.now(); re({ method: t, url: e, headers: i, data: "GET" !== t ? JSON.stringify(n) : void 0, timeout: r, onload: function(e) { const t = Date.now(); a([ e, t - o ]); }, ontimeout: () => s(new Error("\u63a5\u53e3\u8bf7\u6c42\u8d85\u65f6")), onerror: e => { s(e); } }); })); } const getNonAnswerMessage = e => { const t = findNonAnswerText(e); return t ? `\u63a5\u53e3\u8fd4\u56de\u975e\u7b54\u6848\u6587\u6848\uff1a${t}` : ""; }; class Answer { constructor() {} static score(e, t) { let n = Cache.get("api_" + e, { score: 0 }); n.score += t, Cache.set("api_" + e, n, 600); } static async getAnswersFree(e) { return Promise.all([this.getMainAnswer(e)]); } static getTimestamp() { return Math.floor((new Date).getTime() / 1e3); } static cacheAnswer(e, t) { const n = { type: e.type, question: e.question, options: e.options, answer: e.answer }, a = findNonAnswerText(n.answer); if (a) return false; const r = questionHash(n.type, n.question, n.options); n.createTime = this.getTimestamp(); const i = "ques1_" + r; return Cache.set(i, n), (null == t ? void 0 : t.startsWith("ques1_")) && t !== i && Cache.remove(t), true; } static async getCacheAnswer(e) { const t = questionHash(e.type, e.question, e.options); e.type, e.question, e.options; const n = Cache.get("ques1_" + t) ?? findCompatibleCachedQuestion(e, (() => Cache.matchGet("ques1_"))); return n ? { form: "\u672c\u5730\u7f13\u5b58", answer: cachedQuestionAnswer(n), duration: 10 } : { form: "\u672c\u5730\u7f13\u5b58", answer: "", duration: 10, msg: "\u672a\u627e\u5230\u7f13\u5b58" }; } static getMainAnswer(e) { const t = (n = e.question, a = isLoggedInUserCache(Cache.get("user", {})), "string" != typeof n || "" === n.trim() ? { answer: "", duration: 0, msg: "\u9898\u5e72\u4e3a\u7a7a\uff0c\u672a\u67e5\u8be2\u9898\u5e93" } : a ? null : { answer: "", duration: 0, msg: "\u767b\u5f55\u540e\u624d\u53ef\u4ee5\u4f7f\u7528\u9898\u5e93\u641c\u9898\uff0c\u8bf7\u5148\u767b\u5f55", needLogin: true }); var n, a; if (t) return t.msg, Promise.resolve({ form: "私有题库", ...t }); const r = { type: e.type, question: e.question, options: e.options.map((e => e)), workType: e.workType, pageType: e.pageType }, i = apiUrl("answers/resolve"); return new Promise((e => { requestApi(i, "POST", r, {}, 6e3).then((t => { var n; let a = t[1]; t = JSON.parse(t[0].responseText); const nonAnswer = getNonAnswerMessage(null == (n = t.data) ? void 0 : n.answer); 200 === t.code && t.data.answer && !nonAnswer ? (Answer.cacheAnswer({ type: r.type, question: r.question, options: r.options, answer: t.data.answer, cacheOrigin: "cloud" }), e({ form: "私有题库", answer: t.data.answer, duration: a, msg: t.message })) : nonAnswer ? e({ form: "私有题库", answer: "", duration: a, msg: nonAnswer }) : 401 === t.code ? e({ form: "私有题库", answer: "", duration: a, msg: t.message, needLogin: true }) : e({ form: "私有题库", answer: "", duration: a, msg: t.message }); })).catch((t => { e({ form: "私有题库", answer: "", error: t, duration: 10, msg: "\u8bf7\u6c42\u5931\u8d25" }); })); })); } static async syncQuestionList(e) { const result = await uploadWorkspacePlatformAnswers(e.questionList || [], e.pageType); return JSON.stringify({code: result.retry ? 503 : 200, data: result, message: result.retry ? "上传暂未完成,将自动重试" : "采集完成"}); } static async syncPaper(e) { return new Promise(((t, n) => { requestApi(apiUrl("captures/course"), "POST", e, {}).then((e => { try { const n = e[0].responseText, a = JSON.parse(n); a && (200 === a.code || 0 === a.code || a.success), t(a); } catch (n) { t({ code: -1, error: n, msg: "\u54cd\u5e94\u89e3\u6790\u5931\u8d25" }); } })).catch((e => { t({ code: -1, error: e, msg: "\u7f51\u7edc\u8bf7\u6c42\u5931\u8d25" }); })); })); } } const defaultSetAnswer = async (e, t, n, a, r) => { var i; switch (assertFillShouldContinue(r), e) { case "xx": { const optionClickDelay = () => a.optionDelay ? Math.floor(a.optionDelay + 500 * Math.random()) : Math.floor(300 * Math.random() + 200); let e = false; for (let i = 0; i < n.$options.length; i++) { assertFillShouldContinue(r); const s = !(!a.ischecked || !a.ischecked(n.$options.eq(i))); t.includes(i) !== s && (e && (await sleep(optionClickDelay()), assertFillShouldContinue(r)), n.$options.eq(i).click(), e = true); } break; } case "pd": let e = t; 0 == n.options.length ? n.$options.each(((t, n) => { assertFillShouldContinue(r), isTrue(e) && isTrue(removeHtml(O(n).html())) && O(n).click(), isFalse(e) && isFalse(removeHtml(O(n).html())) && O(n).click(); })) : n.$options.each(((t, a) => { assertFillShouldContinue(r), isTrue(e) && isTrue(n.options[t]) && O(a).click(), isFalse(e) && isFalse(n.options[t]) && O(a).click(); })); break; case "jd": O(n.html).find("textarea").each((function(e) { assertFillShouldContinue(r), ie.UE.getEditor(O(this).attr("name")).ready((function() { this.setContent(t[e].replace(/\u7b2c.\u7a7a:/g, "")); })); })), null == (i = O(n.html).find(".savebtndiv>a")) || i.click(); break; case "ydlj": if (Array.isArray(t) && n.options) for (let i = 0; i < t.length && i < n.options.length; i++) { assertFillShouldContinue(r); let e = t[i], s = n.options[i]; if (Array.isArray(e) && e.length > 0 && s.$options) for (let t = 0; t < s.$options.length; t++) if (assertFillShouldContinue(r), e.includes(t)) { if (a.ischecked && a.ischecked(s.$options.eq(t))) continue; s.$options.eq(t).click(), await sleep(Math.floor(300 * Math.random() + 200)); } else a.ischecked && a.ischecked(s.$options.eq(t)) && (s.$options.eq(t).click(), await sleep(Math.floor(300 * Math.random() + 200))); } } }, applyAnswerResult = async (e, t, n, a, r) => { let i = true; assertFillShouldContinue(r), a.setAnswerHook && "function" == typeof a.setAnswerHook && await a.setAnswerHook({ type: n.type, answer: t, html: n.html, ques: n }), assertFillShouldContinue(r), a.setAnswer && "function" == typeof a.setAnswer && (i = await a.setAnswer({ type: n.type, answer: t, html: n.html, ques: n, rule: a })), assertFillShouldContinue(r), i && await defaultSetAnswer(e, t, n, a, r); }, Xe = class _Paper { static getPaper(e) { return Cache.get(`${_Paper.prefix}_${e}`); } static getLastSyncedHashes(e) { const t = Cache.get(`${_Paper.lastSyncedPrefix}_${e}`, { questions: [], chapters: [] }); return { questions: new Set(t.questions || []), chapters: new Set(t.chapters || []) }; } static setLastSyncedHashes(e, t, n) { Cache.set(`${_Paper.lastSyncedPrefix}_${e}`, { questions: t, chapters: n }); } static compareAndGetNewData(e, t) { const n = _Paper.getLastSyncedHashes(t), a = new Set, r = new Set, i = new Map, s = new Map; e.chapter && Array.isArray(e.chapter) && e.chapter.forEach((e => { const t = e.hash; r.add(t); const n = new Map; e.question && Array.isArray(e.question) && e.question.forEach((e => { const t = e.hash; a.add(t), i.set(t, e), n.set(t, e); })), s.set(t, { chapter: e, questions: n }); })); const o = [], l = []; a.forEach((e => { n.questions.has(e) || o.push(e); })), r.forEach((e => { n.chapters.has(e) || l.push(e); })); const c = { hash: e.hash, name: e.name, platform: e.platform, info: e.info, chapter: [] }; return s.forEach(((e, t) => { if (l.includes(t)) c.chapter.push({ hash: e.chapter.hash, name: e.chapter.name, question: Array.from(e.questions.values()) }); else { const t = []; e.questions.forEach(((e, n) => { o.includes(n) && t.push(e); })), t.length > 0 && c.chapter.push({ hash: e.chapter.hash, name: e.chapter.name, question: t }); } })), { newData: c, newQuestionHashes: o, newChapterHashes: l }; } static async setPaper(e, t, n = {}) { if (!e || !t) return; const a = _Paper.getPaper(e) || { chapter: [] }; t.chapter && t.chapter.forEach((e => { const t = a.chapter.find((t => t.hash === e.hash)); t ? (n.replaceQuestions ? t.question = e.question || [] : e.question.forEach((e => { const n = t.question.findIndex((t => t.hash === e.hash)); -1 !== n ? t.question[n] = e : t.question.push(e); })), Object.keys(e).forEach((n => { "question" !== n && (t[n] = e[n]); }))) : a.chapter.push(e); })), Object.keys(t).forEach((e => { "chapter" !== e && (a[e] = t[e]); })), Cache.set(`${_Paper.prefix}_${e}`, a); const {newData: r, newQuestionHashes: i, newChapterHashes: s} = _Paper.compareAndGetNewData(a, e); if (i.length > 0 || s.length > 0) { if (0 === r.chapter.length) return; i.length, s.length; try { const t = await Answer.syncPaper(r); let n; if ("string" == typeof t) try { n = JSON.parse(t); } catch (o) { return; } else n = t; if (!n || 200 !== n.code && 0 !== n.code && !0 !== n.success) JSON.stringify(n); else { const t = _Paper.getLastSyncedHashes(e), n = Array.from(new Set([ ...t.questions, ...i ])), a = Array.from(new Set([ ...t.chapters, ...s ])); _Paper.setLastSyncedHashes(e, n, a), i.length, s.length; } } catch (l) {} } } static hasChapter(e, t) { const n = _Paper.getPaper(e); return !(!n || !n.chapter) && n.chapter.some((e => e.hash === t)); } static getAllPapers() { return Cache.matchGet(`${_Paper.prefix}_`); } }; __publicField(Xe, "prefix", "paper_"), __publicField(Xe, "lastSyncedPrefix", "paper_last_synced_"); let et = Xe; function getDefaultExportFromCjs(e) { return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e; } var tt, nt; const at = getDefaultExportFromCjs(function() { if (nt) return tt; nt = 1; var e = { parse: function(t) { var n = e._bin, a = new Uint8Array(t), r = 0; n.readFixed(a, r), r += 4; var i = n.readUshort(a, r); r += 2, n.readUshort(a, r), r += 2, n.readUshort(a, r), r += 2, n.readUshort(a, r), r += 2; for (var s = [ "cmap", "head", "hhea", "maxp", "hmtx", "name", "OS/2", "post", "loca", "glyf", "kern", "CFF ", "GPOS", "GSUB", "SVG " ], o = { _data: a }, l = {}, c = 0; c < i; c++) { var u = n.readASCII(a, r, 4); r += 4, n.readUint(a, r), r += 4; var p = n.readUint(a, r); r += 4; var d = n.readUint(a, r); r += 4, l[u] = { offset: p, length: d }; } for (c = 0; c < s.length; c++) { var m = s[c]; l[m] && (o[m.trim()] = e[m.trim()].parse(a, l[m].offset, l[m].length, o)); } return o; }, _tabOffset: function(t, n) { for (var a = e._bin, r = a.readUshort(t, 4), i = 12, s = 0; s < r; s++) { var o = a.readASCII(t, i, 4); i += 4, a.readUint(t, i), i += 4; var l = a.readUint(t, i); if (i += 4, a.readUint(t, i), i += 4, o == n) return l; } return 0; } }; return e._bin = { readFixed: function(e, t) { return (e[t] << 8 | e[t + 1]) + (e[t + 2] << 8 | e[t + 3]) / 65540; }, readF2dot14: function(t, n) { return e._bin.readShort(t, n) / 16384; }, readInt: function(t, n) { var a = e._bin.t.uint8; return a[0] = t[n + 3], a[1] = t[n + 2], a[2] = t[n + 1], a[3] = t[n], e._bin.t.int32[0]; }, readInt8: function(t, n) { return e._bin.t.uint8[0] = t[n], e._bin.t.int8[0]; }, readShort: function(t, n) { var a = e._bin.t.uint8; return a[1] = t[n], a[0] = t[n + 1], e._bin.t.int16[0]; }, readUshort: function(e, t) { return e[t] << 8 | e[t + 1]; }, readUshorts: function(t, n, a) { for (var r = [], i = 0; i < a; i++) r.push(e._bin.readUshort(t, n + 2 * i)); return r; }, readUint: function(t, n) { var a = e._bin.t.uint8; return a[3] = t[n], a[2] = t[n + 1], a[1] = t[n + 2], a[0] = t[n + 3], e._bin.t.uint32[0]; }, readUint64: function(t, n) { return 4294967296 * e._bin.readUint(t, n) + e._bin.readUint(t, n + 4); }, readASCII: function(e, t, n) { for (var a = "", r = 0; r < n; r++) a += String.fromCharCode(e[t + r]); return a; }, readUnicode: function(e, t, n) { for (var a = "", r = 0; r < n; r++) { var i = e[t++] << 8 | e[t++]; a += String.fromCharCode(i); } return a; }, _tdec: window.TextDecoder ? new window.TextDecoder : null, readUTF8: function(t, n, a) { var r = e._bin._tdec; return r && 0 == n && a == t.length ? r.decode(t) : e._bin.readASCII(t, n, a); }, readBytes: function(e, t, n) { for (var a = [], r = 0; r < n; r++) a.push(e[t + r]); return a; }, readASCIIArray: function(e, t, n) { for (var a = [], r = 0; r < n; r++) a.push(String.fromCharCode(e[t + r])); return a; } }, e._bin.t = { buff: new ArrayBuffer(8) }, e._bin.t.int8 = new Int8Array(e._bin.t.buff), e._bin.t.uint8 = new Uint8Array(e._bin.t.buff), e._bin.t.int16 = new Int16Array(e._bin.t.buff), e._bin.t.uint16 = new Uint16Array(e._bin.t.buff), e._bin.t.int32 = new Int32Array(e._bin.t.buff), e._bin.t.uint32 = new Uint32Array(e._bin.t.buff), e._lctf = {}, e._lctf.parse = function(t, n, a, r, i) { var s = e._bin, o = {}, l = n; s.readFixed(t, n), n += 4; var c = s.readUshort(t, n); n += 2; var u = s.readUshort(t, n); n += 2; var p = s.readUshort(t, n); return n += 2, o.scriptList = e._lctf.readScriptList(t, l + c), o.featureList = e._lctf.readFeatureList(t, l + u), o.lookupList = e._lctf.readLookupList(t, l + p, i), o; }, e._lctf.readLookupList = function(t, n, a) { var r = e._bin, i = n, s = [], o = r.readUshort(t, n); n += 2; for (var l = 0; l < o; l++) { var c = r.readUshort(t, n); n += 2; var u = e._lctf.readLookupTable(t, i + c, a); s.push(u); } return s; }, e._lctf.readLookupTable = function(t, n, a) { var r = e._bin, i = n, s = { tabs: [] }; s.ltype = r.readUshort(t, n), n += 2, s.flag = r.readUshort(t, n), n += 2; var o = r.readUshort(t, n); n += 2; for (var l = 0; l < o; l++) { var c = r.readUshort(t, n); n += 2; var u = a(t, s.ltype, i + c); s.tabs.push(u); } return s; }, e._lctf.numOfOnes = function(e) { for (var t = 0, n = 0; n < 32; n++) e >>> n & 1 && t++; return t; }, e._lctf.readClassDef = function(t, n) { var a = e._bin, r = [], i = a.readUshort(t, n); if (n += 2, 1 == i) { var s = a.readUshort(t, n); n += 2; var o = a.readUshort(t, n); n += 2; for (var l = 0; l < o; l++) r.push(s + l), r.push(s + l), r.push(a.readUshort(t, n)), n += 2; } if (2 == i) { var c = a.readUshort(t, n); n += 2; for (l = 0; l < c; l++) r.push(a.readUshort(t, n)), n += 2, r.push(a.readUshort(t, n)), n += 2, r.push(a.readUshort(t, n)), n += 2; } return r; }, e._lctf.getInterval = function(e, t) { for (var n = 0; n < e.length; n += 3) { var a = e[n], r = e[n + 1]; if (e[n + 2], a <= t && t <= r) return n; } return -1; }, e._lctf.readValueRecord = function(t, n, a) { var r = e._bin, i = []; return i.push(1 & a ? r.readShort(t, n) : 0), n += 1 & a ? 2 : 0, i.push(2 & a ? r.readShort(t, n) : 0), n += 2 & a ? 2 : 0, i.push(4 & a ? r.readShort(t, n) : 0), n += 4 & a ? 2 : 0, i.push(8 & a ? r.readShort(t, n) : 0), n += 8 & a ? 2 : 0, i; }, e._lctf.readCoverage = function(t, n) { var a = e._bin, r = {}; r.fmt = a.readUshort(t, n), n += 2; var i = a.readUshort(t, n); return n += 2, 1 == r.fmt && (r.tab = a.readUshorts(t, n, i)), 2 == r.fmt && (r.tab = a.readUshorts(t, n, 3 * i)), r; }, e._lctf.coverageIndex = function(t, n) { var a = t.tab; if (1 == t.fmt) return a.indexOf(n); if (2 == t.fmt) { var r = e._lctf.getInterval(a, n); if (-1 != r) return a[r + 2] + (n - a[r]); } return -1; }, e._lctf.readFeatureList = function(t, n) { var a = e._bin, r = n, i = [], s = a.readUshort(t, n); n += 2; for (var o = 0; o < s; o++) { var l = a.readASCII(t, n, 4); n += 4; var c = a.readUshort(t, n); n += 2, i.push({ tag: l.trim(), tab: e._lctf.readFeatureTable(t, r + c) }); } return i; }, e._lctf.readFeatureTable = function(t, n) { var a = e._bin; a.readUshort(t, n), n += 2; var r = a.readUshort(t, n); n += 2; for (var i = [], s = 0; s < r; s++) i.push(a.readUshort(t, n + 2 * s)); return i; }, e._lctf.readScriptList = function(t, n) { var a = e._bin, r = n, i = {}, s = a.readUshort(t, n); n += 2; for (var o = 0; o < s; o++) { var l = a.readASCII(t, n, 4); n += 4; var c = a.readUshort(t, n); n += 2, i[l.trim()] = e._lctf.readScriptTable(t, r + c); } return i; }, e._lctf.readScriptTable = function(t, n) { var a = e._bin, r = n, i = {}, s = a.readUshort(t, n); n += 2, i.default = e._lctf.readLangSysTable(t, r + s); var o = a.readUshort(t, n); n += 2; for (var l = 0; l < o; l++) { var c = a.readASCII(t, n, 4); n += 4; var u = a.readUshort(t, n); n += 2, i[c.trim()] = e._lctf.readLangSysTable(t, r + u); } return i; }, e._lctf.readLangSysTable = function(t, n) { var a = e._bin, r = {}; a.readUshort(t, n), n += 2, r.reqFeature = a.readUshort(t, n), n += 2; var i = a.readUshort(t, n); return n += 2, r.features = a.readUshorts(t, n, i), r; }, e.CFF = {}, e.CFF.parse = function(t, n, a) { var r = e._bin; (t = new Uint8Array(t.buffer, n, a))[n = 0], t[++n], t[++n], t[++n], n++; var i = []; n = e.CFF.readIndex(t, n, i); for (var s = [], o = 0; o < i.length - 1; o++) s.push(r.readASCII(t, n + i[o], i[o + 1] - i[o])); n += i[i.length - 1]; var l = []; n = e.CFF.readIndex(t, n, l); var c = []; for (o = 0; o < l.length - 1; o++) c.push(e.CFF.readDict(t, n + l[o], n + l[o + 1])); n += l[l.length - 1]; var u = c[0], p = []; n = e.CFF.readIndex(t, n, p); var d = []; for (o = 0; o < p.length - 1; o++) d.push(r.readASCII(t, n + p[o], p[o + 1] - p[o])); if (n += p[p.length - 1], e.CFF.readSubrs(t, n, u), u.CharStrings) { n = u.CharStrings; p = []; n = e.CFF.readIndex(t, n, p); var m = []; for (o = 0; o < p.length - 1; o++) m.push(r.readBytes(t, n + p[o], p[o + 1] - p[o])); u.CharStrings = m; } u.Encoding && (u.Encoding = e.CFF.readEncoding(t, u.Encoding, u.CharStrings.length)), u.charset && (u.charset = e.CFF.readCharset(t, u.charset, u.CharStrings.length)), u.Private && (n = u.Private[1], u.Private = e.CFF.readDict(t, n, n + u.Private[0]), u.Private.Subrs && e.CFF.readSubrs(t, n + u.Private.Subrs, u.Private)); var h = {}; for (var f in u) -1 != [ "FamilyName", "FullName", "Notice", "version", "Copyright" ].indexOf(f) ? h[f] = d[u[f] - 426 + 35] : h[f] = u[f]; return h; }, e.CFF.readSubrs = function(t, n, a) { var r = e._bin, i = []; n = e.CFF.readIndex(t, n, i); var s, o = i.length; s = o < 1240 ? 107 : o < 33900 ? 1131 : 32768, a.Bias = s, a.Subrs = []; for (var l = 0; l < i.length - 1; l++) a.Subrs.push(r.readBytes(t, n + i[l], i[l + 1] - i[l])); }, e.CFF.tableSE = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 0, 111, 112, 113, 114, 0, 115, 116, 117, 118, 119, 120, 121, 122, 0, 123, 0, 124, 125, 126, 127, 128, 129, 130, 131, 0, 132, 133, 0, 134, 135, 136, 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 0, 139, 0, 0, 0, 0, 140, 141, 142, 143, 0, 0, 0, 0, 0, 144, 0, 0, 0, 145, 0, 0, 146, 147, 148, 149, 0, 0, 0, 0 ], e.CFF.glyphByUnicode = function(e, t) { for (var n = 0; n < e.charset.length; n++) if (e.charset[n] == t) return n; return -1; }, e.CFF.glyphBySE = function(t, n) { return n < 0 || n > 255 ? -1 : e.CFF.glyphByUnicode(t, e.CFF.tableSE[n]); }, e.CFF.readEncoding = function(t, n, a) { e._bin; var r = [ ".notdef" ], i = t[n]; if (n++, 0 != i) throw "error: unknown encoding format: " + i; var s = t[n]; n++; for (var o = 0; o < s; o++) r.push(t[n + o]); return r; }, e.CFF.readCharset = function(t, n, a) { var r = e._bin, i = [ ".notdef" ], s = t[n]; if (n++, 0 == s) for (var o = 0; o < a; o++) { var l = r.readUshort(t, n); n += 2, i.push(l); } else { if (1 != s && 2 != s) throw "error: format: " + s; for (;i.length < a; ) { l = r.readUshort(t, n); n += 2; var c = 0; 1 == s ? (c = t[n], n++) : (c = r.readUshort(t, n), n += 2); for (o = 0; o <= c; o++) i.push(l), l++; } } return i; }, e.CFF.readIndex = function(t, n, a) { var r = e._bin, i = r.readUshort(t, n), s = t[n += 2]; if (n++, 1 == s) for (var o = 0; o < i + 1; o++) a.push(t[n + o]); else if (2 == s) for (o = 0; o < i + 1; o++) a.push(r.readUshort(t, n + 2 * o)); else if (3 == s) for (o = 0; o < i + 1; o++) a.push(16777215 & r.readUint(t, n + 3 * o - 1)); else if (0 != i) throw "unsupported offset size: " + s + ", count: " + i; return (n += (i + 1) * s) - 1; }, e.CFF.getCharString = function(t, n, a) { var r = e._bin, i = t[n], s = t[n + 1]; t[n + 2], t[n + 3], t[n + 4]; var o = 1, l = null, c = null; i <= 20 && (l = i, o = 1), 12 == i && (l = 100 * i + s, o = 2), 21 <= i && i <= 27 && (l = i, o = 1), 28 == i && (c = r.readShort(t, n + 1), o = 3), 29 <= i && i <= 31 && (l = i, o = 1), 32 <= i && i <= 246 && (c = i - 139, o = 1), 247 <= i && i <= 250 && (c = 256 * (i - 247) + s + 108, o = 2), 251 <= i && i <= 254 && (c = 256 * -(i - 251) - s - 108, o = 2), 255 == i && (c = r.readInt(t, n + 1) / 65535, o = 5), a.val = null != c ? c : "o" + l, a.size = o; }, e.CFF.readCharString = function(t, n, a) { for (var r = n + a, i = e._bin, s = []; n < r; ) { var o = t[n], l = t[n + 1]; t[n + 2], t[n + 3], t[n + 4]; var c = 1, u = null, p = null; o <= 20 && (u = o, c = 1), 12 == o && (u = 100 * o + l, c = 2), 19 != o && 20 != o || (u = o, c = 2), 21 <= o && o <= 27 && (u = o, c = 1), 28 == o && (p = i.readShort(t, n + 1), c = 3), 29 <= o && o <= 31 && (u = o, c = 1), 32 <= o && o <= 246 && (p = o - 139, c = 1), 247 <= o && o <= 250 && (p = 256 * (o - 247) + l + 108, c = 2), 251 <= o && o <= 254 && (p = 256 * -(o - 251) - l - 108, c = 2), 255 == o && (p = i.readInt(t, n + 1) / 65535, c = 5), s.push(null != p ? p : "o" + u), n += c; } return s; }, e.CFF.readDict = function(t, n, a) { for (var r = e._bin, i = {}, s = []; n < a; ) { var o = t[n], l = t[n + 1]; t[n + 2], t[n + 3], t[n + 4]; var c = 1, u = null, p = null; if (28 == o && (p = r.readShort(t, n + 1), c = 3), 29 == o && (p = r.readInt(t, n + 1), c = 5), 32 <= o && o <= 246 && (p = o - 139, c = 1), 247 <= o && o <= 250 && (p = 256 * (o - 247) + l + 108, c = 2), 251 <= o && o <= 254 && (p = 256 * -(o - 251) - l - 108, c = 2), 255 == o) throw p = r.readInt(t, n + 1) / 65535, c = 5, "unknown number"; if (30 == o) { var d = []; for (c = 1; ;) { var m = t[n + c]; c++; var h = m >> 4, f = 15 & m; if (15 != h && d.push(h), 15 != f && d.push(f), 15 == f) break; } for (var g = "", v = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ".", "e", "e-", "reserved", "-", "endOfNumber" ], y = 0; y < d.length; y++) g += v[d[y]]; p = parseFloat(g); } if (o <= 21) if (u = [ "version", "Notice", "FullName", "FamilyName", "Weight", "FontBBox", "BlueValues", "OtherBlues", "FamilyBlues", "FamilyOtherBlues", "StdHW", "StdVW", "escape", "UniqueID", "XUID", "charset", "Encoding", "CharStrings", "Private", "Subrs", "defaultWidthX", "nominalWidthX" ][o], c = 1, 12 == o) u = [ "Copyright", "isFixedPitch", "ItalicAngle", "UnderlinePosition", "UnderlineThickness", "PaintType", "CharstringType", "FontMatrix", "StrokeWidth", "BlueScale", "BlueShift", "BlueFuzz", "StemSnapH", "StemSnapV", "ForceBold", 0, 0, "LanguageGroup", "ExpansionFactor", "initialRandomSeed", "SyntheticBase", "PostScript", "BaseFontName", "BaseFontBlend", 0, 0, 0, 0, 0, 0, "ROS", "CIDFontVersion", "CIDFontRevision", "CIDFontType", "CIDCount", "UIDBase", "FDArray", "FDSelect", "FontName" ][l], c = 2; null != u ? (i[u] = 1 == s.length ? s[0] : s, s = []) : s.push(p), n += c; } return i; }, e.cmap = {}, e.cmap.parse = function(t, n, a) { t = new Uint8Array(t.buffer, n, a), n = 0; var r = e._bin, i = {}; r.readUshort(t, n), n += 2; var s = r.readUshort(t, n); n += 2; var o = []; i.tables = []; for (var l = 0; l < s; l++) { var c = r.readUshort(t, n); n += 2; var u = r.readUshort(t, n); n += 2; var p = r.readUint(t, n); n += 4; var d = "p" + c + "e" + u, m = o.indexOf(p); if (-1 == m) { var h; m = i.tables.length, o.push(p); var f = r.readUshort(t, p); 0 == f ? h = e.cmap.parse0(t, p) : 4 == f ? h = e.cmap.parse4(t, p) : 6 == f ? h = e.cmap.parse6(t, p) : 12 == f ? h = e.cmap.parse12(t, p) : console.log("unknown format: " + f, c, u, p), i.tables.push(h); } if (null != i[d]) throw "multiple tables for one platform+encoding"; i[d] = m; } return i; }, e.cmap.parse0 = function(t, n) { var a = e._bin, r = {}; r.format = a.readUshort(t, n), n += 2; var i = a.readUshort(t, n); n += 2, a.readUshort(t, n), n += 2, r.map = []; for (var s = 0; s < i - 6; s++) r.map.push(t[n + s]); return r; }, e.cmap.parse4 = function(t, n) { var a = e._bin, r = n, i = {}; i.format = a.readUshort(t, n), n += 2; var s = a.readUshort(t, n); n += 2, a.readUshort(t, n), n += 2; var o = a.readUshort(t, n); n += 2; var l = o / 2; i.searchRange = a.readUshort(t, n), n += 2, i.entrySelector = a.readUshort(t, n), n += 2, i.rangeShift = a.readUshort(t, n), n += 2, i.endCount = a.readUshorts(t, n, l), n += 2 * l, n += 2, i.startCount = a.readUshorts(t, n, l), n += 2 * l, i.idDelta = []; for (var c = 0; c < l; c++) i.idDelta.push(a.readShort(t, n)), n += 2; for (i.idRangeOffset = a.readUshorts(t, n, l), n += 2 * l, i.glyphIdArray = []; n < r + s; ) i.glyphIdArray.push(a.readUshort(t, n)), n += 2; return i; }, e.cmap.parse6 = function(t, n) { var a = e._bin, r = {}; r.format = a.readUshort(t, n), n += 2, a.readUshort(t, n), n += 2, a.readUshort(t, n), n += 2, r.firstCode = a.readUshort(t, n), n += 2; var i = a.readUshort(t, n); n += 2, r.glyphIdArray = []; for (var s = 0; s < i; s++) r.glyphIdArray.push(a.readUshort(t, n)), n += 2; return r; }, e.cmap.parse12 = function(t, n) { var a = e._bin, r = {}; r.format = a.readUshort(t, n), n += 2, n += 2, a.readUint(t, n), n += 4, a.readUint(t, n), n += 4; var i = a.readUint(t, n); n += 4, r.groups = []; for (var s = 0; s < i; s++) { var o = n + 12 * s, l = a.readUint(t, o + 0), c = a.readUint(t, o + 4), u = a.readUint(t, o + 8); r.groups.push([ l, c, u ]); } return r; }, e.glyf = {}, e.glyf.parse = function(e, t, n, a) { for (var r = [], i = 0; i < a.maxp.numGlyphs; i++) r.push(null); return r; }, e.glyf._parseGlyf = function(t, n) { var a = e._bin, r = t._data, i = e._tabOffset(r, "glyf") + t.loca[n]; if (t.loca[n] == t.loca[n + 1]) return null; var s = {}; if (s.noc = a.readShort(r, i), i += 2, s.xMin = a.readShort(r, i), i += 2, s.yMin = a.readShort(r, i), i += 2, s.xMax = a.readShort(r, i), i += 2, s.yMax = a.readShort(r, i), i += 2, s.xMin >= s.xMax || s.yMin >= s.yMax) return null; if (s.noc > 0) { s.endPts = []; for (var o = 0; o < s.noc; o++) s.endPts.push(a.readUshort(r, i)), i += 2; var l = a.readUshort(r, i); if (i += 2, r.length - i < l) return null; s.instructions = a.readBytes(r, i, l), i += l; var c = s.endPts[s.noc - 1] + 1; s.flags = []; for (o = 0; o < c; o++) { var u = r[i]; if (i++, s.flags.push(u), 8 & u) { var p = r[i]; i++; for (var d = 0; d < p; d++) s.flags.push(u), o++; } } s.xs = []; for (o = 0; o < c; o++) { var m = !!(2 & s.flags[o]), h = !!(16 & s.flags[o]); m ? (s.xs.push(h ? r[i] : -r[i]), i++) : h ? s.xs.push(0) : (s.xs.push(a.readShort(r, i)), i += 2); } s.ys = []; for (o = 0; o < c; o++) { m = !!(4 & s.flags[o]), h = !!(32 & s.flags[o]); m ? (s.ys.push(h ? r[i] : -r[i]), i++) : h ? s.ys.push(0) : (s.ys.push(a.readShort(r, i)), i += 2); } var f = 0, g = 0; for (o = 0; o < c; o++) f += s.xs[o], g += s.ys[o], s.xs[o] = f, s.ys[o] = g; } else { var v; s.parts = []; do { v = a.readUshort(r, i), i += 2; var y = { m: { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }, p1: -1, p2: -1 }; if (s.parts.push(y), y.glyphIndex = a.readUshort(r, i), i += 2, 1 & v) { var b = a.readShort(r, i); i += 2; var w = a.readShort(r, i); i += 2; } else { b = a.readInt8(r, i); i++; w = a.readInt8(r, i); i++; } 2 & v ? (y.m.tx = b, y.m.ty = w) : (y.p1 = b, y.p2 = w), 8 & v ? (y.m.a = y.m.d = a.readF2dot14(r, i), i += 2) : 64 & v ? (y.m.a = a.readF2dot14(r, i), i += 2, y.m.d = a.readF2dot14(r, i), i += 2) : 128 & v && (y.m.a = a.readF2dot14(r, i), i += 2, y.m.b = a.readF2dot14(r, i), i += 2, y.m.c = a.readF2dot14(r, i), i += 2, y.m.d = a.readF2dot14(r, i), i += 2); } while (32 & v); if (256 & v) { var x = a.readUshort(r, i); i += 2, s.instr = []; for (o = 0; o < x; o++) s.instr.push(r[i]), i++; } } return s; }, e.GPOS = {}, e.GPOS.parse = function(t, n, a, r) { return e._lctf.parse(t, n, a, r, e.GPOS.subt); }, e.GPOS.subt = function(t, n, a) { if (2 != n) return null; var r = e._bin, i = a, s = {}; s.format = r.readUshort(t, a), a += 2; var o = r.readUshort(t, a); a += 2, s.coverage = e._lctf.readCoverage(t, o + i), s.valFmt1 = r.readUshort(t, a), a += 2, s.valFmt2 = r.readUshort(t, a), a += 2; var l = e._lctf.numOfOnes(s.valFmt1), c = e._lctf.numOfOnes(s.valFmt2); if (1 == s.format) { s.pairsets = []; var u = r.readUshort(t, a); a += 2; for (var p = 0; p < u; p++) { var d = r.readUshort(t, a); a += 2, d += i; var m = r.readUshort(t, d); d += 2; for (var h = [], f = 0; f < m; f++) { var g = r.readUshort(t, d); d += 2, 0 != s.valFmt1 && (k = e._lctf.readValueRecord(t, d, s.valFmt1), d += 2 * l), 0 != s.valFmt2 && (q = e._lctf.readValueRecord(t, d, s.valFmt2), d += 2 * c), h.push({ gid2: g, val1: k, val2: q }); } s.pairsets.push(h); } } if (2 == s.format) { var v = r.readUshort(t, a); a += 2; var y = r.readUshort(t, a); a += 2; var b = r.readUshort(t, a); a += 2; var w = r.readUshort(t, a); a += 2, s.classDef1 = e._lctf.readClassDef(t, i + v), s.classDef2 = e._lctf.readClassDef(t, i + y), s.matrix = []; for (p = 0; p < b; p++) { var x = []; for (f = 0; f < w; f++) { var k = null, q = null; 0 != s.valFmt1 && (k = e._lctf.readValueRecord(t, a, s.valFmt1), a += 2 * l), 0 != s.valFmt2 && (q = e._lctf.readValueRecord(t, a, s.valFmt2), a += 2 * c), x.push({ val1: k, val2: q }); } s.matrix.push(x); } } return s; }, e.GSUB = {}, e.GSUB.parse = function(t, n, a, r) { return e._lctf.parse(t, n, a, r, e.GSUB.subt); }, e.GSUB.subt = function(t, n, a) { var r = e._bin, i = a, s = {}; if (1 != n && 4 != n && 5 != n) return null; s.fmt = r.readUshort(t, a), a += 2; var o = r.readUshort(t, a); if (a += 2, s.coverage = e._lctf.readCoverage(t, o + i), 1 == n) { if (1 == s.fmt) s.delta = r.readShort(t, a), a += 2; else if (2 == s.fmt) { var l = r.readUshort(t, a); a += 2, s.newg = r.readUshorts(t, a, l), a += 2 * s.newg.length; } } else if (4 == n) { s.vals = []; l = r.readUshort(t, a); a += 2; for (var c = 0; c < l; c++) { var u = r.readUshort(t, a); a += 2, s.vals.push(e.GSUB.readLigatureSet(t, i + u)); } } else if (5 == n) if (2 == s.fmt) { var p = r.readUshort(t, a); a += 2, s.cDef = e._lctf.readClassDef(t, i + p), s.scset = []; var d = r.readUshort(t, a); a += 2; for (c = 0; c < d; c++) { var m = r.readUshort(t, a); a += 2, s.scset.push(0 == m ? null : e.GSUB.readSubClassSet(t, i + m)); } } else console.log("unknown table format", s.fmt); return s; }, e.GSUB.readSubClassSet = function(t, n) { var a = e._bin.readUshort, r = n, i = [], s = a(t, n); n += 2; for (var o = 0; o < s; o++) { var l = a(t, n); n += 2, i.push(e.GSUB.readSubClassRule(t, r + l)); } return i; }, e.GSUB.readSubClassRule = function(t, n) { var a = e._bin.readUshort, r = {}, i = a(t, n), s = a(t, n += 2); n += 2, r.input = []; for (var o = 0; o < i - 1; o++) r.input.push(a(t, n)), n += 2; return r.substLookupRecords = e.GSUB.readSubstLookupRecords(t, n, s), r; }, e.GSUB.readSubstLookupRecords = function(t, n, a) { for (var r = e._bin.readUshort, i = [], s = 0; s < a; s++) i.push(r(t, n), r(t, n + 2)), n += 4; return i; }, e.GSUB.readChainSubClassSet = function(t, n) { var a = e._bin, r = n, i = [], s = a.readUshort(t, n); n += 2; for (var o = 0; o < s; o++) { var l = a.readUshort(t, n); n += 2, i.push(e.GSUB.readChainSubClassRule(t, r + l)); } return i; }, e.GSUB.readChainSubClassRule = function(t, n) { for (var a = e._bin, r = {}, i = [ "backtrack", "input", "lookahead" ], s = 0; s < i.length; s++) { var o = a.readUshort(t, n); n += 2, 1 == s && o--, r[i[s]] = a.readUshorts(t, n, o), n += 2 * r[i[s]].length; } o = a.readUshort(t, n); return n += 2, r.subst = a.readUshorts(t, n, 2 * o), n += 2 * r.subst.length, r; }, e.GSUB.readLigatureSet = function(t, n) { var a = e._bin, r = n, i = [], s = a.readUshort(t, n); n += 2; for (var o = 0; o < s; o++) { var l = a.readUshort(t, n); n += 2, i.push(e.GSUB.readLigature(t, r + l)); } return i; }, e.GSUB.readLigature = function(t, n) { var a = e._bin, r = { chain: [] }; r.nglyph = a.readUshort(t, n), n += 2; var i = a.readUshort(t, n); n += 2; for (var s = 0; s < i - 1; s++) r.chain.push(a.readUshort(t, n)), n += 2; return r; }, e.head = {}, e.head.parse = function(t, n, a) { var r = e._bin, i = {}; return r.readFixed(t, n), n += 4, i.fontRevision = r.readFixed(t, n), n += 4, r.readUint(t, n), n += 4, r.readUint(t, n), n += 4, i.flags = r.readUshort(t, n), n += 2, i.unitsPerEm = r.readUshort(t, n), n += 2, i.created = r.readUint64(t, n), n += 8, i.modified = r.readUint64(t, n), n += 8, i.xMin = r.readShort(t, n), n += 2, i.yMin = r.readShort(t, n), n += 2, i.xMax = r.readShort(t, n), n += 2, i.yMax = r.readShort(t, n), n += 2, i.macStyle = r.readUshort(t, n), n += 2, i.lowestRecPPEM = r.readUshort(t, n), n += 2, i.fontDirectionHint = r.readShort(t, n), n += 2, i.indexToLocFormat = r.readShort(t, n), n += 2, i.glyphDataFormat = r.readShort(t, n), n += 2, i; }, e.hhea = {}, e.hhea.parse = function(t, n, a) { var r = e._bin, i = {}; return r.readFixed(t, n), n += 4, i.ascender = r.readShort(t, n), n += 2, i.descender = r.readShort(t, n), n += 2, i.lineGap = r.readShort(t, n), n += 2, i.advanceWidthMax = r.readUshort(t, n), n += 2, i.minLeftSideBearing = r.readShort(t, n), n += 2, i.minRightSideBearing = r.readShort(t, n), n += 2, i.xMaxExtent = r.readShort(t, n), n += 2, i.caretSlopeRise = r.readShort(t, n), n += 2, i.caretSlopeRun = r.readShort(t, n), n += 2, i.caretOffset = r.readShort(t, n), n += 2, n += 8, i.metricDataFormat = r.readShort(t, n), n += 2, i.numberOfHMetrics = r.readUshort(t, n), n += 2, i; }, e.hmtx = {}, e.hmtx.parse = function(t, n, a, r) { for (var i = e._bin, s = { aWidth: [], lsBearing: [] }, o = 0, l = 0, c = 0; c < r.maxp.numGlyphs; c++) c < r.hhea.numberOfHMetrics && (o = i.readUshort(t, n), n += 2, l = i.readShort(t, n), n += 2), s.aWidth.push(o), s.lsBearing.push(l); return s; }, e.kern = {}, e.kern.parse = function(t, n, a, r) { var i = e._bin, s = i.readUshort(t, n); if (n += 2, 1 == s) return e.kern.parseV1(t, n - 2, a, r); var o = i.readUshort(t, n); n += 2; for (var l = { glyph1: [], rval: [] }, c = 0; c < o; c++) { n += 2; a = i.readUshort(t, n); n += 2; var u = i.readUshort(t, n); n += 2; var p = u >>> 8; if (0 != (p &= 15)) throw "unknown kern table format: " + p; n = e.kern.readFormat0(t, n, l); } return l; }, e.kern.parseV1 = function(t, n, a, r) { var i = e._bin; i.readFixed(t, n), n += 4; var s = i.readUint(t, n); n += 4; for (var o = { glyph1: [], rval: [] }, l = 0; l < s; l++) { i.readUint(t, n), n += 4; var c = i.readUshort(t, n); n += 2, i.readUshort(t, n), n += 2; var u = c >>> 8; if (0 != (u &= 15)) throw "unknown kern table format: " + u; n = e.kern.readFormat0(t, n, o); } return o; }, e.kern.readFormat0 = function(t, n, a) { var r = e._bin, i = -1, s = r.readUshort(t, n); n += 2, r.readUshort(t, n), n += 2, r.readUshort(t, n), n += 2, r.readUshort(t, n), n += 2; for (var o = 0; o < s; o++) { var l = r.readUshort(t, n); n += 2; var c = r.readUshort(t, n); n += 2; var u = r.readShort(t, n); n += 2, l != i && (a.glyph1.push(l), a.rval.push({ glyph2: [], vals: [] })); var p = a.rval[a.rval.length - 1]; p.glyph2.push(c), p.vals.push(u), i = l; } return n; }, e.loca = {}, e.loca.parse = function(t, n, a, r) { var i = e._bin, s = [], o = r.head.indexToLocFormat, l = r.maxp.numGlyphs + 1; if (0 == o) for (var c = 0; c < l; c++) s.push(i.readUshort(t, n + (c << 1)) << 1); if (1 == o) for (c = 0; c < l; c++) s.push(i.readUint(t, n + (c << 2))); return s; }, e.maxp = {}, e.maxp.parse = function(t, n, a) { var r = e._bin, i = {}, s = r.readUint(t, n); return n += 4, i.numGlyphs = r.readUshort(t, n), n += 2, 65536 == s && (i.maxPoints = r.readUshort(t, n), n += 2, i.maxContours = r.readUshort(t, n), n += 2, i.maxCompositePoints = r.readUshort(t, n), n += 2, i.maxCompositeContours = r.readUshort(t, n), n += 2, i.maxZones = r.readUshort(t, n), n += 2, i.maxTwilightPoints = r.readUshort(t, n), n += 2, i.maxStorage = r.readUshort(t, n), n += 2, i.maxFunctionDefs = r.readUshort(t, n), n += 2, i.maxInstructionDefs = r.readUshort(t, n), n += 2, i.maxStackElements = r.readUshort(t, n), n += 2, i.maxSizeOfInstructions = r.readUshort(t, n), n += 2, i.maxComponentElements = r.readUshort(t, n), n += 2, i.maxComponentDepth = r.readUshort(t, n), n += 2), i; }, e.name = {}, e.name.parse = function(t, n, a) { var r = e._bin, i = {}; r.readUshort(t, n), n += 2; var s = r.readUshort(t, n); n += 2, r.readUshort(t, n); for (var o, l = n += 2, c = 0; c < s; c++) { var u = r.readUshort(t, n); n += 2; var p = r.readUshort(t, n); n += 2; var d = r.readUshort(t, n); n += 2; var m = r.readUshort(t, n); n += 2; a = r.readUshort(t, n); n += 2; var h = r.readUshort(t, n); n += 2; var f = "p" + u; null == i[f] && (i[f] = {}); var g, v = [ "copyright", "fontFamily", "fontSubfamily", "ID", "fullName", "version", "postScriptName", "trademark", "manufacturer", "designer", "description", "urlVendor", "urlDesigner", "licence", "licenceURL", "---", "typoFamilyName", "typoSubfamilyName", "compatibleFull", "sampleText", "postScriptCID", "wwsFamilyName", "wwsSubfamilyName", "lightPalette", "darkPalette" ][m], y = l + 12 * s + h; if (0 == u) g = r.readUnicode(t, y, a / 2); else if (3 == u && 0 == p) g = r.readUnicode(t, y, a / 2); else if (0 == p) g = r.readASCII(t, y, a); else if (1 == p) g = r.readUnicode(t, y, a / 2); else if (3 == p) g = r.readUnicode(t, y, a / 2); else { if (1 != u) throw "unknown encoding " + p + ", platformID: " + u; g = r.readASCII(t, y, a), console.log("reading unknown MAC encoding " + p + " as ASCII"); } i[f][v] = g, i[f]._lang = d; } for (var b in i) if (null != i[b].postScriptName && 1033 == i[b]._lang) return i[b]; for (var b in i) if (null != i[b].postScriptName && 3084 == i[b]._lang) return i[b]; for (var b in i) if (null != i[b].postScriptName) return i[b]; for (var b in i) { o = b; break; } return console.log("returning name table with languageID " + i[o]._lang), i[o]; }, e["OS/2"] = {}, e["OS/2"].parse = function(t, n, a) { var r = e._bin.readUshort(t, n); n += 2; var i = {}; if (0 == r) e["OS/2"].version0(t, n, i); else if (1 == r) e["OS/2"].version1(t, n, i); else if (2 == r || 3 == r || 4 == r) e["OS/2"].version2(t, n, i); else { if (5 != r) throw "unknown OS/2 table version: " + r; e["OS/2"].version5(t, n, i); } return i; }, e["OS/2"].version0 = function(t, n, a) { var r = e._bin; return a.xAvgCharWidth = r.readShort(t, n), n += 2, a.usWeightClass = r.readUshort(t, n), n += 2, a.usWidthClass = r.readUshort(t, n), n += 2, a.fsType = r.readUshort(t, n), n += 2, a.ySubscriptXSize = r.readShort(t, n), n += 2, a.ySubscriptYSize = r.readShort(t, n), n += 2, a.ySubscriptXOffset = r.readShort(t, n), n += 2, a.ySubscriptYOffset = r.readShort(t, n), n += 2, a.ySuperscriptXSize = r.readShort(t, n), n += 2, a.ySuperscriptYSize = r.readShort(t, n), n += 2, a.ySuperscriptXOffset = r.readShort(t, n), n += 2, a.ySuperscriptYOffset = r.readShort(t, n), n += 2, a.yStrikeoutSize = r.readShort(t, n), n += 2, a.yStrikeoutPosition = r.readShort(t, n), n += 2, a.sFamilyClass = r.readShort(t, n), n += 2, a.panose = r.readBytes(t, n, 10), n += 10, a.ulUnicodeRange1 = r.readUint(t, n), n += 4, a.ulUnicodeRange2 = r.readUint(t, n), n += 4, a.ulUnicodeRange3 = r.readUint(t, n), n += 4, a.ulUnicodeRange4 = r.readUint(t, n), n += 4, a.achVendID = [ r.readInt8(t, n), r.readInt8(t, n + 1), r.readInt8(t, n + 2), r.readInt8(t, n + 3) ], n += 4, a.fsSelection = r.readUshort(t, n), n += 2, a.usFirstCharIndex = r.readUshort(t, n), n += 2, a.usLastCharIndex = r.readUshort(t, n), n += 2, a.sTypoAscender = r.readShort(t, n), n += 2, a.sTypoDescender = r.readShort(t, n), n += 2, a.sTypoLineGap = r.readShort(t, n), n += 2, a.usWinAscent = r.readUshort(t, n), n += 2, a.usWinDescent = r.readUshort(t, n), n += 2; }, e["OS/2"].version1 = function(t, n, a) { var r = e._bin; return n = e["OS/2"].version0(t, n, a), a.ulCodePageRange1 = r.readUint(t, n), n += 4, a.ulCodePageRange2 = r.readUint(t, n), n += 4; }, e["OS/2"].version2 = function(t, n, a) { var r = e._bin; return n = e["OS/2"].version1(t, n, a), a.sxHeight = r.readShort(t, n), n += 2, a.sCapHeight = r.readShort(t, n), n += 2, a.usDefault = r.readUshort(t, n), n += 2, a.usBreak = r.readUshort(t, n), n += 2, a.usMaxContext = r.readUshort(t, n), n += 2; }, e["OS/2"].version5 = function(t, n, a) { var r = e._bin; return n = e["OS/2"].version2(t, n, a), a.usLowerOpticalPointSize = r.readUshort(t, n), n += 2, a.usUpperOpticalPointSize = r.readUshort(t, n), n += 2; }, e.post = {}, e.post.parse = function(t, n, a) { var r = e._bin, i = {}; return i.version = r.readFixed(t, n), n += 4, i.italicAngle = r.readFixed(t, n), n += 4, i.underlinePosition = r.readShort(t, n), n += 2, i.underlineThickness = r.readShort(t, n), n += 2, i; }, e.SVG = {}, e.SVG.parse = function(t, n, a) { var r = e._bin, i = { entries: [] }, s = n; r.readUshort(t, n), n += 2; var o = r.readUint(t, n); n += 4, r.readUint(t, n), n += 4, n = o + s; var l = r.readUshort(t, n); n += 2; for (var c = 0; c < l; c++) { var u = r.readUshort(t, n); n += 2; var p = r.readUshort(t, n); n += 2; var d = r.readUint(t, n); n += 4; var m = r.readUint(t, n); n += 4; for (var h = new Uint8Array(t.buffer, s + d + o, m), f = r.readUTF8(h, 0, h.length), g = u; g <= p; g++) i.entries[g] = f; } return i; }, e.SVG.toPath = function(t) { var n = { cmds: [], crds: [] }; if (null == t) return n; for (var a = (new DOMParser).parseFromString(t, "image/svg+xml").firstChild; "svg" != a.tagName; ) a = a.nextSibling; var r = a.getAttribute("viewBox"); r = r ? r.trim().split(" ").map(parseFloat) : [ 0, 0, 1e3, 1e3 ], e.SVG._toPath(a.children, n); for (var i = 0; i < n.crds.length; i += 2) { var s = n.crds[i], o = n.crds[i + 1]; s -= r[0], o = -(o -= r[1]), n.crds[i] = s, n.crds[i + 1] = o; } return n; }, e.SVG._toPath = function(t, n, a) { for (var r = 0; r < t.length; r++) { var i = t[r], s = i.tagName, o = i.getAttribute("fill"); if (null == o && (o = a), "g" == s) e.SVG._toPath(i.children, n, o); else if ("path" == s) { n.cmds.push(o || "#000000"); var l = i.getAttribute("d"), c = e.SVG._tokens(l); e.SVG._toksToPath(c, n), n.cmds.push("X"); } else "defs" == s || console.log(s, i); } }, e.SVG._tokens = function(e) { for (var t = [], n = 0, a = false, r = ""; n < e.length; ) { var i = e.charCodeAt(n), s = e.charAt(n); n++; var o = 48 <= i && i <= 57 || "." == s || "-" == s; a ? "-" == s ? (t.push(parseFloat(r)), r = s) : o ? r += s : (t.push(parseFloat(r)), "," != s && " " != s && t.push(s), a = false) : o ? (r = s, a = true) : "," != s && " " != s && t.push(s); } return a && t.push(parseFloat(r)), t; }, e.SVG._toksToPath = function(t, n) { for (var a = 0, r = 0, i = 0, s = 0, o = 0, l = { M: 2, L: 2, H: 1, V: 1, S: 4, C: 6 }, c = n.cmds, u = n.crds; a < t.length; ) { var p = t[a]; if (a++, "z" == p) c.push("Z"), r = s, i = o; else for (var d = p.toUpperCase(), m = l[d], h = e.SVG._reps(t, a, m), f = 0; f < h; f++) { var g = 0, v = 0; if (p != d && (g = r, v = i), "M" == d) r = g + t[a++], i = v + t[a++], c.push("M"), u.push(r, i), s = r, o = i; else if ("L" == d) r = g + t[a++], i = v + t[a++], c.push("L"), u.push(r, i); else if ("H" == d) r = g + t[a++], c.push("L"), u.push(r, i); else if ("V" == d) i = v + t[a++], c.push("L"), u.push(r, i); else if ("C" == d) { var y = g + t[a++], b = v + t[a++], w = g + t[a++], x = v + t[a++], k = g + t[a++], q = v + t[a++]; c.push("C"), u.push(y, b, w, x, k, q), r = k, i = q; } else if ("S" == d) { var A = Math.max(u.length - 4, 0); y = r + r - u[A], b = i + i - u[A + 1], w = g + t[a++], x = v + t[a++], k = g + t[a++], q = v + t[a++]; c.push("C"), u.push(y, b, w, x, k, q), r = k, i = q; } else console.log("Unknown SVG command " + p); } } }, e.SVG._reps = function(e, t, n) { for (var a = t; a < e.length && "string" != typeof e[a]; ) a += n; return (a - t) / n; }, null == e && (e = {}), null == e.U && (e.U = {}), e.U.codeToGlyph = function(e, t) { var n = e.cmap, a = -1; if (null != n.p0e4 ? a = n.p0e4 : null != n.p3e1 ? a = n.p3e1 : null != n.p1e0 && (a = n.p1e0), -1 == a) throw "no familiar platform and encoding!"; var r = n.tables[a]; if (0 == r.format) return t >= r.map.length ? 0 : r.map[t]; if (4 == r.format) { for (var i = -1, s = 0; s < r.endCount.length; s++) if (t <= r.endCount[s]) { i = s; break; } if (-1 == i) return 0; if (r.startCount[i] > t) return 0; return 65535 & (0 != r.idRangeOffset[i] ? r.glyphIdArray[t - r.startCount[i] + (r.idRangeOffset[i] >> 1) - (r.idRangeOffset.length - i)] : t + r.idDelta[i]); } if (12 == r.format) { if (t > r.groups[r.groups.length - 1][1]) return 0; for (s = 0; s < r.groups.length; s++) { var o = r.groups[s]; if (o[0] <= t && t <= o[1]) return o[2] + (t - o[0]); } return 0; } throw "unknown cmap table format " + r.format; }, e.U.glyphToPath = function(t, n) { var a = { cmds: [], crds: [] }; if (t.SVG && t.SVG.entries[n]) { var r = t.SVG.entries[n]; return null == r ? a : ("string" == typeof r && (r = e.SVG.toPath(r), t.SVG.entries[n] = r), r); } if (t.CFF) { var i = { x: 0, y: 0, stack: [], nStems: 0, haveWidth: false, width: t.CFF.Private ? t.CFF.Private.defaultWidthX : 0, open: false }; e.U._drawCFF(t.CFF.CharStrings[n], i, t.CFF, a); } else t.glyf && e.U._drawGlyf(n, t, a); return a; }, e.U._drawGlyf = function(t, n, a) { var r = n.glyf[t]; null == r && (r = n.glyf[t] = e.glyf._parseGlyf(n, t)), null != r && (r.noc > -1 ? e.U._simpleGlyph(r, a) : e.U._compoGlyph(r, n, a)); }, e.U._simpleGlyph = function(t, n) { for (var a = 0; a < t.noc; a++) { for (var r = 0 == a ? 0 : t.endPts[a - 1] + 1, i = t.endPts[a], s = r; s <= i; s++) { var o = s == r ? i : s - 1, l = s == i ? r : s + 1, c = 1 & t.flags[s], u = 1 & t.flags[o], p = 1 & t.flags[l], d = t.xs[s], m = t.ys[s]; if (s == r) if (c) { if (!u) { e.U.P.moveTo(n, d, m); continue; } e.U.P.moveTo(n, t.xs[o], t.ys[o]); } else u ? e.U.P.moveTo(n, t.xs[o], t.ys[o]) : e.U.P.moveTo(n, (t.xs[o] + d) / 2, (t.ys[o] + m) / 2); c ? u && e.U.P.lineTo(n, d, m) : p ? e.U.P.qcurveTo(n, d, m, t.xs[l], t.ys[l]) : e.U.P.qcurveTo(n, d, m, (d + t.xs[l]) / 2, (m + t.ys[l]) / 2); } e.U.P.closePath(n); } }, e.U._compoGlyph = function(t, n, a) { for (var r = 0; r < t.parts.length; r++) { var i = { cmds: [], crds: [] }, s = t.parts[r]; e.U._drawGlyf(s.glyphIndex, n, i); for (var o = s.m, l = 0; l < i.crds.length; l += 2) { var c = i.crds[l], u = i.crds[l + 1]; a.crds.push(c * o.a + u * o.b + o.tx), a.crds.push(c * o.c + u * o.d + o.ty); } for (l = 0; l < i.cmds.length; l++) a.cmds.push(i.cmds[l]); } }, e.U._getGlyphClass = function(t, n) { var a = e._lctf.getInterval(n, t); return -1 == a ? 0 : n[a + 2]; }, e.U.getPairAdjustment = function(t, n, a) { if (t.GPOS) { for (var r = null, i = 0; i < t.GPOS.featureList.length; i++) { var s = t.GPOS.featureList[i]; if ("kern" == s.tag) for (var o = 0; o < s.tab.length; o++) 2 == t.GPOS.lookupList[s.tab[o]].ltype && (r = t.GPOS.lookupList[s.tab[o]]); } if (r) for (i = 0; i < r.tabs.length; i++) { var l = r.tabs[i], c = e._lctf.coverageIndex(l.coverage, n); if (-1 != c) { if (1 == l.format) { var u = l.pairsets[c]; for (o = 0; o < u.length; o++) u[o].gid2 == a && (m = u[o]); if (null == m) continue; } else if (2 == l.format) var p = e.U._getGlyphClass(n, l.classDef1), d = e.U._getGlyphClass(a, l.classDef2), m = l.matrix[p][d]; return m.val1[2]; } } } if (t.kern) { var h = t.kern.glyph1.indexOf(n); if (-1 != h) { var f = t.kern.rval[h].glyph2.indexOf(a); if (-1 != f) return t.kern.rval[h].vals[f]; } } return 0; }, e.U.stringToGlyphs = function(t, n) { for (var a = [], r = 0; r < n.length; r++) { var i = n.codePointAt(r); i > 65535 && r++, a.push(e.U.codeToGlyph(t, i)); } var s = t.GSUB; if (null == s) return a; for (var o = s.lookupList, l = s.featureList, c = '\n\t" ,.:;!?() \u060c', u = "\u0622\u0623\u0624\u0625\u0627\u0629\u062f\u0630\u0631\u0632\u0648\u0671\u0672\u0673\u0675\u0676\u0677\u0688\u0689\u068a\u068b\u068c\u068d\u068e\u068f\u0690\u0691\u0692\u0693\u0694\u0695\u0696\u0697\u0698\u0699\u06c0\u06c3\u06c4\u06c5\u06c6\u06c7\u06c8\u06c9\u06ca\u06cb\u06cd\u06cf\u06d2\u06d3\u06d5\u06ee\u06ef\u0710\u0715\u0716\u0717\u0718\u0719\u071e\u0728\u072a\u072c\u072f\u074d\u0759\u075a\u075b\u076b\u076c\u0771\u0773\u0774\u0778\u0779\u0840\u0846\u0847\u0849\u0854\u0867\u0869\u086a\u08aa\u08ab\u08ac\u08ae\u08b1\u08b2\u08b9\u0ac5\u0ac7\u0ac9\u0aca\u0ace\u0acf\u0ad0\u0ad1\u0ad2\u0add\u0ae1\u0ae4\u0aef\u0b81\u0b83\u0b84\u0b85\u0b89\u0b8c\u0b8e\u0b8f\u0b91\u0ba9\u0baa\u0bab\u0bac", p = 0; p < a.length; p++) { var d = a[p], m = 0 == p || -1 != c.indexOf(n[p - 1]), h = p == a.length - 1 || -1 != c.indexOf(n[p + 1]); m || -1 == u.indexOf(n[p - 1]) || (m = true), h || -1 == u.indexOf(n[p]) || (h = true), h || -1 == "\ua872\u0acd\u0ad7".indexOf(n[p + 1]) || (h = true), m || -1 == "\ua872\u0acd\u0ad7".indexOf(n[p]) || (m = true); var f = null; f = m ? h ? "isol" : "init" : h ? "fina" : "medi"; for (var g = 0; g < l.length; g++) if (l[g].tag == f) for (var v = 0; v < l[g].tab.length; v++) { 1 == (x = o[l[g].tab[v]]).ltype && e.U._applyType1(a, p, x); } } var y = [ "rlig", "liga", "mset" ]; for (p = 0; p < a.length; p++) { d = a[p]; var b = Math.min(3, a.length - p - 1); for (g = 0; g < l.length; g++) { var w = l[g]; if (-1 != y.indexOf(w.tag)) for (v = 0; v < w.tab.length; v++) for (var x = o[w.tab[v]], k = 0; k < x.tabs.length; k++) if (null != x.tabs[k]) { var q = e._lctf.coverageIndex(x.tabs[k].coverage, d); if (-1 != q) if (4 == x.ltype) for (var A = x.tabs[k].vals[q], _ = 0; _ < A.length; _++) { var T = A[_], C = T.chain.length; if (!(C > b)) { for (var S = true, I = 0; I < C; I++) T.chain[I] != a[p + (1 + I)] && (S = false); if (S) { a[p] = T.nglyph; for (I = 0; I < C; I++) a[p + I + 1] = -1; } } } else if (5 == x.ltype) { var E = x.tabs[k]; if (2 != E.fmt) continue; var U = e._lctf.getInterval(E.cDef, d), $ = E.cDef[U + 2], H = E.scset[$]; for (r = 0; r < H.length; r++) { var P = H[r], L = P.input; if (!(L.length > b)) { for (S = true, I = 0; I < L.length; I++) { var M = e._lctf.getInterval(E.cDef, a[p + 1 + I]); if (-1 == U && E.cDef[M + 2] != L[I]) { S = false; break; } } if (S) { var j = P.substLookupRecords; for (_ = 0; _ < j.length; _ += 2) j[_], j[_ + 1]; } } } } } } } return a; }, e.U._applyType1 = function(t, n, a) { for (var r = t[n], i = 0; i < a.tabs.length; i++) { var s = a.tabs[i], o = e._lctf.coverageIndex(s.coverage, r); -1 != o && (1 == s.fmt ? t[n] = t[n] + s.delta : t[n] = s.newg[o]); } }, e.U.glyphsToPath = function(t, n, a) { for (var r = { cmds: [], crds: [] }, i = 0, s = 0; s < n.length; s++) { var o = n[s]; if (-1 != o) { for (var l = s < n.length - 1 && -1 != n[s + 1] ? n[s + 1] : 0, c = e.U.glyphToPath(t, o), u = 0; u < c.crds.length; u += 2) r.crds.push(c.crds[u] + i), r.crds.push(c.crds[u + 1]); a && r.cmds.push(a); for (u = 0; u < c.cmds.length; u++) r.cmds.push(c.cmds[u]); a && r.cmds.push("X"), i += t.hmtx.aWidth[o], s < n.length - 1 && (i += e.U.getPairAdjustment(t, o, l)); } } return r; }, e.U.pathToSVG = function(e, t) { null == t && (t = 5); for (var n = [], a = 0, r = { M: 2, L: 2, Q: 4, C: 6 }, i = 0; i < e.cmds.length; i++) { var s = e.cmds[i], o = a + (r[s] ? r[s] : 0); for (n.push(s); a < o; ) { var l = e.crds[a++]; n.push(parseFloat(l.toFixed(t)) + (a == o ? "" : " ")); } } return n.join(""); }, e.U.pathToContext = function(e, t) { for (var n = 0, a = e.crds, r = 0; r < e.cmds.length; r++) { var i = e.cmds[r]; "M" == i ? (t.moveTo(a[n], a[n + 1]), n += 2) : "L" == i ? (t.lineTo(a[n], a[n + 1]), n += 2) : "C" == i ? (t.bezierCurveTo(a[n], a[n + 1], a[n + 2], a[n + 3], a[n + 4], a[n + 5]), n += 6) : "Q" == i ? (t.quadraticCurveTo(a[n], a[n + 1], a[n + 2], a[n + 3]), n += 4) : "#" == i.charAt(0) ? (t.beginPath(), t.fillStyle = i) : "Z" == i ? t.closePath() : "X" == i && t.fill(); } }, e.U.P = {}, e.U.P.moveTo = function(e, t, n) { e.cmds.push("M"), e.crds.push(t, n); }, e.U.P.lineTo = function(e, t, n) { e.cmds.push("L"), e.crds.push(t, n); }, e.U.P.curveTo = function(e, t, n, a, r, i, s) { e.cmds.push("C"), e.crds.push(t, n, a, r, i, s); }, e.U.P.qcurveTo = function(e, t, n, a, r) { e.cmds.push("Q"), e.crds.push(t, n, a, r); }, e.U.P.closePath = function(e) { e.cmds.push("Z"); }, e.U._drawCFF = function(t, n, a, r) { for (var i = n.stack, s = n.nStems, o = n.haveWidth, l = n.width, c = n.open, u = 0, p = n.x, d = n.y, m = 0, h = 0, f = 0, g = 0, v = 0, y = 0, b = 0, w = 0, x = 0, k = 0, q = { val: 0, size: 0 }; u < t.length; ) { e.CFF.getCharString(t, u, q); var A = q.val; if (u += q.size, "o1" == A || "o18" == A) i.length % 2 != 0 && !o && (l = i.shift() + a.Private.nominalWidthX), s += i.length >> 1, i.length = 0, o = true; else if ("o3" == A || "o23" == A) { i.length % 2 != 0 && !o && (l = i.shift() + a.Private.nominalWidthX), s += i.length >> 1, i.length = 0, o = true; } else if ("o4" == A) i.length > 1 && !o && (l = i.shift() + a.Private.nominalWidthX, o = true), c && e.U.P.closePath(r), d += i.pop(), e.U.P.moveTo(r, p, d), c = true; else if ("o5" == A) for (;i.length > 0; ) p += i.shift(), d += i.shift(), e.U.P.lineTo(r, p, d); else if ("o6" == A || "o7" == A) for (var _ = i.length, T = "o6" == A, C = 0; C < _; C++) { var S = i.shift(); T ? p += S : d += S, T = !T, e.U.P.lineTo(r, p, d); } else if ("o8" == A || "o24" == A) { _ = i.length; for (var I = 0; I + 6 <= _; ) m = p + i.shift(), h = d + i.shift(), f = m + i.shift(), g = h + i.shift(), p = f + i.shift(), d = g + i.shift(), e.U.P.curveTo(r, m, h, f, g, p, d), I += 6; "o24" == A && (p += i.shift(), d += i.shift(), e.U.P.lineTo(r, p, d)); } else { if ("o11" == A) break; if ("o1234" == A || "o1235" == A || "o1236" == A || "o1237" == A) "o1234" == A && (h = d, f = (m = p + i.shift()) + i.shift(), k = g = h + i.shift(), y = g, w = d, p = (b = (v = (x = f + i.shift()) + i.shift()) + i.shift()) + i.shift(), e.U.P.curveTo(r, m, h, f, g, x, k), e.U.P.curveTo(r, v, y, b, w, p, d)), "o1235" == A && (m = p + i.shift(), h = d + i.shift(), f = m + i.shift(), g = h + i.shift(), x = f + i.shift(), k = g + i.shift(), v = x + i.shift(), y = k + i.shift(), b = v + i.shift(), w = y + i.shift(), p = b + i.shift(), d = w + i.shift(), i.shift(), e.U.P.curveTo(r, m, h, f, g, x, k), e.U.P.curveTo(r, v, y, b, w, p, d)), "o1236" == A && (m = p + i.shift(), h = d + i.shift(), f = m + i.shift(), k = g = h + i.shift(), y = g, b = (v = (x = f + i.shift()) + i.shift()) + i.shift(), w = y + i.shift(), p = b + i.shift(), e.U.P.curveTo(r, m, h, f, g, x, k), e.U.P.curveTo(r, v, y, b, w, p, d)), "o1237" == A && (m = p + i.shift(), h = d + i.shift(), f = m + i.shift(), g = h + i.shift(), x = f + i.shift(), k = g + i.shift(), v = x + i.shift(), y = k + i.shift(), b = v + i.shift(), w = y + i.shift(), Math.abs(b - p) > Math.abs(w - d) ? p = b + i.shift() : d = w + i.shift(), e.U.P.curveTo(r, m, h, f, g, x, k), e.U.P.curveTo(r, v, y, b, w, p, d)); else if ("o14" == A) { if (i.length > 0 && !o && (l = i.shift() + a.nominalWidthX, o = true), 4 == i.length) { var E = i.shift(), U = i.shift(), $ = i.shift(), H = i.shift(), P = e.CFF.glyphBySE(a, $), L = e.CFF.glyphBySE(a, H); e.U._drawCFF(a.CharStrings[P], n, a, r), n.x = E, n.y = U, e.U._drawCFF(a.CharStrings[L], n, a, r); } c && (e.U.P.closePath(r), c = false); } else if ("o19" == A || "o20" == A) { i.length % 2 != 0 && !o && (l = i.shift() + a.Private.nominalWidthX), s += i.length >> 1, i.length = 0, o = true, u += s + 7 >> 3; } else if ("o21" == A) i.length > 2 && !o && (l = i.shift() + a.Private.nominalWidthX, o = true), d += i.pop(), p += i.pop(), c && e.U.P.closePath(r), e.U.P.moveTo(r, p, d), c = true; else if ("o22" == A) i.length > 1 && !o && (l = i.shift() + a.Private.nominalWidthX, o = true), p += i.pop(), c && e.U.P.closePath(r), e.U.P.moveTo(r, p, d), c = true; else if ("o25" == A) { for (;i.length > 6; ) p += i.shift(), d += i.shift(), e.U.P.lineTo(r, p, d); m = p + i.shift(), h = d + i.shift(), f = m + i.shift(), g = h + i.shift(), p = f + i.shift(), d = g + i.shift(), e.U.P.curveTo(r, m, h, f, g, p, d); } else if ("o26" == A) for (i.length % 2 && (p += i.shift()); i.length > 0; ) m = p, h = d + i.shift(), p = f = m + i.shift(), d = (g = h + i.shift()) + i.shift(), e.U.P.curveTo(r, m, h, f, g, p, d); else if ("o27" == A) for (i.length % 2 && (d += i.shift()); i.length > 0; ) h = d, f = (m = p + i.shift()) + i.shift(), g = h + i.shift(), p = f + i.shift(), d = g, e.U.P.curveTo(r, m, h, f, g, p, d); else if ("o10" == A || "o29" == A) { var M = "o10" == A ? a.Private : a; if (0 == i.length) console.log("error: empty stack"); else { var j = i.pop(), O = M.Subrs[j + M.Bias]; n.x = p, n.y = d, n.nStems = s, n.haveWidth = o, n.width = l, n.open = c, e.U._drawCFF(O, n, a, r), p = n.x, d = n.y, s = n.nStems, o = n.haveWidth, l = n.width, c = n.open; } } else if ("o30" == A || "o31" == A) { var z = i.length, D = (I = 0, "o31" == A); for (I += z - (_ = -3 & z); I < _; ) D ? (h = d, f = (m = p + i.shift()) + i.shift(), d = (g = h + i.shift()) + i.shift(), _ - I == 5 ? (p = f + i.shift(), I++) : p = f, D = false) : (m = p, h = d + i.shift(), f = m + i.shift(), g = h + i.shift(), p = f + i.shift(), _ - I == 5 ? (d = g + i.shift(), I++) : d = g, D = true), e.U.P.curveTo(r, m, h, f, g, p, d), I += 4; } else { if ("o" == (A + "").charAt(0)) throw console.log("Unknown operation: " + A, t), A; i.push(A); } } } n.x = p, n.y = d, n.nStems = s, n.haveWidth = o, n.width = l, n.open = c; }, tt = e; }()), decode = async () => { var e; const t = ie.document.querySelectorAll("style"); let n = null; if (t.forEach((e => { var t; -1 !== (null == (t = e.textContent) ? void 0 : t.indexOf("font-cxsecret")) && (n = e); })), !n) return true; const a = null == (e = n.textContent) ? void 0 : e.match(/base64,([\w\W]+?)'/); if (!a) return; const r = base64ToUint8Array(a[1]), i = at.parse(r); let s = await ttfDownloadJson("https://www.forestpolice.org/ttf/2.0/table.json") || await ttfDownloadJson("https://jsd.vxo.im/gh/chengbianruan/staticfile/c.json") || await ttfDownloadJson("https://cdn.jsdelivr.net/gh/chengbianruan/staticfile/c.json"); if (!s) return false; let o = {}; for (let l = 19968; l < 40870; l++) { let e = at.U.codeToGlyph(i, l); e && (e = at.U.glyphToPath(i, e), e = somd5(JSON.stringify(e)).slice(24), o[l] = s[e]); } return ie.document.querySelectorAll(".font-cxsecret").forEach((e => { let t = e.innerHTML; Object.keys(o).forEach((e => { const n = new RegExp(String.fromCharCode(e), "g"); t = t.replace(n, String.fromCharCode(o[e])); })), e.innerHTML = t, e.classList.remove("font-cxsecret"); })), true; }, base64ToUint8Array = e => { const t = atob(e), n = new Uint8Array(t.length); for (let a = 0; a < t.length; a++) n[a] = t.charCodeAt(a); return n; }, cleanChaoxingQuestionLiTitle = (e, t, n) => { const a = e || "", r = t || ""; return n(r && a.includes(r) ? a.split(r).slice(1).join(r).trim() : a).trim(); }, getChaoxingAnswerIndex = e => { const t = (e || "").trim().toUpperCase(); if (/^[A-Z]$/.test(t)) return t.charCodeAt(0) - 65; if (/^\d+$/.test(t)) { const e = Number.parseInt(t, 10) - 1; return e >= 0 ? e : null; } return null; }, mapChaoxingChoiceLettersToOptions = (e, t) => (e || "").trim().toUpperCase().split("").map((e => { const n = getChaoxingAnswerIndex(e); return null == n ? void 0 : t[n]; })).filter((e => void 0 !== e && "" !== e)), normalizeChaoxingSubjectiveAnswer = (e, t = 10) => { const n = (e || "").replace("\u6b63\u786e\u7b54\u6848\uff1a", "").trim(); return n.length < t ? null : [ n ]; }, getChaoxingExamOutLinkTarget = e => { let t; try { t = new URL(e); } catch { return ""; } if ("i.mooc.chaoxing.com" !== t.hostname) return ""; if (!t.pathname.includes("/space/out_link.shtml")) return ""; const n = t.searchParams.get("burl"); if (!n) return ""; try { const e = new URL(n), t = "chaoxing.com" === e.hostname || e.hostname.endsWith(".chaoxing.com"), a = e.pathname.includes("/exam-ans/exam/test/"); return t && a ? e.href : ""; } catch { return ""; } }, getChaoxingReviewLayout = e => e.querySelector(".TiMu .newAnswerBx") ? "modern" : e.querySelector(".TiMu .Py_answer, .TiMu .Py_tk") ? "classic" : null, redirectCurrentChaoxingExamOutLink = () => { ((e, t) => { const n = getChaoxingExamOutLinkTarget(e); !!n && t(n); })(location.href, (e => { ie.location.href = e; })); }, rt = [ { type: "hook", name: "\u5b66\u4e60\u901a\u8003\u8bd5\u5916\u94fe\u8df3\u8f6c", match: () => "" !== getChaoxingExamOutLinkTarget(location.href), hook: redirectCurrentChaoxingExamOutLink, main: redirectCurrentChaoxingExamOutLink }, { type: "ask", name: "\u5b66\u4e60\u901a\u968f\u5802\u7ec3\u4e60", match: () => location.href.includes("/page/quiz/stu/answerQuestion2"), types: [ "0", "1", "2", "3", "4", "5", "6", "7", "9" ], minDelay: 100, answerDelay: 1e3, question: { html: ".left-question-list>.question-item", question: ".html-content-box", options: "ul.option-list>li", type: ".grey-text", workType: "stlx", pageType: "cx" }, init: async () => {}, ischecked: isParentChecked, questionHook: e => (e.options = removeStartChar(e.options), e.type = typeMatch(O(e.html).find(".grey-text").text()), e) }, { type: "save", name: "\u5b66\u4e60\u901a\u8003\u8bd5\u65b0\u7248\u6536\u5f55", match: () => location.href.includes("work/view") || location.href.includes("test/reVersionPaperMarkContentNew"), question: { html: ".questionLi", question: "h3.mark_name", options: "ul.mark_letter.colorDeep > li", type: ".colorShallow", workType: "zj", pageType: "cx" }, answerHook: e => { let t = removeHtml(O(e.html).find('span[class="colorShallow"]').html()); if ("" === t) return null; let n = t.match(/^\((.+?)\)/); if (null === n) return null; e.type = n[1].split(",")[0], e.question = titleClean(e.question.split(t)[1].trim()).trim(), e.options = removeStartChar(e.options); const a = O(e.html).find(".mark_score>.totalScore>i").text(), r = t.match(/(\d+(\.\d+)?)/); let i, s = O(e.html).find(".marking_dui").length > 0 || Number(a) == ((null == r ? void 0 : r[0]) || 0) && 0 != Number(a), o = typeMatch(t); if (!s) switch (o) { case "0": case "1": case "3": 0 != Number(a) && (s = true); } switch (o) { case "0": case "1": e.type = o, e.answer = mapChaoxingChoiceLettersToOptions(O(e.html).find(".mark_answer>div>span.colorGreen:eq(0)").text().replace("\u6b63\u786e\u7b54\u6848:", ""), e.options), 0 === e.answer.length && s && (e.answer = mapChaoxingChoiceLettersToOptions(O(e.html).find(".mark_answer>div>span.colorDeep:eq(0)").text().replace("\u6211\u7684\u7b54\u6848:", ""), e.options)); break; case "3": if (e.type = "3", e.options = [], e.answer = judgeAnswer(O(e.html).find(".mark_answer>div>span.colorGreen:eq(0)").text().replace("\u6b63\u786e\u7b54\u6848", "")), e.answer, 0 === e.answer.length) { if (i = removeHtml(O(e.html).find(".mark_answer>div>span.colorDeep:eq(0)").html()), e.answer = judgeAnswer(i), 0 === e.answer.length) return null; if (0 == Number(a) && !s && "3" == o) return null; s || (e.answer = "\u6b63\u786e" === e.answer[0] ? [ "\u9519\u8bef" ] : [ "\u6b63\u786e" ]); } break; case "4": if (e.type = "4", e.answer = normalizeChaoxingSubjectiveAnswer(removeHtml(O(e.html).find(".mark_answer>div>.colorGreen:eq(0)").html())), null == e.answer) return null; break; case "5": if (e.type = "5", e.answer = normalizeChaoxingSubjectiveAnswer(removeHtml(O(e.html).find(".mark_answer>div>.colorGreen:eq(0)").html())), null == e.answer) return null; break; case "7": if (e.type = "7", e.answer = normalizeChaoxingSubjectiveAnswer(removeHtml(O(e.html).find(".mark_answer>div>.colorGreen:eq(0)").html())), null == e.answer) return null; break; case "6": if (e.type = "6", e.answer = normalizeChaoxingSubjectiveAnswer(removeHtml(O(e.html).find(".mark_answer>div>.colorGreen:eq(0)").html())), null == e.answer) return null; break; case "2": if (e.type = "2", e.answer = O(e.html).find(".mark_answer>div>.colorGreen:eq(0)>dd").map(((e, t) => removeHtml(O(t).html()).replace(`(${e + 1})`, "").trim())).get(), 0 == e.answer.length) { const t = O(e.html).find(".mark_answer>div>.colorDeep:eq(0)>dd").map(((e, t) => removeHtml(O(t).html()).replace(`(${e + 1})`, "").trim())).get(); O(e.html).find(".mark_answer>div>.colorDeep:eq(0)>dd>.marking_dui").length == t.length && (e.answer = t); } break; default: return null; } return e; }, paper: async e => { const t = { platform: "cx" }, n = O("#courseId").val(), a = (ie.document.body.innerHTML.match(/(?:examId|relationId)=(\d+)/) || [])[1] || "", r = `https://mobilelearn.chaoxing.com/v2/apis/class/getClassDetail?courseId=${n}&classId=${O("#classId").val()}`; await request(r, "GET").then((e => { const n = JSON.parse(e[0].responseText).data.course.data[0]; t.name = n.name, t.info = {}, t.info.imageurl = n.imageurl; })), t.hash = n, t.info = {}, t.chapter = [ { hash: `${a}`, name: O(".mark_title").text().trim(), question: e } ], et.setPaper(t.hash, t); } }, { type: "save", name: "\u5b66\u4e60\u901a\u7ecf\u5178\u4f5c\u4e1a\u6536\u5f55", match: () => /\/work\/selectWorkQuestionYiPiYue$/.test(location.pathname) && "classic" === getChaoxingReviewLayout(document), question: { html: ".TiMu", question: ".Zy_TItle > .clearfix > div:first-child", options: "ul.Zy_ulTop > li > a.fl", type: ".newZy_TItle", workType: "zj", pageType: "cx" }, answerHook: e => { const t = ((e, t) => { var n, a, r, i, s, o, l; let c = "", u = e.previousElementSibling; for (let x = 200; u && x > 0; x--) { if (u.matches(".Cy_TItle1")) { c = (null == (n = u.textContent) ? void 0 : n.trim()) || ""; break; } u = u.previousElementSibling; } const p = null == (a = c.match(/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\d]+[.\u3001\uff0e]\s*(\u5355\u9009\u9898|\u591a\u9009\u9898|\u5224\u65ad\u9898|\u586b\u7a7a\u9898|\u7b80\u7b54\u9898)/)) ? void 0 : a[1]; if (!p) return null; const d = e.querySelector(".Zy_TItle > .clearfix > div:first-child"), m = d ? cleanQuestionTitle(t(d.innerHTML)) : ""; if (!m) return null; if ("\u586b\u7a7a\u9898" === p || "\u7b80\u7b54\u9898" === p) { const n = Array.from(e.querySelectorAll(":scope > .Py_tk")).filter((e => { var t; return /^\s*\u6b63\u786e\u7b54\u6848\s*[:\uff1a]\s*$/.test((null == (t = e.querySelector(":scope > p")) ? void 0 : t.textContent) || ""); })), a = n[0]; if (1 !== n.length || !a) return null; const s = Array.from(a.querySelectorAll(":scope > div > span.font14")); if (0 === s.length || s.length > 64 || "\u7b80\u7b54\u9898" === p && 1 !== s.length) return null; if ("\u586b\u7a7a\u9898" === p && e.querySelectorAll(":scope > .Py_answer > div > div.font14").length !== s.length) return null; const o = []; for (const [e, l] of s.entries()) { let n = l; if ("\u586b\u7a7a\u9898" === p) { const t = e + 1, a = "\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d", s = t < 10 ? a[t - 1] : `${t < 20 ? "" : a[Math.floor(t / 10) - 1]}\u5341${t % 10 ? a[t % 10 - 1] : ""}`; if ((null == (i = null == (r = l.querySelector(":scope > i")) ? void 0 : r.textContent) ? void 0 : i.trim()) !== `\u7b2c${s}\u7a7a\uff1a`) return null; const o = l.querySelectorAll(":scope > div"), c = o[0]; if (1 !== o.length || !c) return null; n = c; } const a = t(n.innerHTML).trim(); if (!a || a.length > 4e3) return null; o.push(a); } return { question: m, options: [], type: "\u586b\u7a7a\u9898" === p ? "2" : "4", answer: o }; } const h = Array.from(e.querySelectorAll(".Py_answer > span")).map((e => { var t; return (null == (t = e.textContent) ? void 0 : t.trim()) || ""; })).filter((e => /^\u6b63\u786e\u7b54\u6848\s*[:\uff1a]/.test(e))); if (1 !== h.length) return null; const f = h[0].replace(/^\u6b63\u786e\u7b54\u6848\s*[:\uff1a]\s*/, "").trim(); if ("\u5224\u65ad\u9898" === p) return /^(\u6b63\u786e|\u9519\u8bef|\u5bf9|\u9519|\u221a|\xd7)$/.test(f) ? { question: m, options: [], type: "3", answer: judgeAnswer(f) } : null; const g = Array.from(e.querySelectorAll("ul.Zy_ulTop > li")); if (g.length < 2 || g.length > 26) return null; const v = [], y = new Map; for (const x of g) { const e = null == (l = null == (o = null == (s = x.querySelector("i.fl")) ? void 0 : s.textContent) ? void 0 : o.trim().match(/^([A-Z])[\u3001.\uff0e]$/)) ? void 0 : l[1], n = x.querySelector("a.fl"), a = n ? t(n.innerHTML).trim() : ""; if (!e || !a || y.has(e)) return null; v.push(a), y.set(e, a); } if (!/^[A-Z](?:[\s,\uff0c\u3001;\uff1b]*[A-Z])*$/.test(f)) return null; const b = f.replace(/[\s,\uff0c\u3001;\uff1b]/g, "").split(""); if ("\u5355\u9009\u9898" === p && 1 !== b.length || new Set(b).size !== b.length) return null; const w = []; for (const x of b) { const e = y.get(x); if (!e) return null; w.push(e); } return { question: m, options: v, type: "\u5355\u9009\u9898" === p ? "0" : "1", answer: w }; })(e.html, removeHtml); return t ? { ...e, ...t } : null; } }, { type: "hook", name: "hook", match: () => location.href.includes("work/selectWorkQuestionYiPiYue") && location.href.includes("mooc2=0") && "classic" !== getChaoxingReviewLayout(document), main: e => { location.href.includes("mooc2=0") ? ie.location.href = location.href.replace("mooc2=0", "mooc2=1") : ie.location.href = location.href + "&mooc2=1"; } }, { type: "save", name: "\u5b66\u4e60\u901a\u4f5c\u4e1a\u6536\u5f55\u65b0", match: () => location.href.includes("work/selectWorkQuestionYiPiYue") && "modern" === getChaoxingReviewLayout(document), question: { html: ".TiMu", question: ".Zy_TItle .clearfix", options: "ul.Zy_ulTop li", type: ".newZy_TItle", workType: "zj", pageType: "cx" }, answerHook: e => { e.type = O(e.html).find(".newZy_TItle").text().replace(/\u3010|\u3011/g, "").trim(); let t, n = O(e.html).find(".marking_dui").length > 0; switch (removeHtml(O(e.html).find(".Py_addpy:eq(0)").html()), e.question = titleClean(e.question).trim(), e.type) { case "\u5355\u9009\u9898": case "\u591a\u9009\u9898": e.type = "\u5355\u9009\u9898" === e.type ? "0" : "1", e.options = O(e.html).find("ul.Zy_ulTop li").map(((e, t) => { let n = O(t).find("i.fl").text().trim(), a = removeHtml(O(t).html()); return "" === n ? a.trim() : removeKnownOptionPrefix(a, n); })).get(), e.answer = mapChaoxingChoiceLettersToOptions(O(e.html).find(".correctAnswer >.fl.answerCon").text(), e.options), 0 === e.answer.length && n && (e.answer = mapChaoxingChoiceLettersToOptions(O(e.html).find(".myAnswer > .fl.answerCon").text(), e.options)); break; case "\u5224\u65ad\u9898": if (e.type = "3", e.answer = O(e.html).find(".correctAnswer > .fl.answerCon").text().trim().split("").map((e => e.includes("\u6b63\u786e") || e.includes("\u5bf9") || e.includes("\u221a") ? "\u6b63\u786e" : e.includes("\u9519\u8bef") || e.includes("\u9519") || e.includes("\xd7") ? "\u9519\u8bef" : null)).filter((e => null !== e)), 0 === e.answer.length) { t = removeHtml(O(e.html).find(".fl.answerCon").html()); let [n, a] = [ ".marking_dui", ".marking_cuo" ].map((t => O(e.html).find(t).length)); if (n + a === 0) return null; if (t.includes("\u6b63\u786e") || t.includes("\u5bf9") || t.includes("\u221a")) e.answer = [ "\u6b63\u786e" ]; else { if (!(t.includes("\u9519\u8bef") || t.includes("\u9519") || t.includes("\xd7"))) return null; e.answer = [ "\u9519\u8bef" ]; } 0 === n && 0 !== a && (e.answer = "\u6b63\u786e" === e.answer[0] ? "\u9519\u8bef" : "\u6b63\u786e"); } break; case "\u586b\u7a7a\u9898": e.type = "2", e.answer = O(e.html).find(".correctAnswerBx>.correctAnswer>p:not(.clear)").map(((e, t) => removeHtml(O(t).html()).replace(`(${e + 1})`, "").trim())).get().filter((e => "" !== e)), 0 == e.answer.length && (e.answer = O(e.html).find(".myAllAnswerBx>.myAnswerBx>.myAnswer").map(((e, t) => removeHtml(O(t).html()).replace(/\u7b2c[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d]+\u7a7a\uff1a/, "").trim())).get(), e.answer.length !== O(e.html).find(".marking_dui").length && (e.answer = [])); break; case "\u5206\u5f55\u9898": if (e.type = "9", e.answer = O(e.html).find(".correctAnswerBx>.correctAnswer>p:not(.clear)").map(((e, t) => removeHtml(O(t).html()))).get().filter((e => "" !== e)), e.answer.length != O(e.html).find(".CorrectOrNot").length) { if (O(e.html).find(".marking_cuo").length > 0) return null; if (e.answer = O(e.html).find(".myAnswerBx>.myAnswer>p:not(.clear)").map(((e, t) => removeHtml(O(t).html()))).get().filter((e => "" !== e)), e.answer.length != O(e.html).find(".CorrectOrNot").length) return null; } e.answer; break; case "\u8fde\u7ebf\u9898": e.type = "11"; let a = O(e.html).find("ul.firstUlList>li:not(.groupTitile)").map(((e, t) => { let n = O(t).clone(); return n.find(".fl").remove(), removeHtml(n.html()); })).get(), r = O(e.html).find("ul.secondUlList>li:not(.groupTitile)").map(((e, t) => { let n = O(t).clone(); return n.find(".fl").remove(), removeHtml(n.html()); })).get(); t = O(e.html).find(".correctAnswer >.fl.answerCon >.collectAnswer").map(((e, t) => removeHtml(O(t).text()))).get(), e.options = [ a, r ]; let i = {}; t.forEach((e => { let [t, n] = e.split("-"); const s = getChaoxingAnswerIndex(t), o = getChaoxingAnswerIndex(n); null != s && null != o && null != a[s] && null != r[o] && (i[a[s]] = r[o]); })), e.answer = i, e.answer; break; case "\u9009\u62e9\u9898": { const t = O(e.html).find("ul.Zy_ulTop > li"); if (0 === t.length) return null; const n = O(e.html).find(".correctAnswerBx .correctAnswer .answerCon").text(), a = {}; for (const e of n.matchAll(/\((\d+)\)\s*([A-Z]+)/g)) a[parseInt(e[1], 10)] = e[2]; const r = []; let i = false; if (t.each(((e, t) => { if (i) return; const n = O(t).find("label.selectLabel span.selectItem > p").map(((e, t) => removeHtml(O(t).html()))).get(), s = a[e + 1], o = n.length && s ? mapChaoxingChoiceLettersToOptions(s, n) : []; 0 !== o.length ? r.push({ type: "0", question: `\u7b2c${e + 1}\u7a7a`, options: n, answer: o }) : i = true; })), i || 0 === r.length) return null; e.answer = r.map((e => e.answer)), e.options = r.map((({answer: e, ...t}) => t)), e.type = "15", e.answer; break; } case "\u9605\u8bfb\u7406\u89e3": const s = O(e.html).find(".readCompreHensionItem").map(((e, t) => { let n = typeMatch(O(t).find("i.index").text()), a = removeHtml(O(t).find(".clearfix").html()), r = O(t).find("ul.Zy_ulTop>li").map(((e, t) => removeHtml(O(t).html()))).get(); r = removeOptionsStartChar(r); let i = removeHtml(O(t).find(".correctAnswerBx>.correctAnswer>.answerCon").text()), s = []; switch (n) { case "0": case "1": s = mapChaoxingChoiceLettersToOptions(i, r); break; default: return null; } return 0 === s.length ? null : { type: n, question: a, options: r, answer: s }; })).get(); if (null == s || 0 == s.length) return null; e.answer = s.map((e => e.answer)), e.options = s.map((e => (delete e.answer, e))), e.type = "15"; break; default: return e.type, null; } return e; }, paper: async e => { const t = { platform: "cx" }, n = ie.courseId, a = ie.jobid, r = `https://mobilelearn.chaoxing.com/v2/apis/class/getClassDetail?courseId=${n}&classId=${ie.classId}`; await request(r, "GET").then((e => { const n = JSON.parse(e[0].responseText).data.course.data[0]; t.name = n.name, t.info = {}, t.info.imageurl = n.imageurl; })), t.hash = n, t.info = {}, t.chapter = [ { hash: `${a}`, name: O(".ceyan_name>h3").text().trim(), question: e } ], et.setPaper(t.hash, t); } }, { type: "ask", name: "\u5b66\u4e60\u901a\u65b0\u7248\u4f5c\u4e1a", match: () => /\/mooc2\/work\/dowork/i.test(location.pathname), types: [ "0", "1", "2", "3", "4", "5", "6", "7", "9" ], question: { html: ".questionLi", question: "h3", options: "ul:eq(0) li .after, .answer_p", type: "input[name^=answertype]:eq(0)", workType: "zy", pageType: "cx" }, questionHook: e => { const t = removeHtml(O(e.html).find(".colorShallow").html()); return e.question = cleanChaoxingQuestionLiTitle(e.question, t, titleClean), e.$options = O(e.html).find(".answerBg"), e; }, setAnswerHook: e => { qc(e.html), qc1(e.html); } }, { type: "ask", name: "\u5b66\u4e60\u901a\u65b0\u7248\u8003\u8bd5", match: () => /exam\/preview/i.test(location.pathname) || /exam\/test\/reVersionTestStartNew/i.test(location.pathname), types: [ "0", "1", "2", "3", "4", "5", "6", "7", "9" ], question: { html: ".questionLi", question: "h3", options: "ul:eq(0) li .after, .answer_p", type: "input[name^=type]:not([name=type])", workType: "ks", pageType: "cx" }, questionHook: e => { const t = removeHtml(O(e.html).find(".colorShallow").html()); if (e.question = cleanChaoxingQuestionLiTitle(e.question, t, titleClean), e.$options = O(e.html).find(".answerBg"), "3" === e.type) e.options = []; return e; }, setAnswerHook: e => { qc(e.html), qc1(e.html); }, next: () => { O('.nextDiv .jb_btn:contains("\u4e0b\u4e00\u9898")').click(); } }, { type: "ask", name: "\u5b66\u4e60\u901a\u65e7\u7248\u4f5c\u4e1a", match: () => /work\/doHomeWorkNew/i.test(location.pathname) && 0 == location.href.includes("mooc2=1"), types: [ "0", "1", "2", "3", "4", "5", "6", "7", "9" ], init: async () => { if (!(await decode())) return msg("\u9875\u9762\u89e3\u5bc6\u5931\u8d25\uff0c\u65e0\u6cd5\u7b54\u9898\uff0c\u8bf7\u5c1d\u8bd5\u5207\u6362\u7f51\u7edc\u6216\u53cd\u9988\u7ed9\u4f5c\u8005\u5427", "error"), false; }, question: { html: ".TiMu", question: ".clearfix.fontLabel", options: "ul:eq(0) li .after", type: "input[name^=answertype]:eq(0), .answer_p", workType: "zy", pageType: "cx" }, questionHook: e => { switch (e.question = titleClean(e.question).trim(), e.$options = O(e.html).find(".fl.before"), e.type) { case "3": e.options = O(e.html).find("ul:eq(0) li").map(((e, t) => O(t).find(".ri").length > 0 ? "\u6b63\u786e" : O(t).find(".wr").length > 0 ? "\u9519\u8bef" : isTrue(O(t).attr("aria-label") || "") ? "\u6b63\u786e" : isFalse(O(t).attr("aria-label") || "") ? "\u9519\u8bef" : void 0)).get(), e.$options = O(e.html).find("ul>li"); break; case "11": let t = O(e.html).find("ul.firstUlList>li:not(.groupTitile)").map(((e, t) => { let n = O(t).clone(); return n.find(".fl").remove(), removeHtml(n.html()); })).get(), n = O(e.html).find("ul.secondUlList>li:not(.groupTitile)").map(((e, t) => { let n = O(t).clone(); return n.find(".fl").remove(), removeHtml(n.html()); })).get(); e.options = [ t, n ], e.$options = O(e.html).find("ul.thirdUlList>li:not(.groupTitile)"); } return e; }, setAnswerHook: e => { qc(e.html), qc1(e.html); }, setAnswer: e => { switch (e.type) { case "11": return e.ques.$options.each(((t, n) => { var a, r, i; const s = null == (a = e.ques.options) ? void 0 : a[0], o = null == (r = e.ques.options) ? void 0 : r[1], l = null == (i = e.answer) ? void 0 : i[null == s ? void 0 : s[t]], c = Array.isArray(o) ? o.indexOf(l) : -1; if (c < 0) return void (null == s || s[t]); const u = String.fromCharCode(c + 65), p = O(n).find("select"); p.find("option").each(((e, t) => { O(t).prop("selected", O(t).val() == u); })), p.val(u).trigger("change"); })), e.answer, false; case "3": let t = e.answer; return e.ques.$options.each(((e, n) => { isTrue(t) && (isTrue(removeHtml(O(n).html())) || O(n).find(".ri").length > 0) && O(n).find("input").click(), isFalse(t) && (isFalse(removeHtml(O(n).html())) || O(n).find(".wr").length > 0) && O(n).find("input").click(); })), false; default: return true; } } }, { type: "ask", name: "\u5b66\u4e60\u901a\u65b0\u7248\u7ae0\u8282", match: () => /work\/doHomeWorkNew/i.test(location.pathname) && location.href.includes("mooc2=1"), types: [ "0", "1", "2", "3", "4", "5", "6", "7", "9" ], init: async () => { if (!(await decode())) return msg("\u9875\u9762\u89e3\u5bc6\u5931\u8d25\uff0c\u65e0\u6cd5\u7b54\u9898\uff0c\u8bf7\u5c1d\u8bd5\u5207\u6362\u7f51\u7edc\u6216\u53cd\u9988\u7ed9\u4f5c\u8005\u5427", "error"), false; }, question: { html: ".TiMu", question: ".clearfix.fontLabel", options: "ul:eq(0) li .after, .answer_p", type: "input[name^=answertype]:eq(0)", workType: "zj", pageType: "cx" }, questionHook: e => { switch (e.question = titleClean(e.question).trim(), e.type) { case "3": e.options = O(e.html).find("ul:eq(0) li").map(((e, t) => "true" === O(t).find(".num_option").attr("data") ? "\u6b63\u786e" : "false" === O(t).find(".num_option").attr("data") ? "\u9519\u8bef" : void 0)).get(), e.options = []; break; case "11": let t = O(e.html).find("ul.firstUlList>li:not(.groupTitile)").map(((e, t) => { let n = O(t).clone(); return n.find(".fl").remove(), removeHtml(n.html()); })).get(), n = O(e.html).find("ul.secondUlList>li:not(.groupTitile)").map(((e, t) => { let n = O(t).clone(); return n.find(".fl").remove(), removeHtml(n.html()); })).get(); e.options = [ t, n ], e.$options = O(e.html).find("ul.thirdUlList>li:not(.groupTitile)"); break; case "15": const a = O(e.html).find(".readCompreHensionItem").map(((e, t) => { let n = typeMatch(O(t).find("i.index").text()), a = removeHtml(O(t).find(".clearfix").html()), r = O(t).find("ul.Zy_ulTop>li").map(((e, t) => removeHtml(O(t).html()))).get(); return r = removeOptionsStartChar(r), { type: n, question: a, options: r, $options: O(t).find("ul.Zy_ulTop>li") }; })).get(); if (null == a || 0 == a.length) return null; e.options = a, e.$options = null; break; case "14": const r = O(e.html).find("ul.Zy_ulTop").map(((e, t) => { const n = O(t).children("li"); return { type: "0", question: `\u7b2c${e + 1}\u7a7a`, options: n.map(((e, t) => { const n = O(t).find(".after").html(); return removeHtml(null != n ? n : O(t).html()); })).get(), $options: n }; })).get(); if (null == r || 0 === r.length) return null; e.options = r, e.$options = null, e.type = "15"; break; default: e.type; } return e; }, setAnswerHook: e => { qc(e.html), qc1(e.html); }, setAnswer: e => (e.ques.options, "11" !== e.type || (e.ques.$options.each(((t, n) => { var a, r, i; const s = null == (a = e.ques.options) ? void 0 : a[0], o = null == (r = e.ques.options) ? void 0 : r[1], l = null == (i = e.answer) ? void 0 : i[null == s ? void 0 : s[t]], c = Array.isArray(o) ? o.indexOf(l) : -1; if (c < 0) return void (null == s || s[t]); const u = String.fromCharCode(c + 65); let p = ie.$(n).find(".dept_select"); p.val(u).trigger("change"), p.chosen().val(u).trigger("chosen:updated"); })), e.answer, false)) } ], extractZhihuishuExamQuestions = e => (e => { var t, n, a; return (null == (n = null == (t = null == e ? void 0 : e.rt) ? void 0 : t.examBase) ? void 0 : n.workExamParts) || (null == (a = null == e ? void 0 : e.examBase) ? void 0 : a.workExamParts) || (null == e ? void 0 : e.workExamParts) || []; })(e).flatMap((e => e.questionDtos || [])).filter((e => Boolean(e))), it = [ { type: "ask", name: "\u667a\u6167\u6811\u7ae0\u8282", tips: "\u667a\u6167\u6811\u5fc5\u987b\u5f00\u81ea\u52a8\u8df3\u8f6c\uff0c\u5426\u5219\u7b54\u6848\u53ef\u80fd\u65e0\u6cd5\u4fdd\u5b58\u5bfc\u81f4\u4f4e\u5206\uff01", match: () => location.href.includes("zhihuishu.com") && !location.href.includes("checkHomework") && location.host.includes("zhihuishu") && ("/stuExamWeb.html" === location.pathname || location.href.includes("/webExamList/dohomework/") || location.href.includes("/webExamList/doexamination/")), types: [ "0", "1", "2", "3" ], question: { html: ".examPaper_box > div:eq(1) >div:not(.examPaper_partTit)", question: ".subject_describe.dynamic-fonts:eq(0) div:eq(0)", options: ".subject_node .nodeLab .label.clearfix .node_detail", type: ".subject_type span:first-child", workType: "zhs", pageType: "zhs" }, init: async () => { await waitUntil((function() { return !O(".yidun_popup").hasClass("yidun_popup--light") && extractZhihuishuExamQuestions(ie.zhsques).length > 0; })); }, next: () => { O(".switch-btn-box button:eq(1)").click(); }, questionHook: (e, t) => { const n = extractZhihuishuExamQuestions(ie.zhsques)[t]; if (!n) return e; const a = (e => { var t; const n = typeConvert((null == (t = e.questionType) ? void 0 : t.name) || e.questionTypeName || e.typeName || ""), a = e.questionOptions || e.options || [], r = "3" === n ? [] : removeStartChar(a.map((e => removeHtml(e.content || "")))); return { question: removeHtml(e.name || e.questionStem || e.questionName || ""), type: n, options: r }; })(n); return e.type = a.type, e.question = a.question, e.options = a.options, e; } }, { type: "save", name: "\u667a\u6167\u6811\u4f5c\u4e1a\u6536\u5f55", match: () => location.href.includes("zhihuishu.com") && location.href.includes("checkHomework") && location.host.includes("zhihuishu") && ("/stuExamWeb.html" === location.pathname || location.href.includes("/webExamList/checkHomework/")), question: { html: ".questionType", question: ".subject_describe", options: ".examquestions-answer", type: ".newZy_TItle", workType: "zhs", pageType: "zhs" }, init: async () => { await waitUntil((function() { return O(".questionType").length > 0 && O(".questionType:eq(0)")[0].__vue__.answerImgMap; })); }, answerHook: e => { const t = O(e.html)[0].__vue__, n = t.answerData[t.data.id], a = "1" === n.isCurrent ? n.answer.split(",") : [], r = t.data, i = t.answerImgMap[t.data.id] || ""; t.answerImgMap, t.data.id, somd5(i), e.type = typeMatch(r.questionType.name); const s = []; if (e.options = r.questionOptions.map((e => (a.includes(String(e.id)) && s.push(removeHtml(e.content)), removeHtml(e.content)))), e.answer = s, "3" === e.type) { e.options = []; const t = e.answer[0]; e.answer = isTrue(t) ? [ "\u6b63\u786e" ] : isFalse(t) ? [ "\u9519\u8bef" ] : []; } return e; } }, { type: "save", name: "\u667a\u6167\u6811\u8003\u8bd5\u6536\u5f55", match: () => location.href.includes("zhihuishu.com") && location.href.includes("/atHomeworkExam/stu/examQ/doExamnew"), question: { html: ".subjecttype-div.clearfloat", question: ".subjectTitle-p", options: ".TitleOptions-div label", type: ".subjecttopic-div", workType: "zhs", pageType: "zhs" }, init: async () => { await waitUntil((function() { return O(".subjecttype-div.clearfloat").length > 0; })); }, answerHook: e => { const t = O(e.html).find(".Referenceanswer-div.clearFloat>.Referenceanswer-r.fl").text(); return e.question = removeHtml(e.question), e.options = removeStartChar(e.options), e.type = typeMatch(O(e.html).find(".subjecttopic-div").text()), e.answer = t.split("").map((t => e.options[t.charCodeAt(0) - 65])), "3" == e.type && (e.options = [], e.answer = isTrue(e.answer[0]) ? [ "\u6b63\u786e" ] : isFalse(e.answer[0]) ? [ "\u9519\u8bef" ] : []), e; } } ], st = [ { type: "hook", name: "\u82af\u4f4d\u6559\u80b2hook", match: "www.beeline-ai.com" === location.host, main: async e => { const getPageIdentifier = () => O(".el-main > div:eq(0)").attr("class"); ie.mainClass = getPageIdentifier(); const t = new MutationObserver((async e => { const n = getPageIdentifier(); ie.mainClass !== n && (ie.mainClass = n, "homework-detail-container" === n && await waitUntil((() => 0 === O(".el-loading-mask").length)), vuePageChange(), t.disconnect()); for (const a of e) if ("attributes" === a.type && "class" === a.attributeName) { const e = a.target.textContent; if (e && (e.includes("\u4e0b\u4e00\u9898") || e.includes("\u4e0a\u4e00\u9898"))) { vuePageChange(), t.disconnect(); break; } } })); O("body").length >= 1 && t.observe(O("body")[0], { subtree: true, attributes: true, childList: true }); } }, { type: "ask", name: "\u82af\u4f4d\u6559\u80b2\u4f5c\u4e1a", tips: "\u82af\u4f4d\u6559\u80b2\u4ec5\u652f\u6301\u9009\u62e9\u5224\u65ad\uff0c\u5176\u4ed6\u9898\u578b\u5f85\u9002\u914d", match: () => "www.beeline-ai.com" === location.host && (/student\/#\/courseInfo\/[A-Za-z0-9]+\/homework/i.test(location.href) || /student\/#\/courseInfo\/[A-Za-z0-9]+\/exam/i.test(location.href)), types: [ "0", "1", "3" ], question: { html: ".content-area > div.content", question: ".content", options: ".el-radio-group label .label,.el-checkbox-group label .label", type: ".question-box .tag", workType: "xinwei", pageType: "xinwei" }, init: async () => { await waitUntil((function() { return 0 !== O(".question-box").length; })); }, next: () => { O('.toggle-box > button:contains("\u4e0b\u4e00\u9898")').click(); }, ischecked: isParentChecked, questionHook: e => (e.type = typeMatch(O(e.html).find(".question-box>.tag").text()), e) }, { type: "save", name: "\u82af\u4f4d\u6559\u80b2\u6536\u5f55", match: () => "www.beeline-ai.com" === location.host && location.href.includes("/homeworkDetailPage"), question: { html: ".question-content-body", question: ".topic-title", options: ".el-radio-group label .label,.el-checkbox-group label .label", type: ".question-box .tag", workType: "xinwei", pageType: "xinwei" }, init: async () => { await waitUntil((function() { return 0 !== O(".question-content-body").length; })); }, answerHook: e => { e.type = typeMatch(O(e.html).find(".question-box>.tag").text()); let t = O(e.html).find(".answer-area > span:eq(1)").text(); switch (e.type) { case "0": case "1": let n = t.split(","); if (e.answer = n.map((t => e.options[t.charCodeAt(0) - 65])), 0 === e.answer.length) return; break; case "3": "T" == t && (e.answer = [ "\u6b63\u786e" ]), "F" == t && (e.answer = [ "\u9519\u8bef" ]); } return e; } } ], mergeMoodleReviewQuestionContext = (e, t) => { const n = e.trim(), a = t.trim(); return n && /^[\uff08(]\d+(?:\.\d+)*[)\uff09]/.test(a) ? `${n}\n${a}` : a; }, ot = { single_selection: "\u5355\u9009\u9898", multiple_selection: "\u591a\u9009\u9898", true_or_false: "\u5224\u65ad\u9898", fill_in_blank: "\u586b\u7a7a\u9898", short_answer: "\u7b80\u7b54\u9898", text: "\u6587\u672c", analysis: "\u7efc\u5408\u9898", matching: "\u5339\u914d\u9898", random: "\u968f\u673a\u9898", cloze: "\u5b8c\u5f62\u586b\u7a7a\u9898" }, buildAnalysisSubQuestion = e => { if (!e || "text" === e.type || "analysis" === e.type) return null; const t = parseFloat(e.point), n = parseFloat(e.score), a = 0 !== t && t === n; let r = false, i = []; if (e.correctOptions && e.correctOptions.length > 0 && (i = e.correctOptions.map((e => removeHtml(e.content))), r = true), e.correct_answers && e.correct_answers.length > 0 && (i = e.correct_answers.map((e => e.content)), r = true), !r && !a) return null; if (!r) if ("single_selection" === e.type || "multiple_selection" === e.type || "true_or_false" === e.type) { if (i = (e.options || []).filter((e => e.isChosen)).map((e => removeHtml(e.content))), 0 === i.length) return null; } else { if ("fill_in_blank" !== e.type) return null; if (i = (e.answers || []).map((e => e.content)), 0 === i.length) return null; } const s = O(`
    ${e.description || ""}
    `).clone(); s.find("span.__blank__").remove(); const o = removeHtml(s.html()); let l = (e.options || []).map((e => removeHtml(e.content))); const c = typeConvert(ot[e.type]); return "true_or_false" === e.type && (i = judgeAnswer(i[0]), l = [], 0 === i.length) ? null : { type: c, question: o, options: l, answer: i }; }, lt = [ { type: "hook", name: "\u56fd\u5f00hook", match: location.host.includes("ouchn.cn"), main: e => { observeVuePageChange(O("body")[0], getUrl, { beforeChange: async e => { "homework-detail-container" === e && await waitUntil((function() { return 0 !== O(".selectDan").length; })); } }); } }, { type: "save", name: "\u56fd\u5f00\u7b54\u6848\u6536\u5f55\u65e7", match: () => /\/exam\/([0-9]+)\/subjects#\/submission\/([0-9]+)/i.test(location.href), question: { html: "li.subject", question: ".summary-title .subject-description", options: ".subject-options li .option-content", type: ".subject-point > span:eq(0)", workType: "guokai", pageType: "guokai" }, init: async () => { await waitUntil((function() { return O(".loading-gif").hasClass("ng-hide"); })); }, answerHook: e => { const t = ie.angular.element(e.html).scope().subject; if ("text" === t.type) return; if ("analysis" === t.type) { const n = (t.sub_subjects || []).map(buildAnalysisSubQuestion).filter(Boolean); if (0 === n.length) return; const a = O(`
    ${t.description || ""}
    `).clone(); return a.find("span.__blank__").remove(), e.question = removeHtml(a.html()), e.type = "15", e.options = n.map((e => ({ type: e.type, question: e.question, options: e.options }))), e.answer = n.map((e => e.answer)), e; } let n = false; const a = parseFloat(t.point), r = parseFloat(t.score), i = 0 !== a && a === r; let s = O(`
    ${t.description}
    `).clone(); if (s.find("span.__blank__").remove(), e.question = removeHtml(s.html()), e.options = t.options.map((e => removeHtml(e.content))), e.type = typeConvert(ot[t.type]), t.correctOptions && t.correctOptions.length > 0 && (e.answer = t.correctOptions.map((e => removeHtml(e.content))), n = true), t.correct_answers && t.correct_answers.length > 0 && (e.answer = t.correct_answers.map((e => e.content)), n = true), n || i) { switch (t.type) { case "single_selection": case "multiple_selection": case "true_or_false": if (n) "true_or_false" === t.type && (e.answer = judgeAnswer(e.answer[0]), e.options = []); else { if (t.options, e.answer = t.options.filter((e => e.isChosen)).map((e => removeHtml(e.content))), 0 === e.answer.length) return; "true_or_false" === t.type && (e.answer = judgeAnswer(e.answer[0]), e.options = []); } break; case "analysis": break; case "cloze": t.sub_subjects, e.options = t.sub_subjects.map((e => e.options.map((e => removeHtml(e.content))))); break; case "fill_in_blank": n || (e.answer = t.answers.map((e => e.content))); } return e; } }, paper: e => { const t = ie.globalData.course, n = ie.angular.element(O("body")).scope(), a = ie.angular.element(O(".hd")).scope().exam, r = n.submissionData.id; if (!n.examSubmissions.find((e => (e.id, String(e.id) === String(r))))) return; const i = { platform: "guokai" }; i.hash = t.id, i.name = t.name, i.info = {}, i.info.school = t.orgName, i.chapter = [ { hash: `${a.id}`, name: a.title, question: e } ], et.setPaper(i.hash, i); } }, { type: "save", name: "\u5e7f\u5f00\u7b54\u6848\u6536\u5f55", match: () => /mod\/quiz\/review\.php/i.test(location.pathname), question: { html: ".que", question: ".qtext", options: ".answer > div", type: "", answer: ".rightanswer", workType: "ougd", pageType: "ougd" }, init: async () => { O(".specificfeedback").remove(); }, next: async () => { !O(".qn_buttons > a").last().hasClass("thispage") && O(".arrow_text").click(); }, answerHook: e => { e.preserveImageHtml = true; const t = O(e.html).find(".info .state").text(); e.type = (O(e.html).attr("class") || "").split(" ")[1], O(e.html).find(".qtext .accesshide").remove(), e.question = removeHtml(O(e.html).find(".qtext").html()); const n = removeHtml(O(e.html).prevAll(".que.description").first().find(".qtext").html() || ""); if (e.question = mergeMoodleReviewQuestionContext(n, e.question), e.question.includes("egg")) { let t = O(e.html).clone(); t.find("img").each((function() { var e; (null == (e = O(this).attr("src")) ? void 0 : e.includes("egg")) && O(this).remove(); })), e.question = removeHtml(t.find(".qtext").html()), e.question = mergeMoodleReviewQuestionContext(n, e.question); } switch (e.type, e.type) { case "truefalse": e.type = "3", e.$options = O(e.html).find("input[type=radio]"), e.options = O(e.html).find(".answer > div").map(((e, t) => removeHtml(O(t).html()).trim())).get(), e.answer = [], e.answer = O(e.html).find(".answer > div").map(((t, n) => e.$options.eq(t).prop("checked") ? e.options[t] : "")).get(), e.answer = e.answer.filter((e => "" !== e)), 0 === e.answer.length ? (e.temp = removeHtml(O(e.html).find(".rightanswer").html()).replace("\u6b63\u786e\u7b54\u6848\u662f", "").trim(), e.answer = [ e.temp ]) : t.includes("\u6b63\u786e") || (e.answer = e.options.filter((t => !t.includes(e.answer[0])))), isTrue(e.answer[0]) ? e.answer = [ "\u6b63\u786e" ] : isFalse(e.answer[0]) ? e.answer = [ "\u9519\u8bef" ] : e.answer = [], e.options = []; break; case "multichoice": case "multichoiceset": if (e.type = "1", e.$options = O(e.html).find("input[type=checkbox]"), 0 === e.$options.length && (e.type = "0", e.$options = O(e.html).find("input[type=radio]")), e.options = O(e.html).find(".answer > div").map(((e, t) => { let n = O(t).find(".answernumber").text().trim(), a = removeHtml(O(t).html()); return "" === n ? a.trim() : removeKnownOptionPrefix(a, n); })).get(), t.includes("\u6b63\u786e") && !t.includes("\u90e8\u5206\u6b63\u786e")) e.answer = [], e.answer = O(e.html).find(".answer > div").map(((t, n) => { let a = O(n).find(".answernumber").text().trim(), r = removeHtml(O(n).html()); return e.$options.eq(t).prop("checked") && O(n).find(".text-success").length > 0 ? "" === a ? r.trim() : removeKnownOptionPrefix(r, a) : ""; })).get(), e.answer = e.answer.filter((e => "" !== e)); else { e.temp = removeHtml(O(e.html).find(".rightanswer").html(), false).replace("\u6b63\u786e\u7b54\u6848\u662f\uff1a", "").trim(); const t = e.options.slice(0); t.sort(((e, t) => t.length - e.length)), e.answer = t.map((t => e.temp.includes(t) ? (e.temp = e.temp.replace(t, ""), t) : "")), e.answer = e.answer.filter((e => "" !== e)), e.answer.length; } break; case "shortanswer": e.type = "4", e.$options = O(e.html).find("input[type=text]"), e.answer = removeHtml(O(e.html).find(".rightanswer").html()).replace("\u6b63\u786e\u7b54\u6848\uff1a", "").trim(); break; case "match": e.type = "24", e.match = O(".answer tr td.text").map(((e, t) => removeHtml(O(t).html()))).get(), e.$options = O(".answer tr td.control select"), e.selects = O(".answer tr td.control select").map(((e, t) => [ O(t).find("option").map(((e, t) => ({ value: O(t).val(), text: O(t).text() }))).get() ])).get(); break; case "multianswer": e.type = "14"; let n = O(e.html).find(".formulation").clone(); n.find(".subquestion").remove(), n.find(".accesshide").remove(), e.question = removeHtml(n.html()); let a = [], r = []; O(e.html).find(".subquestion").map(((e, t) => { let n = O(t).find("select>option").map(((e, t) => removeHtml(O(t).html()))).get(); n = n.filter((e => "" !== e)), a.push(n); let i = O(t).find("select>option:selected").map(((e, t) => removeHtml(O(t).html()))).get(); r.push(i[0]); })), e.options = a; O(e.html).find(".text-success").length == e.options.length && (e.answer = r); break; case "description": return; } return e; }, paper: async e => { var t; const n = { platform: "ougd" }, a = ie.document.body.outerHTML, r = ((e, t = {}) => { const n = String(t.courseId ?? t.courseid ?? "").trim(); return (/^\d+$/.test(n) ? n : "") || (e.match(new RegExp("(?:[\"']courseId[\"']|(? { try { const e = new URL(t).searchParams.get("cmid"); if (e) return e; } catch (n) {} return (e.match(/[?&]cmid=(\d+)/i) || [])[1] || (e.match(/\/mod\/quiz\/view\.php\?id=(\d+)/i) || [])[1] || ""; })(a, ie.location.href); n.hash = r.trim(), "" !== n.hash && "" !== i && (n.info = {}, n.name = ((e, t) => { if (!t) return ""; const n = t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), a = new RegExp(`]*href=["'][^"']*/course/view\\.php\\?id=${n}(?:[&#][^"']*)?["'][^>]*>([\\s\\S]*?)`, "i"); return (e => e.replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim())((e.match(a) || [])[1] || ""); })(a, r) || O("h1").text().trim() || ie.document.title.trim(), n.chapter = [ { hash: `${i}`, name: ie.document.title.trim(), question: e } ], et.setPaper(n.hash, n, { replaceQuestions: true })); } }, { type: "ask", name: "\u5e7f\u5f00\u5f62\u8003", tips: "\u5e7f\u5f00\u4ec5\u652f\u6301\u57fa\u7840\u9898\u578b\uff0c\u7279\u6b8a\u9898\u578b\u8bf7\u624b\u52a8\u5b8c\u6210", match: () => /mod\/quiz\/attempt\.php/i.test(location.pathname), types: [ "0", "1", "2", "3", "4", "5", "6", "7", "9", "14", "24" ], question: { html: ".que", question: ".qtext", options: ".answer > div", type: "", workType: "ougd", pageType: "ougd" }, ischecked: e => Boolean(e.prop("checked")), questionHook: e => { e.preserveImageHtml = true, e.type = (O(e.html).attr("class") || "").split(" ")[1], O(e.html).find(".qtext .accesshide").remove(), e.question = removeHtml(O(e.html).find(".qtext").html()); const t = removeHtml(O(e.html).prevAll(".que.description").first().find(".qtext").html() || ""); if (e.question = mergeMoodleReviewQuestionContext(t, e.question), e.question.includes("egg")) { let n = O(e.html).clone(); n.find("img").each((function() { var e; (null == (e = O(this).attr("src")) ? void 0 : e.includes("egg")) && O(this).remove(); })), e.question = removeHtml(n.find(".qtext").html()), e.question = mergeMoodleReviewQuestionContext(t, e.question); } switch (e.type) { case "truefalse": e.type = "3", e.$options = O(e.html).find("input[type=radio]"), e.options = []; break; case "multichoice": case "multichoiceset": e.type = "1", e.$options = O(e.html).find("input[type=checkbox]"), 0 === e.$options.length && (e.type = "0", e.$options = O(e.html).find("input[type=radio]")), e.options = O(e.html).find(".answer > div").map(((e, t) => { let n = O(t).find(".answernumber").text().trim(), a = removeHtml(O(t).html()); return "" === n ? a.trim() : removeKnownOptionPrefix(a, n); })).get(); break; case "shortanswer": e.type = "4", e.$options = O(e.html).find("input[type=text]"); break; case "match": e.type = "24", e.match = O(".answer tr td.text").map(((e, t) => removeHtml(O(t).html()))).get(), e.$options = O(".answer tr td.control select"), e.selects = O(".answer tr td.control select").map(((e, t) => [ O(t).find("option").map(((e, t) => ({ value: O(t).val(), text: O(t).text() }))).get() ])).get(); case "essay": e.type = "4", e.$options = O(e.html).find("iframe"); break; case "multianswer": e.type = "14"; let t = O(e.html).find(".formulation").clone(); t.find(".subquestion").remove(), t.find(".accesshide").remove(), e.question = removeHtml(t.html()); let n = []; O(e.html).find(".subquestion").map(((e, t) => { let a = O(t).find("select>option").map(((e, t) => removeHtml(O(t).html()))).get(); a = a.filter((e => "" !== e)), n.push(a), O(t).find("select>option:selected").map(((e, t) => removeHtml(O(t).html()))).get(); })), e.$options = O(e.html).find("select"), e.options = n; break; case "description": return; } return e; }, setAnswer: e => { switch (e.type) { case "4": return O(e.html).find("input.form-control").each((function(t, n) { O(n).val(e.answer[t]); })), O(e.html).find("iframe:eq(0)").contents().find("body").html(e.answer[0]), false; case "3": e.ques.$options.each(((t, n) => { const a = O(n).parent().find("label").text(); return "object" == typeof e.answer && (e.answer = e.answer[0]), isTrue(e.answer) && isTrue(a) ? (O(n).click(), false) : !isFalse(e.answer) || !isFalse(a) || (O(n).click(), false); })); case "14": return O(e.html).find("select").each(((t, n) => { const a = e.answer[t]; O(n).find(`option:contains("${a}")`).prop("selected", true); })), false; default: return true; } }, finish: e => { O(".submitbtns .btn-primary").click(); } }, { type: "ask", name: "\u56fd\u5f00\u4e13\u9898\u6d4b\u9a8c", match: () => /\/exam\/([0-9]+)\/subjects/i.test(location.pathname) && !/\/exam\/([0-9]+)\/subjects#\/submission\/([0-9]+)/i.test(location.href), types: [ "0", "1", "2", "3", "4", "5", "6", "7", "9", "14", "15", "24" ], question: { html: "li.subject", question: ".summary-title .subject-description", options: ".subject-options li .option-content", type: ".summary-sub-title span:eq(0)", workType: "guokai", pageType: "guokai" }, init: async () => { await waitUntil((function() { return O(".loading-gif").hasClass("ng-hide") && "" === O(".hd .examinee .submit-label").eq(0).text(); })), await waitUntil((function() { return 0 !== O("li.subject").length; })); }, ischecked: e => Boolean(e.parent().find("input").eq(-1).prop("checked")), questionHook: e => { const t = ie.angular.element(e.html).scope(), n = t.subject; if ("text" === n.type) return; if ("analysis" === n.type) { const a = O(`
    ${n.description || ""}
    `).clone(); return a.find("span.__blank__").remove(), e.question = removeHtml(a.html()), e.type = "15", e.options = (n.sub_subjects || []).map((e => { const t = typeConvert(ot[e.type]), n = (e.options || []).map((e => removeHtml(e.content))), a = O(`
    ${e.description || ""}
    `).clone(); return a.find("span.__blank__").remove(), { type: t, question: removeHtml(a.html()), options: "true_or_false" === e.type ? [] : n }; })), e.$options = null, e.subject = n, e.scope = t, e; } e.type = typeConvert(ot[n.type]); let a = O(`
    ${n.description}
    `).clone(); switch (a.find("span.__blank__").remove(), e.question = removeHtml(a.html()), n.options = n.options.sort(((e, t) => e.sort - t.sort)), e.options = n.options.map((e => removeHtml(e.content))), e.type, n.type, n.type) { case "cloze": e.options = n.sub_subjects.map((e => e.options.map((e => removeHtml(e.content))))), e.$options = O(e.html).find("select"); case "true_or_false": e.options = []; } return e.subject = n, e.scope = t, e; }, setAnswer: e => { switch (e.ques, e.type) { case "2": return O(e.html).find(".___answer"), O(e.html).find(".___answer").each(((t, n) => { O(n).html(e.answer[t]), e.ques.scope.subject.answers[t].content = e.answer[t], e.ques.scope.onChangeSubmission(e.ques.subject); })), false; case "4": return O(e.html).find(".simditor-body.needsclick>p").each((function(t, n) { O(n).html(e.answer[t]), e.ques.subject.answered_content = e.answer[t]; })), e.ques.scope.onChangeSubmission(e.ques.subject), false; case "14": return e.ques.subject.sub_subjects.forEach(((t, n) => { let a = e.answer[n]; t.options.forEach(((r, i) => { r.content === a && (t.answeredOption = String(r.id), e.ques.scope.onChangeSubmission(t), O(e.html).find(`input[value="${r.id}"]`).click(), O(e.html).find(`button:eq(${n})>span:eq(1)`).text(a)); })); })), false; case "15": return e.ques.subject.sub_subjects.forEach(((t, n) => { const a = e.answer[n]; if (!a || 0 === a.length) return; const r = a[0], i = (t.options || []).find(((e, n) => { const a = removeHtml(e.content); return "number" == typeof r ? n === r : "true_or_false" === t.type ? isTrue(r) && isTrue(a) || isFalse(r) && isFalse(a) : a === r; })); i && (t.answeredOption = String(i.id), e.ques.scope.onChangeSubmission(t), O(e.html).find(`input[value="${i.id}"]`).click()); })), false; } return true; } }, { type: "save", name: "\u4e0a\u6d77\u5f00\u653e\u6536\u5f55", match: () => "l.shou.org.cn" === location.host && location.href.includes("assignment/history.aspx?homeWorkId"), question: { html: ".e-q-body", question: ".ErichText", options: "ul>li>.ErichText", type: ".question-box .tag", workType: "shou", pageType: "shou" }, init: async () => {}, answerHook: e => { e.$options = O(e.html).find("ul>li"); let t = O(e.html).find("ul>li.checked").map(((e, t) => removeHtml(O(t).find(".ErichText").html() || O(t).html()))).get(); const n = O(e.html).find(".e-q-right").length > 0; e.answer = t.filter((e => "" !== e)); let a = O(e.html).find(".e-ans-ref .e-ans-r").map(((e, t) => removeHtml(O(t).html()))).get().map((t => { let n = t.charCodeAt() - 65; return e.options[n]; })).filter((e => "" !== e && void 0 !== e)); switch (e.options = removeStartChar(e.options), O(e.html).attr("data-questiontype")) { case "2": e.type = "1"; break; case "1": e.type = "0"; break; case "3": e.type = "3", e.answer = O(e.html).find("ul>li.checked").map(((e, t) => removeHtml(O(t).html()))).get(), e.options = [], isTrue(e.answer[0]) ? e.answer = [ "\u6b63\u786e" ] : isFalse(e.answer[0]) ? e.answer = [ "\u9519\u8bef" ] : e.answer = []; break; case "8": e.type = "15"; const t = O(e.html).find(".e-q-quest form").map(((e, t) => { let n = removeHtml(O(t).find(".e-q-q .ErichText").html()), a = O(t).find("ul>li").map(((e, t) => removeHtml(O(t).find(".ErichText").html() || O(t).html()))).get(), r = "0"; a = removeStartChar(a); const i = O(t).find(".e-a-right").length > 0, s = O(t).find(".e-ans-ref .e-ans-r").map(((e, t) => removeHtml(O(t).html()))).get(); let o = s.map((e => { let t = e.charCodeAt() - 65; return a[t]; })).filter((e => "" !== e && void 0 !== e)); if (2 === a.length && 1 === s.length) { let e = judgeAnswer(s[0]); e.length > 0 && (o = e, a = [], r = "3"); } return o.length > 1 && (r = "1"), { question: n, options: a, answer: o, isT: i, type: r }; })).get(); if (t.some((e => !e.isT))) return; a = t.map((e => e.answer)).flat(), e.options = t.map((e => ({ question: e.question, options: e.options, type: e.type }))); break; case "11": e.type = "19"; const n = O(e.html).find("form").map(((e, t) => ({ type: "0", question: removeHtml(O(t).find(".e-q-q .ErichText").html()), options: O(t).find("ul li .ErichText").map(((e, t) => removeHtml(O(t).html()))).get() }))).get(); a = a.length > 0 ? judgeAnswer(a[0]) : [], e.options = n; break; default: return void O(e.html).attr("data-questiontype"); } return a.length > 0 ? (e.answer = a, e) : !n && "3" === e.type && e.answer.length > 0 || !n ? void 0 : e; }, paper: async e => { const t = { platform: "shou" }, n = O("input[name=CourseOpenId]").val(), a = O("input[name=WorkId]").val(); await request("https://l.shou.org.cn/student/CourseScoreNew-inside.aspx", "GET").then((e => { const a = O(e[0].responseText); t.name = a.find(`#courseSelect>option[data-xid="${n}"]`).text().trim(), t.info = {}; })), t.hash = n, t.info = {}, t.chapter = [ { hash: `${a}`, name: O(".mark_title").text().trim(), question: e } ], et.setPaper(t.hash, t); } }, { type: "ask", name: "\u4e0a\u6d77\u5f00\u653e\u4f5c\u4e1a", tips: "", match: () => "l.shou.org.cn" === location.host && (location.href.includes("assignment/preview.aspx?homeWorkId") || location.href.includes("study/assignment/continuation.aspx")), types: [ "0", "1", "3" ], question: { html: ".e-q-body", question: ".ErichText", options: "ul>li>.ErichText", type: ".question-box .tag", workType: "shou", pageType: "shou" }, init: async () => { await waitUntil((function() { return 0 !== O(".e-q-body").length; })); }, ischecked: isParentChecked, questionHook: e => { switch (O(e.html).attr("data-questiontype")) { case "2": e.type = "1"; break; case "1": e.type = "0"; break; case "3": e.type = "3", e.$options = O(e.html).find("ul>li"); break; case "8": e.type = "15", e.quesList = O(e.html).find("form").map(((e, t) => ({ type: "0", question: removeHtml(O(t).find(".e-q-q .ErichText").html()), options: O(t).find("ul li .ErichText").map(((e, t) => removeHtml(O(t).html()))).get() }))).get(); break; default: return void O(e.html).attr("data-questiontype"); } return e; } } ], ct = [ { type: "ask", name: "\u6210\u6559\u4e91\u8003\u8bd5", tips: "", match: () => location.href.includes("student/exam/resource/paper_card"), types: [ "0", "1", "3" ], question: { html: ".ui-question", question: ".ui-question-content-wrapper", options: ".ui-question-options li .ui-question-content-wrapper", type: ".ui-question-group-title", workType: "chengjiaoyun", pageType: "chengjiaoyun" }, init: async () => { if (await waitUntil((function() { return isExist(".ui-question"); })), !ie.top.location.href.includes("student/exam2/doexam")) return false; }, toquestion: async e => { O(ie.top.document).find(".ui-card-questions ul li:eq(" + e + ")").click(); }, next: async () => { O("#next-btn").click(); }, ischecked: e => e.hasClass("ui-option-selected"), questionHook: e => { if (e.type = typeMatch(O(e.html).parent().find(".ui-question-group-title").text()), e.$options = O(e.html).find(".ui-question-options li>span"), "3" === e.type) e.options = []; return e; }, setAnswer: e => { if ("3" === e.type) { let t = e.answer; return e.ques.$options.each(((e, n) => { isTrue(t) && isTrue(removeHtml(O(n).parent().html())) && O(n).click(), isFalse(t) && isFalse(removeHtml(O(n).parent().html())) && O(n).click(); })), false; } return true; } }, { type: "save", name: "\u6210\u6559\u4e91\u6536\u5f55", match: () => location.href.includes("student/exam/resource/paper_card"), question: { html: ".ui-question", question: ".ui-question-content-wrapper", options: ".ui-question-options li .ui-question-content-wrapper", type: ".ui-question-group-title", workType: "chengjiaoyun", pageType: "chengjiaoyun" }, init: async () => { if (await waitUntil((function() { return isExist(".ui-question"); })), ie.top.location.href.includes("student/exam2/doexam")) return false; }, answerHook: e => { if (e.type = typeMatch(O(e.html).parent().find(".ui-question-group-title").text()), e.$options = O(e.html).find(".ui-question-options li>span"), e.answer = O(e.html).find(".ui-question-options li.ui-correct-answer .ui-question-content-wrapper").map(((e, t) => removeHtml(O(t).html()))).get(), "3" === e.type) e.options = [], e.answer = isTrue(e.answer[0]) ? [ "\u6b63\u786e" ] : isFalse(e.answer[0]) ? [ "\u9519\u8bef" ] : []; return e; } } ]; const ut = [ { type: "hook", name: "hook", match: () => "xuexi.jsou.cn" === location.host && location.href.includes("newHomework/showHomeworkByStatus") && location.href.includes("checked=true"), main: e => { ie.mainClass = O("#homeworkHistory").find(".active").attr("id"); let t = new MutationObserver((async e => { ie.mainClass !== O("#homeworkHistory").find(".active").attr("id") && (ie.mainClass = O("#homeworkHistory").find(".active").attr("id"), await waitUntil((function() { return 0 === O(".layui-layer-shade").length; })), vuePageChange(), t.disconnect()); for (let n of e) "attributes" === n.type && "class" === n.attributeName && n.target.textContent && (n.target.textContent.includes("\u4e0b\u4e00\u9898") || n.target.textContent.includes("\u4e0a\u4e00\u9898")) && (t.disconnect(), vuePageChange()); })); O("body").length >= 1 && t.observe(O("body")[0], { subtree: true, attributes: true, childList: true }); } }, { type: "ask", name: "\u6c5f\u82cf\u5f00\u653e\u5927\u5b66\u7b54\u9898", tips: "", match: () => "xuexi.jsou.cn" === location.host && location.href.includes("/showHomeworkByStatus") && location.href.includes("checked=false"), types: [ "0", "1", "2", "3" ], question: { html: ".insert", question: ".window-title", options: ".questionId-option li > div:not(.numberCover)", type: ".questionDiv >div:eq(0)", workType: "jsou", pageType: "jsou" }, init: async () => { document.addEventListener("copy", (function(e) { e.stopImmediatePropagation(), layer.msg("\u590d\u5236\u6210\u529f", { icon: 4 }), e.clipboardData.setData("text/plain", window.getSelection().toString()); })), document.addEventListener("paste", (() => { event.stopImmediatePropagation(); let e = (event.clipboardData || window.clipboardData).getData("text"); layer.msg("\u7c98\u8d34\u6210\u529f", { icon: 4 }), document.execCommand("insertText", false, e); })); }, ischecked: function(e) { if (!e) return false; const hasSelectedClass = e => !(!(null == e ? void 0 : e.length) || "function" != typeof e.hasClass || !e.hasClass("is-checked") && !e.hasClass("answer-title")); if (hasSelectedClass(e)) return true; if (hasSelectedClass("function" == typeof e.closest ? e.closest(".default-option, li") : null)) return true; const t = "function" == typeof e.parent ? e.parent() : null; return !!hasSelectedClass(t) || hasSelectedClass("function" == typeof (null == t ? void 0 : t.parent) ? t.parent() : null); }, questionHook: e => (e.type = O(e.html).find(".questionDiv >div:eq(1)").text().trim(), e.type = typeConvert(e.type), e.$options = O(e.html).find(".questionId-option li .numberCover"), "3" == e.type && (e.options = []), e), setAnswer: e => { switch (e.type) { case "2": if (e.$options = O(e.html).find(".questionTitle input"), e.$options.length == e.answer.length) return e.$options.each(((t, n) => { O(n).val(e.answer[t]); })), false; break; case "3": let t = e.answer; return O(e.html).find(".questionId-option>.default-option").each(((e, n) => { isTrue(t) && isTrue(removeHtml(O(n).find(".option-title>div:eq(1)").html())) && O(n).find("div.numberCover").click(), isFalse(t) && isFalse(removeHtml(O(n).find(".option-title>div:eq(1)").html())) && O(n).find("div.numberCover").click(); })), false; case "4": const n = O(e.html).find(".jianda-answer>div").attr("id"); return ie.UE.getEditor(`${n}`).setContent(e.answer), false; } return true; } }, { type: "save", name: "\u6c5f\u82cf\u5f00\u653e\u5927\u5b66\u6536\u5f55", match: () => "xuexi.jsou.cn" === location.host && location.href.includes("newHomework/showHomeworkByStatus") && location.href.includes("checked=true"), question: { html: ".insert", question: ".window-title", options: "#questionId-option li > div:not(.numberCover)", type: ".questionDiv >div:eq(0)", workType: "jsou", pageType: "jsou" }, init: async () => {}, answerHook: e => { const t = O(e.html).find(".questionDiv >div").text(), n = t.match(/\u5206\u503c(\d+)\u5206/), a = t.match(/\u5f97\u5206\uff1a(\d+)/); if (!n || !a) return null; e.type = typeConvert(O(e.html).find(".questionDiv >div:eq(1)").text()); if (!(n[1] === a[1] && "0" !== a[1]) && "3" !== e.type) return null; switch (e.type) { case "0": case "1": case "3": if (e.answer = O(e.html).find(".answer .correctAnswer").text().trim().split("\uff1b").map((t => e.options[t.charCodeAt(0) - 65])), e.answer = e.answer.filter((e => e)), 0 == e.answer.length && (e.answer = O(e.html).find(".answer .studentAnswer").text().trim().split("\uff1b").map((t => e.options[t.charCodeAt(0) - 65]))), e.answer = e.answer.filter((e => e)), 3 == e.type) { e.options = []; let t = e.answer[0]; if (isFalse(t)) e.answer = "\u9519\u8bef"; else { if (!isTrue(t)) return; e.answer = "\u6b63\u786e"; } } break; case "2": e.options = [], e.answer = O(e.html).find(".answer .correctAnswer").text().trim().split("\uff1b"), e.answer = e.answer.filter((e => e)), 0 == e.answer.length && (e.answer = O(e.html).find(".answer .studentAnswer").text().trim().split("\uff1b")), e.answer = e.answer.filter((e => e)); break; default: return; } return e; }, paper: e => { const t = ie.homework, n = { platform: "jsou" }; n.hash = t.courseId, n.name = t.courseName, n.info = {}, n.chapter = [ { hash: `${t.homeworkId}`, name: t.title, question: e } ], et.setPaper(n.hash, n); } } ], parseZhijiaoyunTypeText = e => { const t = String(e ?? "").match(/\u3010(.*)\u3011/); return t ? t[1].trim().replace("\u586b\u7a7a\u9898(\u5ba2\u89c2)", "\u586b\u7a7a\u9898") : ""; }, pt = [ { type: "hook", name: "hook", match: "spoc-exam.icve.com.cn" === location.host || location.host.includes("exam.courshare.cn") || location.host.includes("webtrn.cn"), main: e => { ie.mainClass = O(".q_content").first().attr("id"); let t = new MutationObserver((async e => { ie.mainClass !== O(".q_content").first().attr("id") && (ie.mainClass = O(".q_content").first().attr("id"), "homework-detail-container" === ie.mainClass && await waitUntil((function() { return 0 !== O(".q_content").length; })), vuePageChange(), t.disconnect()); for (let n of e) "attributes" === n.type && "class" === n.attributeName && n.target.textContent && (n.target.textContent.includes("\u4e0b\u4e00\u9898") || n.target.textContent.includes("\u4e0a\u4e00\u9898")) && (t.disconnect(), vuePageChange()); })); O("#examPage").length >= 1 && t.observe(O("#examPage")[0], { subtree: true, attributes: true, childList: true }); } }, { type: "hook", name: "hook", match: "zjy2.icve.com.cn" === location.host || "zyk.icve.com.cn" === location.host || "ai.icve.com.cn" === location.host, main: e => { O(".minimized-dialog img").css({ "z-index": "999999" }); observeVuePageChange(O("#app")[0], (() => O("#app")[0].__vue__.$route.name), { beforeChange: async e => { "homework-detail-container" === e && await waitUntil((function() { return 0 !== O(".q_content").length; })); } }); } }, { type: "ask", name: "\u804c\u6559\u4e91\u4f5c\u4e1a", tips: "", match: () => location.href.includes("examflow_index.action"), types: [ "0", "2", "1", "3", "4" ], question: { html: ".q_content", question: ".divQuestionTitle", options: ".questionOptions > div", type: ".question-box .tag", workType: "zhijiaoyun", pageType: "zhijiaoyun" }, init: async () => { await waitUntil((function() { return 0 !== O(".q_content").length; })); }, finish: e => { O('.paging_next:contains("\u4e0b\u4e00\u9875")').click(); }, ischecked: e => 0 !== e.parent().find(".checkbox_on").length, questionHook: e => { var t, n; e.question = removeHtml(O(e.html).find(".divQuestionTitle").html()); let a = O(e.html).find("[name='quesId']").attr("id"), r = null == (n = null == (t = document.getElementById(`questionId[${a}]`)) ? void 0 : t.getAttribute("answertype")) ? void 0 : n.trim(), i = O(e.html).find("span[name^='questionIndex']").text().trim() + "\u3001", s = O(e.html).find(".q_score").text().trim(); var o; switch (e.question = (o = e.question.replace(i, "").replace(s, "").trim(), titleClean(String(o ?? "").replace(/\s*\u2691?\s*(?:\u6807\u8bb0\u5b58\u7591|\u53d6\u6d88\u5b58\u7591)\s*$/, "").replace(/\s*\uff08\d+(?:\.\d+)?\s*\u5206\uff09$/, "").trim())), e.options = O(e.html).find(".questionOptions>div").map(((e, t) => { let n = O(t).find(".option_index").text().trim(); return removeHtml(O(t).html()).replace(n, "").trim(); })).get(), e.$options = O(e.html).find(".questionOptions>div input"), r) { case "\u5355\u9879\u9009\u62e9\u9898": case "\u5355\u9009\u9898": case "singlechoice": e.type = "0"; break; case "\u591a\u9879\u9009\u62e9\u9898": case "\u591a\u9009\u9898": case "multichoice": e.type = "1"; break; case "\u5224\u65ad\u9898": case "bijudgement": e.type = "3", e.options = []; break; case "fillblank": e.type = "2", e.question = removeHtml(O(e.html).find("[name='fillblankTitle']").html()); break; case "cloze": e.type = "14", e.options = O(e.html).find(".questionOptions>.exam_cloze_choice").map(((e, t) => [ O(t).find(".optionContent").map(((e, t) => removeHtml(O(t).html()))).get() ])).get(); break; case "textarea": e.type = "4", e.options = []; } return e; }, setAnswer: e => { switch (e.type) { case "2": return O(e.html).find(".fillblank_input > input").each(((t, n) => { O(n).val(e.answer[t]); })), false; case "3": let t = e.answer; return e.ques.$options.each(((e, n) => { isTrue(t) && isTrue(removeHtml(O(n).parent().html())) && O(n).click(), isFalse(t) && isFalse(removeHtml(O(n).parent().html())) && O(n).click(); })), false; case "4": let n = O(e.html).find("[name='quesId']").attr("id"); return ie.UE.getEditor(`_baidu_editor_${n}`).setContent(`

    ${e.answer}

    `), false; } return true; } }, { type: "save", name: "\u804c\u6559\u4e91\u6536\u5f55", match: () => location.href.includes("examrecord_recordDetail.action"), question: { html: ".q_content", question: ".divQuestionTitle", options: ".questionOptions>div.q_option_readonly", type: ".question-box .tag", workType: "zhijiaoyun", pageType: "zhijiaoyun" }, init: async () => { await waitUntil((function() { return 0 !== O(".q_content").length; })); }, answerHook: e => { const t = O(e.html).find(".exam.icon_examright").length, n = O(e.html).find("input[name='quesId']:not([id='']").attr("id"), a = O(`input#qId${n}`).attr("qtype"), r = O(e.html).find("span[name^='questionIndex']").text().trim() + "\u3001", i = O(e.html).find(".q_score").text().trim(); switch (e.question = e.question.replace(r, "").replace(i, "").trim(), e.options = O(e.html).find(".questionOptions>div.q_option_readonly").map(((e, t) => { let n = O(t).find("span[name='optionIndexName']").text().trim(); return removeHtml(O(t).html()).replace(n, "").trim(); })).get(), a) { case "\u5355\u9879\u9009\u62e9\u9898": case "\u5355\u9009\u9898": case "singlechoice": e.type = "0"; break; case "\u591a\u9879\u9009\u62e9\u9898": case "\u591a\u9009\u9898": case "multichoice": e.type = "1"; break; case "\u5224\u65ad\u9898": case "bijudgement": e.type = "3"; break; case "fillblank": case "\u586b\u7a7a\u9898": e.type = "2"; const t = O(e.html).find(".answerOption>span:eq(0)").clone(); t.find(".exam_answers").remove(), e.question = titleClean(removeHtml(t.html())).replace(/\uff08.*?\u5206\uff09/g, "").trim(); break; case "cloze": case "\u5b8c\u5f62\u586b\u7a7a": e.type = "14", e.options = O(e.html).find(".questionOptions>.exam_cloze_choice").map(((e, t) => [ O(t).find(".optionContent").map(((e, t) => removeHtml(O(t).html()))).get() ])).get(), e.answer = O(e.html).find(".exam_rightAnswer .answer_table .one_answer>span").map(((t, n) => { const a = O(n).text().trim(); return e.options[t][a.charCodeAt(0) - 65]; })).get(); break; case "textarea": e.type = "4", e.options = [], e.answer = removeHtml(O(e.html).find(".exam_rightAnswer .has_standard_answer").html()); } switch (e.type) { case "0": case "1": if (e.answer = O(e.html).find('.exam_rightAnswer .exam_answers_tit>span[name="rightAnswer"]').text().trim().split("").map((t => e.options[t.charCodeAt(0) - 65])), e.answer, 0 == e.answer.length) { if (0 == t) return; e.answer = O(e.html).find('.exam_stu_answer span[name="stuAnswer"]').text().trim().split("").map((t => e.options[t.charCodeAt(0) - 65])); } break; case "2": e.answer = 0 == t ? O(e.html).find(".exam_rightAnswer span.fillblank_answer").map(((e, t) => removeHtml(O(t).html()))).get() : O(e.html).find(".exam_stu_answer span.fillblank_answer").map(((e, t) => removeHtml(O(t).html()))).get(), e.answer; break; case "3": e.options = []; let n = O(e.html).find('.exam_stu_answer span[name="stuAnswer"]').text().trim(); [ "\u6b63\u786e", "\u9519\u8bef" ].includes(n) && t && (e.answer = [ n ]); } return e; } }, { type: "save", name: "\u667a\u6167\u804c\u6559\u6536\u5f55", match: () => "zjy2.icve.com.cn" === location.host && (location.href.includes("/spocviewsJob") || location.href.includes("/viewExam")), question: { html: ".subjectDet", question: ".seeTitle .htmlP.ql-editor", options: ".optionList .htmlP.ql-editor", type: ".question-box .tag", workType: "zhijiaoyun", pageType: "zhijiaoyun" }, init: async () => { await waitUntil((function() { return 0 !== O(".subjectDet").length; })); }, answerHook: e => { const t = O(e.html).find(".xvhao").text().trim(); e.type = typeConvert(parseZhijiaoyunTypeText(t)); let n = O(e.html).find(".answer").text().trim(); switch (e.answer = n.split(",").map((t => e.options[t.charCodeAt(0) - 65])), e.type) { case "2": e.options = [], e.answer = O(e.html).find(".answer>span").map(((e, t) => removeHtml(O(t).html()))).get(); break; case "3": e.options = O(e.html).find(".optionList>div").map(((e, t) => removeHtml(O(t).html()))).get(), e.answer = n.split(",").map((t => e.options[t.charCodeAt(0) - 65])), e.answer = judgeAnswer(e.answer[0]), e.options = []; break; case "11": const t = O(e.html).find(".optionList .matching>.htmlP.ql-editor").map(((e, t) => removeHtml(O(t).html()))).get(), a = O(e.html).find(".optionList>.text .htmlP.ql-editor").map(((e, t) => removeHtml(O(t).html()))).get(); e.options = [ t, a ]; let r = {}; n = O(e.html).find(".answer>span").map(((e, n) => { let [i, s] = O(n).text().trim().split("."); i.charCodeAt(0) >= 65 ? i = (i.charCodeAt(0) - 65).toString() : /^\d+$/.test(i) && (i = (parseInt(i) - 1).toString()), s.charCodeAt(0) >= 65 ? s = (s.charCodeAt(0) - 65).toString() : /^\d+$/.test(s) && (s = (parseInt(s) - 1).toString()), r[t[i]] = a[s]; })), e.answer = r; } return e; } }, { type: "ask", name: "\u667a\u6167\u804c\u6559+\u7b54\u9898", tips: "\u8be5\u5e73\u53f0\u95ee\u9898\u8f83\u591a\uff0c\u9047\u5230\u8bf7\u53cd\u9988\u7ed9\u4f5c\u8005", match: () => { return e = location.href, !/spockeepTestView|spocjobTestDocument/.test(e) && (e.includes("coursePreview/jobTest") || e.includes("spockeepTest") || e.includes("spocjobTest")); var e; }, types: [ "0", "1", "2", "3" ], question: { html: ".subjectDet", question: ".ql-editor", options: ".optionList .ql-editor", type: ".question-box .tag", workType: "zhijiaoyun", pageType: "zhijiaoyun" }, init: async () => { await waitUntil((function() { return 0 !== O(".subjectDet").length; })); }, ischecked: e => e.parent().parent().parent().hasClass("is-checked"), questionHook: e => { const t = O(e.html).find(".title.titleTwo").text().trim(); switch (e.type = typeConvert(parseZhijiaoyunTypeText(t)), e.type) { case "2": e.options = [], e.$options = O(e.html).find(".tkInput input"); break; case "3": e.options = [], e.$options = O(e.html).find(".optionList>div label"); } return e; }, setAnswer: e => "2" !== e.type || (((e, t) => { const n = Array.isArray(t) ? t : [ t ]; let a = 0; e.forEach(((e, t) => { const r = n[t]; null != r && (e.value = String(r), e.dispatchEvent(new Event("input", { bubbles: true })), a++); })); })(O(e.html).find(".tkInput input").get(), e.answer), false) }, { type: "save", name: "\u667a\u6167\u804c\u6559+\u6536\u5f55", match: () => "zyk.icve.com.cn" === location.host && (location.href.includes("/coursePreview/viewJob1") || location.href.includes("/viewExam")), question: { html: ".subjectDet", question: ".seeTitle>span:eq(1)", options: ".optionList>div", type: ".question-box .tag", workType: "zhijiaoyun", pageType: "zhijiaoyun" }, init: async () => { await waitUntil((function() { return 0 !== O(".subjectDet").length; })); }, answerHook: e => { e.options = removeStartChar(e.options); const t = O(e.html).find(".xvhao").text().trim(); e.type = typeConvert(parseZhijiaoyunTypeText(t)); let n = O(e.html).find(".answer").text().trim(); switch (e.answer = n.split(",").map((t => e.options[t.charCodeAt(0) - 65])), e.type) { case "2": e.options = [], e.answer = O(e.html).find(".answer>span").map(((e, t) => removeHtml(O(t).html()))).get(); break; case "3": e.options = O(e.html).find(".optionList>div").map(((e, t) => removeHtml(O(t).html()))).get(), e.answer = n.split(",").map((t => e.options[t.charCodeAt(0) - 65])), e.answer = judgeAnswer(e.answer[0]), e.options = []; } return e; } }, { type: "save", name: "ai\u4f18\u8bfe\u6536\u5f55\u65b0", match: () => "ai.icve.com.cn" === location.host && location.href.includes("/review-exam/"), question: { html: () => { let e = O(".examination-paper")[0].__vue__.sjAllInfo.questions, t = []; return e.sort(((e, t) => e.txdm - t.txdm)), e.forEach((e => { t.push(e); })), t; }, question: ".seeTitle>span:eq(1)", options: ".optionList>div", type: ".question-box .tag", workType: "zhijiaoyun", pageType: "zhijiaoyun" }, init: async () => { await waitUntil((function() { return 0 !== O(".examination-paper")[0].__vue__.sjAllInfo.questions.length; })); let e = O(".examination-paper")[0].__vue__.sjAllInfo.questions, t = []; e.sort(((e, t) => e.txdm - t.txdm)), e.forEach((e => { t.push(e); })), ie.quesList = t; }, answerHook: (e, t) => { const n = e.html; e.type = typeMatch(n.type), e.question = titleClean(n.tmmc); let a = []; switch (e.type) { case "3": "1" == n.answer && (e.answer = [ "\u6b63\u786e" ]), "0" == n.answer && (e.answer = [ "\u9519\u8bef" ]); break; case "2": e.answer = n.answer.split(","); break; case "4": e.answer = n.answer; break; case "0": case "1": e.options = n.sjtmxxlist.map((e => ("1" == e.sfzqda && a.push(removeHtml(e.xxnr)), removeHtml(e.xxnr)))), e.answer = a; } return e; }, paper: async e => {} }, { type: "ask", name: "ai\u4f18\u8bfe\u7b54\u9898", tips: "", match: () => "ai.icve.com.cn" === location.host && location.href.includes("/preview-exam/"), types: [ "0", "1" ], question: { html: () => { let e = O(".examination-paper")[0].__vue__.tmActivelist, t = []; return e.sort(((e, t) => e.px - t.px)), e.forEach((e => { t.push(e); })), t; }, question: ".seeTitle>span:eq(1)", options: "label", type: ".question-box .tag", workType: "zhijiaoyun", pageType: "zhijiaoyun" }, init: async () => { await waitUntil((function() { return 0 !== O(".examination-paper")[0].__vue__.tmActivelist.length; })); }, toquestion: e => { O(".topic-zpx-list .topic-zpx-main span:eq(" + e + ")").click(); }, ischecked: e => e.hasClass("wrongXz"), questionHook: e => { var t; const n = e.html, a = O(".examination-paper")[0].__vue__.topList, r = []; Object.keys(a).forEach((e => { a[e].forEach((t => { r.push({ id: t.id, type: t.txdmmc || e }); })); })); const i = (null == (t = r.find((e => e.id === n.id))) ? void 0 : t.type) || "\u5176\u4ed6"; e.type = typeMatch(i), e.question = titleClean(n.title); const s = n.dataArr.map((e => removeHtml(e.Content))); return e.options = s, e.answer = [], e.html = O(".content-center"), e.$options = () => O("label"), e; } }, { type: "ask", name: "\u7f51\u68af\u81ea\u6d4b\u7b54\u9898", tips: "", match: () => location.href.includes("coursewareTest_intoTestPage.action"), types: [ "0", "1", "3", "2" ], question: { html: ".test_item", question: ".test_item_tit", options: ".test_item_theme li", type: ".test_item_type", workType: "webtrn", pageType: "webtrn" }, init: async () => { await waitUntil((function() { return 0 !== O(".test_item").length; })); }, ischecked: e => e.is(":checked"), questionHook: e => { const t = O(e.html), n = t.find(".test_item_tit").clone(); n.find(".tipNodo").remove(); let a = removeHtml(n.html() || "").replace(/^\s*\d+\s*[\.\u3001\uff0e]\s*/, "").replace(/\uff08\s*[\d.]+\s*\u5206\s*\uff09\s*$/, "").trim(); e.question = titleClean(a); let r = t.prevAll(".test_item_type").first().text().trim(); switch (r || (r = t.parent().prevAll(".test_item_type").first().text().trim()), r.includes("\u591a\u9009") ? e.type = "1" : r.includes("\u5224\u65ad") ? e.type = "3" : r.includes("\u586b\u7a7a") ? e.type = "2" : r.includes("\u7b80\u7b54") || r.includes("\u95ee\u7b54") || r.includes("\u8bba\u8ff0") ? e.type = "4" : e.type = "0", e.type) { case "3": e.options = [], e.$options = t.find(".test_item_theme input"); break; case "2": e.options = [], e.$options = t.find('input[type="text"], textarea'); break; case "4": e.options = [], e.$options = t.find("textarea"); break; default: e.options = t.find(".test_item_theme li").map(((e, t) => { const n = O(t), a = n.find(".zdh_op_con"); return (a.length ? removeHtml(a.html() || "") : removeHtml(n.html() || "").replace(/^[A-Z][\uff0e\.\u3001]?\s*/, "")).trim(); })).get(), e.$options = t.find(".test_item_theme li input"); } return e; }, setAnswer: e => { switch (e.type) { case "3": { const t = e.answer; return e.ques.$options.each(((e, n) => { const a = (O(n).attr("value") || "").toUpperCase(), r = O(n).parent().text(); (isTrue(t) && ("T" === a || /\u5bf9|\u6b63\u786e/.test(r)) || isFalse(t) && ("F" === a || /\u9519|\u9519\u8bef/.test(r))) && !n.checked && O(n).click(); })), false; } case "2": return e.ques.$options.each(((t, n) => { O(n).val(e.answer[t]).trigger("change"); })), false; case "4": return e.ques.$options.first().val(e.answer).trigger("change"), false; } return true; } }, { type: "save", name: "\u7f51\u68af\u81ea\u6d4b\u6536\u5f55", match: () => location.href.includes("coursewareTest_intoTestAnswerPage.action"), question: { html: ".test_item", question: ".test_item_tit", options: ".test_item_theme li", type: ".test_item_type", workType: "webtrn", pageType: "webtrn" }, init: async () => { await waitUntil((function() { return 0 !== O(".test_item").length; })); }, answerHook: e => { const t = O(e.html), n = t.find(".test_item_tit").clone(); n.find(".zdh_t_f, .test_item_key").remove(); let a = removeHtml(n.html() || "").replace(/^\s*\d+\s*[\.\u3001\uff0e]\s*/, "").replace(/\uff08\s*[\d.]+\s*\u5206\s*\uff09\s*$/, "").trim(); e.question = titleClean(a); let r = t.prevAll(".test_item_type").first().text().trim(); r || (r = t.parent().prevAll(".test_item_type").first().text().trim()), r.includes("\u591a\u9009") ? e.type = "1" : r.includes("\u5224\u65ad") ? e.type = "3" : r.includes("\u586b\u7a7a") ? e.type = "2" : r.includes("\u7b80\u7b54") || r.includes("\u95ee\u7b54") || r.includes("\u8bba\u8ff0") ? e.type = "4" : e.type = "0"; const i = t.find(".test_item_key_tit").text().replace(/^.*?[\uff1a:]\s*/, "").trim(); switch (e.type) { case "0": case "1": e.options = t.find(".test_item_theme ul li").map(((e, t) => { const n = O(t).find(".zdh_op_con"); return (n.length ? removeHtml(n.html() || "") : removeHtml(O(t).html() || "").replace(/^[A-Z][\uff0e\.\u3001]?\s*/, "")).trim(); })).get(), e.answer = i.split("").filter((e => /[A-Z]/.test(e))).map((t => e.options[t.charCodeAt(0) - 65])).filter((e => void 0 !== e)); break; case "3": e.options = [], e.answer = judgeAnswer(i); break; case "2": e.options = [], e.answer = i.split(/[,\uff0c;\uff1b\s]+/).filter(Boolean); break; case "4": e.options = [], e.answer = i; } return e; } } ], dt = [ { type: "ask", name: "\u5ddd\u519c\u5728\u7ebf\u7b54\u9898", tips: "", match: () => location.host.includes("cnzx.info") && location.href.includes("KaoShi/ShiTiYe.aspx"), types: [ "0", "1", "3" ], question: { html: "li.question", question: ".wenti >p.stem", options: ".wenti > ol > li", type: ".question_head > span:eq(0)", workType: "cnzx", pageType: "cnzx" }, init: async () => {}, ischecked: e => e.find("input").prop("checked"), questionHook: e => (e.$options = O(e.html).find(".wenti > ol > li input"), 0 !== e.options.length && (e.type = "radio" === e.$options.eq(0).attr("type") ? "0" : "1", 2 === e.options.length && e.options.includes("\u6b63\u786e") && e.options.includes("\u9519\u8bef") && (e.type = "3", e.options = [])), e), setAnswer: e => "3" !== e.type || (O(e.html).find(".wenti > ol > li").each(((t, n) => { isTrue(e.answer) && isTrue(removeHtml(O(n).html())) && e.ques.$options.eq(t).click(), isFalse(e.answer) && isFalse(removeHtml(O(n).html())) && e.ques.$options.eq(t).click(); })), false), finish: e => { O("li.paginationjs-next.J-paginationjs-next").click(); } }, { type: "save", name: "\u5ddd\u519c\u5728\u7ebf\u6536\u5f55", match: () => location.host.includes("cnzx.info") && location.href.includes("ZaiXianLianXi.aspx"), question: { html: ".ShiTi>.ShiTiMiaoShu", question: ".ShiTiMiaoShu", options: ".el-radio-group label .label,.el-checkbox-group label .label", type: ".question-box .tag", workType: "cnzx", pageType: "cnzx" }, init: async () => {}, answerHook: e => { O(e.html).text(), e.question = removeHtml(titleClean(removeHtml(O(e.html).html()))); let t = O("ul.TiXing>li.DangQianTiXing:eq(0)>a").text(), n = [], a = O(e.html).next(); switch (e.options = removeStartChar(a.find("ul li").map(((e, t) => (O(t).hasClass("DaAn1") && n.push(e), titleClean(removeHtml(O(t).html()))))).get()), e.answer = n.map((t => e.options[t])), t) { case "\u5355\u9009\u9898": case "\u8bcd\u6c47\u4e0e\u7ed3\u6784": case "\u4ea4\u9645\u7528\u8bed": e.type = "0"; break; case "\u591a\u9009\u9898": e.type = "1"; break; case "\u5224\u65ad\u9898": e.type = "3", e.options = [], e.answer = isTrue(e.answer[0]) ? [ "\u6b63\u786e" ] : isFalse(e.answer[0]) ? [ "\u9519\u8bef" ] : []; } return e; } } ], mt = [ { type: "hook", name: "安徽继续教育hook", match: () => /ahjxjy\.cn/i.test(location.host) || location.href.includes("ahjxjy"), main: () => { // URL-only observer like other aiask SPA hooks; init() already waits for the paper DOM. observeVuePageChange(document.body, (() => location.href)); } }, { type: "ask", name: "\u5b89\u5fbd\u7ee7\u7eed\u6559\u80b2\u7b54\u9898(\u65e7\u7248)", tips: "", match: () => location.href.includes("study/html/content/studying/?courseOpenId=") || location.href.includes("study/html/content/sxsk/?courseOpenId=") || location.href.includes("study/html/content/tkOnline/?courseOpenId=") || location.href.includes("study/html/content/bkExam/?courseOpenId="), types: [ "0", "1", "3" ], question: { html: ".e-q-body>.e-q", question: ".ErichText", options: "ul>li>.ErichText", type: ".question-box .tag", workType: "ahjxjy", pageType: "ahjxjy" }, init: async () => { if (await waitUntil((function() { return isExist(".e-q-body>.e-q") && isExist(".e-item"); })), !isExist(".photo-time") && !isExist(".btn_save")) return false; }, ischecked: e => e.parent().hasClass("checked"), questionHook: e => { var t; const n = O(e.html).parent().parent(); switch (e.type = n ? null == (t = n.attr("id")) ? void 0 : t.trim() : "", e.type) { case "2": e.type = "1"; break; case "1": e.type = "0"; break; case "3": e.type = "3", e.$options = O(e.html).find("ul>li"); break; case "4": e.type = "2"; break; case "5": e.type = "4"; break; default: e.type, e.type = "8"; } return e; }, setAnswer: e => { switch (e.type) { case "4": case "2": return O(e.html).find("textarea.answer-input").focus(), O(e.html).find(" textarea.answer-input"), O(e.html).find(".answer-input.edui-default").each(((t, n) => { let a = O(n).attr("id"), r = ie.UE.getEditor(a); r.ready((function() { r.setContent(`

    ${e.answer[t]}

    `); })); })), O(e.html).find(".answer-input").blur(), false; } return true; } }, { type: "save", name: "\u5b89\u5fbd\u7ee7\u7eed\u6559\u80b2\u6536\u5f55(\u65e7\u7248)", tips: "\u8be5\u5e73\u53f0\u4ec5\u652f\u6301\u5355\u9009\u3001\u591a\u9009\u3001\u5224\u65ad\u9898\u578b\uff0c\u5176\u4ed6\u9898\u578b\u6682\u4e0d\u652f\u6301", match: () => location.href.includes("study/html/content/studying/?courseOpenId=") || location.href.includes("study/html/content/sxsk/?courseOpenId=") || location.href.includes("study/html/content/tkOnline/?courseOpenId=") || location.href.includes("study/html/content/bkExam/?courseOpenId="), question: { html: ".e-q-body>.e-q", question: ".ErichText", options: "ul>li>.ErichText", type: ".question-box .tag", workType: "ahjxjy", pageType: "ahjxjy" }, init: async () => { if (await waitUntil((function() { return isExist(".e-save"), isExist(".e-q-body>.e-q") && isExist(".w_e-q-panel"); })), !isExist(".e-quest-review")) return false; }, answerHook: e => { var t; const n = O(e.html).parent().parent(); e.type = n ? null == (t = n.attr("id")) ? void 0 : t.trim() : "", e.$options = O(e.html).find("ul>li"); let a = O(e.html).find("ul>li.checked").map(((e, t) => removeHtml(O(t).find(".ErichText").html()))).get(); const r = O(e.html).find(".e-q-right").length > 0; e.answer = a.filter((e => "" !== e)); let i = O(e.html).find(".e-ans-ref .e-ans-r").map(((e, t) => removeHtml(O(t).html()))).get(); 1 === i.length && i[0].length > 1 && (i = i[0].split("\u3001")); let s = i.map((t => { let n = t.charCodeAt() - 65; return e.options[n]; })).filter((e => "" !== e && void 0 !== e)); switch (e.type) { case "2": e.type = "1"; break; case "1": e.type = "0"; break; case "3": e.type = "3", e.answer = O(e.html).find("ul>li.checked").map(((e, t) => removeHtml(O(t).html()))).get(), e.options = [], isTrue(e.answer[0]) ? e.answer = [ "\u6b63\u786e" ] : isFalse(e.answer[0]) ? e.answer = [ "\u9519\u8bef" ] : e.answer = []; break; case "4": e.type = "2", e.options = []; break; case "5": e.type = "4", s = [ removeHtml(O(e.html).find(".e-ans-ref>.e-ans-r").html()) ], e.options = []; break; case "11": e.type = "19"; const t = O(e.html).find("form").map(((e, t) => ({ type: "0", question: removeHtml(O(t).find(".e-q-q .ErichText").html()), options: O(t).find("ul li .ErichText").map(((e, t) => removeHtml(O(t).html()))).get() }))).get(); s = s.length > 0 ? judgeAnswer(s[0]) : [], e.options = t; default: return void e.type; } if (s.length > 0) return e.answer = s, e; if (!r && "3" === e.type && e.answer.length > 0) { if (e.answer = isTrue((o = e.answer)[0]) || isFalse(o[0]) ? isTrue(o[0]) ? [ "\u9519\u8bef" ] : [ "\u6b63\u786e" ] : [], 0 === e.answer.length) return; } else if (!r) return; var o; return e; }, paper: e => { const t = ie.online, n = { platform: "ahjxjy" }; n.hash = t.courseOpenId, n.name = ie.localStorage.courseNmae, n.info = {}, n.chapter = [ { hash: `${t.cell.id}`, name: t.cell.title, question: e } ], et.setPaper(n.hash, n); } }, { type: "save", name: "安徽继续教育收录(新版)", tips: "该平台仅支持单选、多选、判断题型,其他题型暂不支持", match: () => location.href.includes("/myHomework/answerRecord") || location.href.includes("/myHomework/assignment") || location.href.includes("/myExam/examDetails") || location.href.includes("/myExam/examHistory"), question: { html: ".option>div[id='answer-card-area']", question: ".ErichText", options: "ul>li>.ErichText", type: ".question-box .tag", workType: "ahjxjy", pageType: "ahjxjy" }, init: async () => { await waitUntil((function() { return isExist(".option>div[id='answer-card-area']"); })); // assignment/examDetails also match the ask rule. While submitting, never wait for IsAnswer. if (O(".submit-area").text().includes("提交")) return false; const hasPublishedAnswer = () => { var e; const t = null == (e = O("micro-app-body>#app>div")[0]) ? void 0 : e.__vue__; return (t && t.hierarchyList || []).some((e => (e.CourseQuestionOptionList || []).some((e => e.IsAnswer)))); }; if (hasPublishedAnswer()) return; // Brief grace for review-page Vue hydrate only — do not block ask for 12s. try { await waitUntil(hasPublishedAnswer, { timeout: 800 }); } catch { return false; } }, collect: async () => { var e; const t = null == (e = O("micro-app-body>#app>div")[0]) ? void 0 : e.__vue__; return (t && t.hierarchyList || []).map((n => { const a = typeMatch(n.name), r = titleClean(removeHtml(n.Content)), {options: i, answer: s} = (n.CourseQuestionOptionList || []).reduce(((e, t) => { const n = removeHtml(t.Content); return t.IsAnswer && e.answer.push(n), e.options.push(n), e; }), { options: [], answer: [] }), o = "3" === a ? [] : i, l = "3" === a ? [ judgeAnswer(s[0]) ] : s; return { question: r, options: o, answer: l, type: a, hash: questionHash(a, r, o) }; })); }, answerHook: (e, t) => { const n = O("micro-app-body>#app>div")[0].__vue__.hierarchyList[t]; e.type = typeMatch(n.name), e.question = titleClean(removeHtml(n.Content)); const {options: a, answer: r} = n.CourseQuestionOptionList.reduce(((e, t) => { const n = removeHtml(t.Content); return t.IsAnswer && e.answer.push(n), e.options.push(n), e; }), { options: [], answer: [] }); return e.options = a, e.answer = "3" === e.type ? [ judgeAnswer(r[0]) ] : r, "3" === e.type && (e.options = []), e; } }, { type: "ask", name: "\u5b89\u5fbd\u7ee7\u7eed\u6559\u80b2\u7b54\u9898(\u65b0\u7248)", tips: "\u5355\u9898\u95f4\u9694\u5fc5\u987b\u5927\u4e8e 3 \u79d2\uff01\uff01\u591a\u9009\u9898\u6bcf\u9009\u4e00\u9879\u90fd\u4f1a\u8bf7\u6c42\u63a5\u53e3\uff0c\u5df2\u81ea\u52a8\u653e\u6162\u9010\u9879\u70b9\u51fb\u901f\u5ea6\uff0c\u5426\u5219\u5bb9\u6613\u5f02\u5e38(403)\uff01\uff01", match: () => location.href.includes("/myHomework/assignment") || location.href.includes("/myExam/examDetails"), types: [ "0", "1", "3" ], minDelay: 3e3, answerDelay: 1e3, optionDelay: 2e3, question: { html: ".option>div[id='answer-card-area']", question: ".ErichText", options: "ul.answer-list>li", type: ".question-box .tag", workType: "ahjxjy", pageType: "ahjxjy" }, init: async () => { if (await waitUntil((function() { return isExist(".option>div[id='answer-card-area']"); })), !O(".submit-area").text().includes("\u63d0\u4ea4")) return false; const e = O("micro-app-body>#app>div")[0].__vue__, t = e.hierarchyList[0]; e.goAnchor(t.Id); }, collect: async () => { var e; const t = null == (e = O("micro-app-body>#app>div")[0]) ? void 0 : e.__vue__; return (t && t.hierarchyList || []).map((n => { const a = typeMatch(n.name), r = titleClean(removeHtml(n.Content)); let i = []; return (n.CourseQuestionOptionList || []).forEach((e => { i.push(removeHtml(e.Content)); })), { type: a, question: r, options: "3" === a ? [] : i, answer: [], html: "body", $options: () => O("ul.answer-list>li"), workType: "ahjxjy", pageType: "ahjxjy" }; })); }, toquestion: e => { const t = O("micro-app-body>#app>div")[0].__vue__, n = t.hierarchyList[e]; (null == n ? void 0 : n.Id) && t.goAnchor(n.Id); }, ischecked: e => e.hasClass("on"), questionHook: (e, t) => { const n = O("micro-app-body>#app>div")[0].__vue__.hierarchyList[t]; e.type = typeMatch(n.name), e.question = titleClean(removeHtml(n.Content)); let a = []; return n.CourseQuestionOptionList.forEach((e => { const t = removeHtml(e.Content); e.IsAnswer, a.push(t); })), e.options = a, e.html = "body", e.$options = () => O("ul.answer-list>li"), e; } }, { type: "ask", name: "\u5b89\u5fbd\u7ee7\u7eed\u6559\u80b2\u7b54\u9898(\u81ea\u8003)", tips: "", match: () => location.href.includes("/userinfo/testPaper"), types: [ "0", "1", "3" ], question: { html: ".item-card-area", question: ".desc", options: "ul>li", type: ".question-box .tag", workType: "ahjxjy", pageType: "ahjxjy" }, init: async () => { if (await waitUntil((function() { return isExist(".exam-paper-wrap"); })), isExist(".exam-process-area")) return false; const e = O(".exam-paper-wrap")[0].__vue__.topicList.map((e => e.getPaperList)).flat(); window.Zques = e; }, ischecked: e => e.parent().hasClass("checked"), questionHook: (e, t) => { const n = Zques[t]; e.type = typeMatch(n.questionTypeName), e.question = titleClean(removeHtml(n.content)); const {options: a, answer: r} = n.courseQuestionOptionList.reduce(((e, t) => { const n = removeHtml(t.content); return t.isAnswer && e.answer.push(n), e.options.push(n), e; }), { options: [], answer: [] }); return e.options = a, e.answer = "3" === e.type ? [ judgeAnswer(r[0]) ] : r, "3" === e.type && (e.options = []), e; }, setAnswer: e => { switch (e.type) { case "4": case "2": return O(e.html).find("textarea.answer-input").focus(), O(e.html).find(" textarea.answer-input"), O(e.html).find(".answer-input.edui-default").each(((t, n) => { let a = O(n).attr("id"), r = ie.UE.getEditor(a); r.ready((function() { r.setContent(`

    ${e.answer[t]}

    `); })); })), O(e.html).find(".answer-input").blur(), false; } return true; } }, { type: "save", name: "\u5b89\u5fbd\u7ee7\u7eed\u6559\u80b2\u6536\u5f55(\u81ea\u8003)", tips: "\u8be5\u5e73\u53f0\u4ec5\u652f\u6301\u5355\u9009\u3001\u591a\u9009\u3001\u5224\u65ad\u9898\u578b\uff0c\u5176\u4ed6\u9898\u578b\u6682\u4e0d\u652f\u6301", match: () => location.href.includes("/userinfo/testPaper"), question: { html: ".item-card-area", question: ".ErichText", options: "ul>li>.ErichText", type: ".question-box .tag", workType: "ahjxjy", pageType: "ahjxjy" }, init: async () => { if (await waitUntil((function() { return isExist(".exam-paper-wrap"); })), !isExist(".score-describe")) return false; const e = O(".exam-paper-wrap")[0].__vue__.topicList.map((e => e.getPaperList)).flat(); window.Zques = e; }, answerHook: (e, t) => { const n = Zques[t]; e.type = typeMatch(n.questionTypeName), e.question = titleClean(removeHtml(n.content)); const {options: a, answer: r} = n.courseQuestionOptionList.reduce(((e, t) => { const n = removeHtml(t.content); return t.isAnswer && e.answer.push(n), e.options.push(n), e; }), { options: [], answer: [] }); return e.options = a, e.answer = "3" === e.type ? [ judgeAnswer(r[0]) ] : r, "3" === e.type && (e.options = []), e; } } ], lettersToOptions = (e, t) => { if ("string" != typeof e) return []; const n = e.trim().toUpperCase(); if (!/^[A-Z]+$/.test(n) || new Set(n).size !== n.length) return []; const a = [ ...n ].map((e => t[e.charCodeAt(0) - 65])); return a.every((e => "string" == typeof e && e.trim())) ? a : []; }, buildQingshuAnswer = (e, t, n) => { if ("15" === e) { const e = [], n = []; return (t.subQuestions ?? []).forEach((t => { const a = (t.options ?? []).map((e => removeHtml(e.description ?? ""))); n.push(lettersToOptions(t.solution, a)), e.push(a); })), { options: e, answer: n.length && n.every((e => e.length)) ? n : [] }; } if ("3" === e) { const e = lettersToOptions(t.solution, n), a = 1 === e.length ? e[0] : "", r = isTrue(a ?? "") ? "\u6b63\u786e" : isFalse(a ?? "") ? "\u9519\u8bef" : ""; return { options: [], answer: r ? [ r ] : [] }; } if ("0" === e || "1" === e) { const a = lettersToOptions(t.solution, n); return { options: n, answer: "0" === e && 1 !== a.length ? [] : a }; } const a = removeHtml(t.solution ?? "").trim(); return { options: n, answer: a ? [ a ] : [] }; }, isQingshuPage = e => { try { const t = new URL(e); return /^https?:$/.test(t.protocol) && ("qingshuxuetang.com" === t.hostname || t.hostname.endsWith(".qingshuxuetang.com")) && /\/Student\/(?:ExercisePaper|ExamPaper|ViewQuiz|(?:SimulationExercise|Quiz)\/Detail)$/i.test(t.pathname) && [ "quizId", "id", "courseId" ].some((e => !!t.searchParams.get(e))); } catch { return false; } }, parseQingshuQuestion = e => { if (!e || "string" != typeof e.questionId || !e.questionId || "string" != typeof e.description) return null; if (null != e.options && (!Array.isArray(e.options) || e.options.length > 64)) return null; const t = e.options ?? [], n = t.map((e => "string" == typeof (null == e ? void 0 : e.label) ? e.label.trim().toUpperCase() : "")); if (n.some((e => !/^[A-Z]$/.test(e))) || new Set(n).size !== n.length || t.some((e => "string" != typeof (null == e ? void 0 : e.description)))) return null; const a = t.map((e => removeHtml(e.description))), r = []; n.forEach(((e, t) => { r[e.charCodeAt(0) - 65] = a[t]; })); const i = typeConvert(e.typeDesc ?? ""); if ([ "0", "1", "3" ].includes(i) && (a.length < 2 || a.some((e => !e)))) return null; const s = buildQingshuAnswer(i, e, r); return { id: e.questionId, question: removeHtml(e.description), options: "15" === i ? s.options : a, labels: n, type: i, answer: s.answer }; }, findQingshuQuestion = (e, t) => { const n = e.filter((e => (null == e ? void 0 : e.questionId) === t)); return 1 === n.length ? parseQingshuQuestion(n[0]) : null; }, resolveQingshuTargets = (e, t) => { const n = Array.from(e.querySelectorAll(".paper-container > .question-detail-container")).filter((e => e.id === t.id)); if (1 !== n.length || ![ "0", "1", "3" ].includes(t.type)) return null; const a = n[0], r = a.querySelector(".question-detail-description"); if (!r || normalizeComparableText(removeHtml(r.innerHTML)) !== normalizeComparableText(t.question)) return null; const i = Array.from(a.querySelectorAll(".question-detail-options > .question-detail-option")); if (i.length !== t.labels.length) return null; const s = t.labels.map(((e, n) => { var a; const r = i.filter((t => { var n; return (null == (n = t.querySelector("input.option-input")) ? void 0 : n.getAttribute("value")) === e; })); if (1 !== r.length) return null; const s = r[0], o = s.querySelector("input.option-input"), l = s.querySelector("label.option-label"), c = removeHtml((null == (a = s.querySelector(".option-description")) ? void 0 : a.innerHTML) ?? ""), u = normalizeComparableText(c) === normalizeComparableText(t.options[n]); return l && !o.disabled && o.type === ("1" === t.type ? "checkbox" : "radio") && u ? l : null; })); return s.every((e => !!e)) && new Set(s).size === s.length ? s : null; }, getQuestions$2 = () => { const e = ie.qsques; return Array.isArray(e) && e.length <= 500 ? e : []; }, waitForQuestions = async () => { try { return await waitUntil((() => getQuestions$2().length > 0), { timeout: 1e4, timeoutMessage: "\u9752\u4e66\u8bd5\u5377\u6570\u636e\u672a\u52a0\u8f7d\uff0c\u8bf7\u5237\u65b0\u540e\u91cd\u8bd5" }), !0; } catch (e) { return false; } }, ht = [ { type: "save", name: "\u9752\u4e66\u4f5c\u4e1a\u7b54\u6848\u6536\u5f55", match: () => isQingshuPage(location.href), question: { html: getQuestions$2, question: "", options: "", type: "", workType: "qingshu", pageType: "qingshu" }, init: async () => await waitForQuestions() && getQuestions$2().some((e => { var t; return null == (t = parseQingshuQuestion(e)) ? void 0 : t.answer.length; })), answerHook: e => { const t = e.html, n = t && findQingshuQuestion(getQuestions$2(), t.questionId ?? ""); return (null == n ? void 0 : n.answer.length) ? { ...e, ...n } : null; } }, { type: "ask", name: "\u9752\u4e66\u5b66\u5802\u4f5c\u4e1a\u7b54\u9898", tips: "\u56fe\u7247\u9898\u4fdd\u7559\u539f\u56fe\uff1b\u5e73\u53f0\u5df2\u8fd4\u56de\u7684\u6b63\u786e\u7b54\u6848\u4f18\u5148\u4f7f\u7528\u672c\u5730\u7f13\u5b58\u3002\u4e0d\u81ea\u52a8\u4ea4\u5377\u3002", match: () => { return isQingshuPage(location.href) && (e = location.href, !(isQingshuPage(e) && /\/Student\/ViewQuiz$/i.test(new URL(e).pathname))); var e; }, types: [ "0", "1", "3" ], question: { html: ".paper-container > .question-detail-container", question: ".question-detail-description", options: ".question-detail-options > .question-detail-option > label.option-label", type: ".question-detail-type-desc", workType: "qingshu", pageType: "qingshu" }, init: async () => { if (!(await waitForQuestions())) return false; try { return await waitUntil((() => !!document.querySelector(".paper-container input.option-input:not(:disabled)")), { timeout: 1e4 }), !0; } catch { return false; } }, ischecked: e => true === e.find("input.option-input").prop("checked"), toquestion: e => { var t, n, a; const r = null == (n = null == (t = getAskStore().questionList[e]) ? void 0 : t.qingshu) ? void 0 : n.id; r && (null == (a = ((e, t) => { const n = Array.from(e.querySelectorAll(".paper-container > .question-detail-container")).findIndex((e => e.id === t)); return n >= 0 ? e.getElementById(`group-item-${n + 1}`) : null; })(document, r)) || a.click()); }, questionHook: e => { const t = findQingshuQuestion(getQuestions$2(), e.html.id), n = t && resolveQingshuTargets(document, t); return t && n ? { ...e, ...t, qingshu: t, $options: O(n) } : null; }, setAnswerHook: ({ques: e}) => { const t = e.qingshu, n = t && findQingshuQuestion(getQuestions$2(), t.id), a = t && n && JSON.stringify([ n.question, n.options, n.labels, n.type ]) === JSON.stringify([ t.question, t.options, t.labels, t.type ]) ? resolveQingshuTargets(document, t) : null; if (!a) throw new Error("\u9752\u4e66\u9898\u76ee\u6216\u9009\u9879\u5df2\u53d8\u5316\uff0c\u8bf7\u5237\u65b0\u540e\u91cd\u8bd5"); e.$options = O(a); } } ], ft = [ { type: "save", name: "\u4f18\u8bfe\u5728\u7ebf\u6536\u5f55", match: () => "cce.org.uooconline.com" === location.host && (location.href.includes("/exam/paper") || location.href.includes("/exam/")), question: { html: ".queContainer", question: ".topic-title", options: ".el-radio-group label .label,.el-checkbox-group label .label", type: ".question-box .tag", workType: "uooc", pageType: "uooc" }, init: async () => { await waitUntil((function() { return 0 !== O(".queContainer").length; })); }, answerHook: e => { const t = ie.angular.element(e.html).scope().question; if (e.type = typeConvert(t.type_text), e.question = t.question, e.options = t.options_app.map((e => e.value)), e.answer = t.answer.map((e => t.options[e])), "3" === e.type) e.options = [], e.answer = judgeAnswer(e.answer[0]); return e; } } ], gt = [ { type: "ask", name: "\u4eac\u4eba\u5e73\u53f0\u7b54\u9898", tips: "", match: () => location.host.includes("cj-edu.com") && (location.href.includes("/Examination") || location.href.includes("/ExamInfo")), types: [ "0", "1", "3" ], question: { html: ".el-main>.all_subject>div.el-row", question: "div.stem", options: "ul li > label > span.el-radio__label > div:nth-child(2),ul li > label > span.el-checkbox__label > div:nth-child(2)", type: ".question-box .tag", workType: "cjedu", pageType: "cjedu" }, init: async () => { await waitUntil((function() { return 0 !== O(".el-main>.all_subject>div.el-row").length; })); }, ischecked: isParentChecked, questionHook: e => { switch (O(e.html).prevAll("h1").first().text().trim()) { case "\u5355\u9009\u9898": e.type = "0"; break; case "\u591a\u9009\u9898": e.type = "1"; break; case "\u5224\u65ad\u9898": e.$options = O(e.html).find("ul li>label"), e.options = [], e.type = "3"; } return e; } }, { type: "save", name: "\u4eac\u4eba\u5e73\u53f0\u4f5c\u4e1a\u6536\u5f55", match: () => location.host.includes("cj-edu.com") && location.href.includes("/ViewAnswerSheet"), question: { html: ".el-main>.all_subject>div.el-row", question: "p.stem", options: "ul li > label > span.el-radio__label > div:nth-child(2),ul li > label > span.el-checkbox__label > div:nth-child(2)", type: ".question-box .tag", workType: "cjedu", pageType: "cjedu" }, init: async () => { await waitUntil((function() { return 0 !== O(".el-main>.all_subject>div.el-row").length; })); }, answerHook: e => { let t = O(e.html).find(".seeStudentAnswer>p.answer").text().replace("\u53c2\u8003\u7b54\u6848\uff1a", "").trim(), n = O(e.html).prevAll("h1").first().text().trim(); switch (e.options.length > 0 && (e.answer = t.split(",").map((t => e.options[t.charCodeAt(0) - 65]))), n) { case "\u5355\u9009\u9898": e.type = "0"; break; case "\u591a\u9009\u9898": e.type = "1"; break; case "\u5224\u65ad\u9898": e.options = [], e.answer = judgeAnswer(t), e.type = "3"; } return e; } } ], vt = [ { type: "hook", name: "hook", match: location.host.includes("ytccr.com"), main: e => { observeVuePageChange(O("#app")[0], (() => getUrl())); } }, { type: "ask", name: "\u7ece\u901a\u7ee7\u6559\u4e91\u7b54\u9898", tips: "", match: () => location.host.includes("ytccr.com") && location.href.includes("learning-work") && location.href.includes("type=3"), types: [ "0", "1", "3" ], question: { html: ".border-item", question: ".title.qa-title", options: ".opts-list .opt-title-cnt", type: ".question-box .tag", workType: "ytccr", pageType: "ytccr" }, init: async () => { await waitUntil((function() { return 0 !== O(".border-item").length; })); }, ischecked: isParentChecked, questionHook: e => { if (e.type = typeConvert(O(e.html).find(".qtype").text().trim()), "3" === e.type) e.options = []; return e; } }, { type: "save", name: "\u7ece\u901a\u7ee7\u6559\u4e91\u6536\u5f55", match: () => location.host.includes("ytccr.com") && location.href.includes("learning-work") && location.href.includes("type=5"), question: { html: ".border-item", question: ".title.qa-title", options: ".opts-list .opt-title-cnt", type: ".question-box .tag", workType: "ytccr", pageType: "ytccr" }, init: async () => { await waitUntil((function() { return 0 !== O(".border-item").length; })); }, answerHook: e => { e.type = typeConvert(O(e.html).find(".qtype").text().trim()); let t = O(e.html).find(".u-text-success,.u-text-danger").text().split("\uff0c")[0].trim(); if (t = t.match(/[A-Z]+$/)[0].trim(), e.answer = t.split("").map((t => e.options[t.charCodeAt(0) - 65])), 0 === e.answer.length) return e; if ("3" === e.type) e.options = [], e.answer = judgeAnswer(e.answer[0]); return e; } } ], yt = [ { type: "ask", name: "\u5b66\u8d77\u8003\u8bd5", tips: "", match: () => location.href.includes("oxer/page/ots/examIndex.html"), types: [ "0", "1", "3" ], question: { html: ".queItemClass", question: "dt > div.din:eq(1)", options: "dd > div", type: ".question-box .tag", workType: "xueqi", pageType: "xueqi" }, init: async () => { await waitUntil((function() { return isExist(".queItemClass"); })), ie.document.onkeydown = null, ie.oncontextmenu = null; }, ischecked: e => e.parent().hasClass("cur"), questionHook: e => { let t = O(e.html).parent().find("div .fb:eq(0)").text().split("\u3001")[1]; if (t.includes("\u5224\u65ad") && (t = "\u5224\u65ad\u9898"), e.type = typeMatch(t), "3" === e.type) e.options = [], e.$options = O(e.html).find("input"); return e; }, setAnswer: e => { if ("3" === e.type) { let t = e.answer; return e.ques.$options.each(((e, n) => { isTrue(t) && isTrue(removeHtml(O(n).val())) && O(n).click(), isFalse(t) && isFalse(removeHtml(O(n).val())) && O(n).click(); })), false; } return true; } }, { type: "save", name: "\u5b66\u671f\u8003\u8bd5\u6536\u5f55", match: () => location.href.includes("OTS-UniverDetail.html"), question: { html: ".dl_list", question: "dt > div.fl:eq(1)", options: "dd > var", type: ".question-box .tag", workType: "xueqi", pageType: "xueqi" }, init: async () => { await waitUntil((function() { return isExist(".dl_list"); })); }, answerHook: e => { var t, n, a; const r = O(e.html).attr("queid"), i = e.html._ms_context_.el.questions.find((e => e.id === r)); e.type = typeMatch(i.questionTypeName.includes("\u5224\u65ad") ? "\u5224\u65ad\u9898" : i.questionTypeName), e.question = removeHtml(i.stem); const s = (null == (t = i.answerArea) ? void 0 : t.optionList) || [], o = "0" === e.type || "1" === e.type; if (o) { const t = O(e.html).find("dd > span").map(((e, t) => O(t).text().trim())).get(); if (e.options.length < 2 || e.options.length !== s.length || t.length !== e.options.length || t.some(((e, t) => e !== String.fromCharCode(65 + t))) || e.options.some((e => !e.trim()))) return null; } o || (e.options = s.map((e => removeHtml(e.content)))); if (!!!((null == (n = i.answer) ? void 0 : n.ans) || Array.isArray(null == (a = i.answer) ? void 0 : a.ansL) && i.answer.ansL.length) && (o || 0 === i.answerScore)) return null; const l = ((e, t, n) => { const a = t || {}, r = a.ans || (Array.isArray(a.ansL) ? a.ansL.join("") : ""); if ("3" === e) return { answer: judgeAnswer(String(r)), options: [] }; if ("0" === e || "1" === e) { if (r) { const t = String(r).split(""), a = t.map((e => n[e.charCodeAt(0) - 65])); return !/^[A-Z]+$/.test(String(r)) || new Set(t).size !== t.length || "0" === e && 1 !== t.length || a.some((e => "string" != typeof e || !e.trim())) ? { answer: [], options: n } : { answer: a, options: n }; } return { answer: [], options: n }; } return { answer: (Array.isArray(a.ansL) && a.ansL.length > 0 ? a.ansL : a.ans ? [ a.ans ] : []).map((e => removeHtml(String(e)))).filter(Boolean), options: n }; })(e.type, i.answer, e.options); return 0 === l.answer.length ? null : (e.answer = l.answer, e.options = l.options, e); }, paper: e => { const t = O(".dl_list:eq(0)")[0]._ms_context_.loop.category, n = O(".dl_list:eq(0)")[0]._ms_context_.oAnswerDetailInfo, a = { platform: "xueqi" }; a.hash = t.code, a.name = t.value, a.info = {}, a.chapter = [ { hash: `${n.arrangementid}`, name: n.arrangementname, question: e } ], et.setPaper(a.hash, a); } } ], bt = [ { type: "hook", name: "hook", match: "gdrtvu.exam-cloud.cn" === location.host, main: e => { observeVuePageChange(O("#app")[0], getUrl); } }, { type: "ask", name: "\u7b54\u9898", tips: "\u516c\u544a", match: () => location.host.includes("exam-cloud.cn") && location.href.includes("oe-web/online-exam/exam"), types: [ "0", "1", "3" ], question: { html: ".question-container", question: ".question-body:first", options: ".option .question-options", type: ".question-header .container", workType: "guangkai", pageType: "guangkai" }, init: async () => { await waitUntil((function() { return isExist(".question-container"); })); }, ischecked: isParentChecked, questionHook: e => { let t = O(".list .current-question").parent().parent().find(".title").text(); if (console.log(t), t = t.split("\u3001")[1], t = t.replace(/\(.*\)/, "").trim(), console.log(t), e.type = typeConvert(t), "8" == e.type ? e.type = typeMatch(t) : e.type, "3" === e.type) e.options = []; return e; }, finish: e => { O(".next .qm-primary-button").length && O(".next .qm-primary-button")[0].click(); } } ], wt = [ { type: "hook", name: "hook", match: location.host.includes("open.ha.cn"), main: e => { const getHash = () => O(".stuHomeworkVersionId.active").attr("id"); ie.mainClass = getHash(); let t = new MutationObserver((async e => { getHash(), ie.mainClass !== getHash() && (ie.mainClass = getHash(), vuePageChange(), t.disconnect()); })); O(".homeworkBody").length >= 1 && t.observe(O(".homeworkBody")[0], { subtree: true, attributes: true, childList: true }); } }, { type: "ask", name: "\u4e91\u4e0a\u6cb3\u5f00\u7b54\u9898", tips: "", match: () => location.host.includes("open.ha.cn") && location.href.includes("/homework/showHomeworkByStatus") && location.href.includes("checked=false"), types: [ "0", "1" ], question: { html: ".layui-colla-content > .insert", question: ".window-title", options: ".option-title", type: ".question-box .tag", workType: "openha", pageType: "openha" }, init: async () => { await waitUntil((function() { return isExist(".layui-colla-content > .insert"); })); }, ischecked: isParentChecked, questionHook: e => (e.options = e.$options.map(((t, n) => { let a = O(n).find(".numberCover").text().trim(); return removeHtml(e.$options.eq(t).html()).replace(a, "").trim(); })).get(), e.type = typeConvert(O(e.html).find(".questionDiv>.float-l:eq(1)").text().trim()), e.$options = O(e.html).find(".option-title .numberCover"), e) }, { type: "save", name: "\u4e91\u4e0a\u6cb3\u5f00\u6536\u5f55", match: () => location.host.includes("open.ha.cn") && location.href.includes("/homework/showHomeworkByStatus") && location.href.includes("checked=true"), question: { html: ".layui-colla-content > .insert", question: ".window-title", options: ".option-title", type: ".question-box .tag", workType: "openha", pageType: "openha" }, init: async () => { await waitUntil((function() { return isExist(".layui-colla-content > .insert"); })); }, answerHook: e => { let t = []; const n = 0 == O(e.html).find(".option-title.error2").length; if (e.options = e.$options.map(((n, a) => { let r = O(a).find(".numberCover").text().trim(), i = removeHtml(e.$options.eq(n).html()).replace(r, "").trim(); return O(a).hasClass("answer-title") && t.push(i), i; })).get(), e.type = typeConvert(O(e.html).find(".questionDiv>.float-l:eq(1)").text().trim()), n) return e.answer = t, O(e.html).find(".option-title.error2"), e; }, paper: e => { const t = ie.homework, n = { platform: "openha" }; n.hash = t.courseId, n.name = t.courseName, n.info = {}, n.chapter = [ { hash: `${t.homeworkId}`, name: t.title, question: e } ], et.setPaper(n.hash, n); } } ], xt = [ { type: "ask", name: "\u6cb3\u5357\u7ee7\u7eed\u6559\u80b2\u7b54\u9898", tips: "", match: () => location.href.includes("uc/task/startTask"), types: [ "0", "1" ], answerDelay: 1e3, minDelay: 1e3, question: { html: ".carousel-inner>.item.changeless-box", question: ".exam-tg-txt__wrap.e-tg-box", options: ".ic-options-list address", type: ".question-box .tag", workType: "cloudwis", pageType: "cloudwis" }, init: async () => { if (await waitUntil((function() { return isExist(".carousel-inner>.item.changeless-box"); })), !isExist("#finish")) return false; await waitUntil((function() { let e = O(".carousel-inner>article").filter(((e, t) => O(t).hasClass("temporary-box"))).eq(0).index(); return e > 0 ? (O(".slide-tihao:eq(" + e + ")")[0].click(), !1) : (O(".slide-tihao:eq(0)")[0].click(), !0); })); }, toquestion: e => { O(".slide-tihao:eq(" + e + ")")[0].click(); }, ischecked: e => e.find(".checked").length > 0, questionHook: e => (e.type = typeConvert(O(e.html).attr("data-name") || ""), e.$options = O(e.html).find(".ic-options__wrap label"), e.question = e.question.replace(/^\(\d+\)/, "").trim(), e.question = e.question.replace(/\(\d+\u5206\)$/, "").trim(), e) }, { type: "ask", name: "\u6cb3\u5357\u7ee7\u7eed\u6559\u80b2\u8003\u8bd5\u7b54\u9898", tips: "", match: () => location.href.includes("uc/exam/record/startExamination"), types: [ "0", "1" ], question: { html: ".trunk-box", question: ".exam-tg-txt__wrap.e-tg-box", options: ".ic-options-list address", type: ".question-box .tag", workType: "cloudwis", pageType: "cloudwis" }, init: async () => { if (await waitUntil((function() { return isExist(".trunk-box") && isExist(".ic-ac-checkbox-ol"); })), await waitUntil((function() { return window.scrollTo(0, document.body.scrollHeight), O(".ic-ac-checkbox-ol li").length == O(".trunk-box").length; })), !isExist("#submit-btn")) return false; }, next: () => { O("#carousel-professional").carousel("next"); }, ischecked: e => e.find(".checked").length > 0, questionHook: e => { const t = O(e.html).attr("data-type"); switch (console.log(t), t) { case "1": e.type = "0"; break; case "2": e.type = "1"; break; case "3": e.type = "3", e.options = []; } return e.question = e.question.replace(/^\d+\u3001/, "").trim(), e.question = e.question.replace(/\(\d+\u5206\)$/, "").trim(), e.question = e.question.replace(/\[\S+\]$/, "").trim(), e.$options = O(e.html).find(".ic-options__wrap label"), e; } }, { type: "save", name: "\u6cb3\u5357\u7ee7\u7eed\u6559\u80b2\u6536\u5f55", match: () => location.href.includes("uc/task/startTask"), question: { html: ".carousel-inner>.item.changeless-box", question: ".exam-tg-txt__wrap.e-tg-box", options: ".ic-options-list address", type: ".question-box .tag", workType: "cloudwis", pageType: "cloudwis" }, init: async () => { if (await waitUntil((function() { return isExist(".carousel-inner>.item.changeless-box") && isExist(".slide-tihao"); })), isExist("#finish")) return false; await waitUntil((function() { let e = O(".carousel-inner>article").filter(((e, t) => O(t).hasClass("temporary-box"))).eq(0).index(); return e > 0 ? (O(".slide-tihao:eq(" + e + ")")[0].click(), !1) : (O(".slide-tihao:eq(0)")[0].click(), !0); })); }, answerHook: e => { const t = O(e.html).find(".analysis-box .fs20.c-primary.vam").text().trim().split(""); return e.type = typeConvert(O(e.html).attr("data-name") || ""), e.answer = t.map((t => e.options[t.charCodeAt(0) - 65])), e.question = e.question.replace(/^\(\d+\)/, "").trim(), e.question = e.question.replace(/\(\d+\u5206\)$/, "").trim(), e; } }, { type: "save", name: "\u6cb3\u5357\u7ee7\u7eed\u6559\u80b2\u8003\u8bd5\u6536\u5f55", match: () => location.href.includes("uc/exam/record/startExamination"), question: { html: ".trunk-box.answer-question", question: ".exam-tg-txt__wrap.e-tg-box", options: ".ic-options-list address", type: ".question-box .tag", workType: "cloudwis", pageType: "cloudwis" }, init: async () => { if (await waitUntil((function() { return isExist(".trunk-box") && isExist(".ic-ac-correct"); })), await waitUntil((function() { return window.scrollTo(0, document.body.scrollHeight), O(".ic-ac-correct,.ic-ac-error").length == O(".trunk-box").length; })), isExist("#submit-btn")) return false; }, next: () => { O(".next-slide").click(); }, answerHook: e => { const t = O(e.html).attr("data-type"); console.log(t); const n = O(e.html).find(".ic-options__wrap label").filter(((e, t) => O(t).find(".checked").length > 0)).map(((e, t) => removeHtml(O(t).html()))).get(); switch (e.answer = n.map((t => e.options[t.charCodeAt(0) - 65])), e.question = e.question.replace(/^\d+\u3001/, "").trim(), e.question = e.question.replace(/\(\d+\u5206\)$/, "").trim(), e.question = e.question.replace(/\[\S+\]$/, "").trim(), t) { case "1": e.type = "0"; break; case "2": e.type = "1"; break; case "3": e.type = "3", e.options = [], e.answer = judgeAnswer(e.answer[0]); } return e; } } ], kt = [ { type: "hook", name: "hook", match: location.host.includes("sclecb.cn"), main: e => { observeVuePageChange(O("#app")[0], (() => getUrl())); } }, { type: "ask", name: "\u56db\u5ddd\u5f00\u653e\u5927\u5b66\u7b54\u9898", tips: "", match: () => "study.sclecb.cn" === location.host && /\/[0-9]+\/show/i.test(location.href), types: [ "0", "1", "3" ], question: { html: ".testpaper-question.js-testpaper-question", question: ".testpaper-question-stem", options: ".testpaper-question-choices li", type: ".question-box .tag", workType: "sclecb", pageType: "sclecb" }, init: async () => { await waitUntil((function() { return isExist(".testpaper-question.js-testpaper-question"); })); }, ischecked: e => e.hasClass("checked"), questionHook: e => { switch (e.options = removeStartChar(e.options), e.$options = O(e.html).find(".testpaper-question-choice-inputs > label > input"), e.type = typeConvert(O(e.html).parent().parent().find(".panel-heading>strong").text().trim()), e.type, e.type) { case "0": case "1": break; case "3": e.$options = O(e.html).find(".radio-inline"); } return e; } }, { type: "ask", name: "\u56db\u5ddd\u5f00\u653e\u5927\u5b66\u7b54\u9898\u65e7", tips: "", match: () => location.host.includes("sclecb.cn") && /student\/course\/study\/[0-9a-zA-Z]+\/test\/redo/i.test(location.href), types: [ "0", "1" ], question: { html: ".questiono-item", question: ".clearfix.questiono-header h6", options: ".common_test_option .processing_img", type: ".question-box .tag", workType: "sclecb", pageType: "sclecb" }, init: async () => { await waitUntil((function() { return isExist(".questiono-item"); })); }, ischecked: e => e.hasClass("checked"), questionHook: e => { const t = O(e.html).parent().parent().find("div:eq(0)").text().trim(); switch (true) { case t.includes("\u5355\u9009\u9898"): e.type = "0"; break; case t.includes("\u591a\u9009\u9898"): e.type = "1"; break; case t.includes("\u5224\u65ad\u9898"): e.type = "3", e.options = [], e.$options = O(e.html).find(".common_test_option > label"); break; default: return; } return e; } }, { type: "save", name: "\u56db\u5ddd\u5f00\u653e\u5927\u5b66\u6536\u5f55", match: () => "study.sclecb.cn" === location.host && (/task\/[0-9]+\/activity_show/i.test(location.href) || /result\/[0-9]+\/show/i.test(location.href)), question: { html: ".testpaper-question.js-testpaper-question", question: ".testpaper-question-stem", options: ".testpaper-question-choices li", type: ".question-box .tag", workType: "sclecb", pageType: "sclecb" }, init: async () => { await waitUntil((function() { return isExist(".testpaper-question.js-testpaper-question"); })); }, answerHook: (e, t) => { let n = []; e.options = e.$options.map(((e, t) => { const a = removeHtml(O(t).clone().find(".testpaper-question-choice-index").remove().end().html()); return O(t).hasClass("testpaper-question-choice-right") && n.push(a), a; })).get(), e.answer = n, e.type = typeConvert(O(".js-panel-card>span").eq(t).prevAll("p").first().text().trim()); const a = O(".js-panel-card>span").eq(t).hasClass("bg-success"); switch (e.type) { case "0": case "1": break; case "3": let t = ""; t = O(e.html).find(".testpaper-question-result").text().replace("\u4f60\u7684\u7b54\u6848\u662f", "").trim(), e.answer = judgeAnswer(t); } if ((a || !(e.answer.length > 0) || "3" != e.type) && a) return e; } } ], qt = [ { type: "hook", name: "hook", match: location.host.includes("superchutou.com"), main: e => { observeVuePageChange(O("#root")[0], (() => getUrl())); } }, { type: "ask", name: "\u51fa\u5934\u7cfb\u7edf\u7b54\u9898", tips: "", match: () => location.host.includes("superchutou.com") && location.href.includes("onlineclass/exam/"), types: [ "0", "1" ], question: { html: "[class^='single_excer_item']", question: "[class^='title_content'] > [class^='title_content_text']:eq(1)", options: "[class^='options_content'] label", type: ".question-box .tag", workType: "chutou", pageType: "chutou" }, init: async () => { await waitUntil((function() { return isExist("[class^='single_excer_item']"); })); }, ischecked: isParentChecked, questionHook: e => { let t = O(e.html).find("[class^='title_content'] > span:eq(1)").text(); if (t = t.replace(/\u3010|\u3011/g, "").trim(), e.type = typeConvert(t), e.options = removeStartChar(e.options), "3" === e.type) e.options = []; return e; } }, { type: "save", name: "\u51fa\u5934\u6536\u5f55", match: () => location.host.includes("superchutou.com") && location.href.includes("/onlineclass/analysis/"), question: { html: "[class^='single_excer_item']", question: "[class^='title_content'] > [class^='title_content_text']:eq(1)", options: "[class^='options_content'] label", type: ".question-box .tag", workType: "chutou", pageType: "chutou" }, init: async () => { await waitUntil((function() { return isExist("dl>dd>span"); })); }, answerHook: e => { let t = O(e.html).find("[class^='title_content'] > span:eq(1)").text(); t = t.replace(/\u3010|\u3011/g, "").trim(), e.type = typeConvert(t), e.options = removeStartChar(e.options); const n = O(e.html).find(".ant-collapse-header>div.ant-row>div.ant-col.ant-col-18>div:eq(1)").text().replace("\u53c2\u8003\u7b54\u6848\uff1a", "").trim(); switch (e.type) { case "0": case "1": e.answer = n.split("").map((t => e.options[t.charCodeAt(0) - 65])); break; case "3": e.options = [], e.answer = judgeAnswer(n); } return e; } } ], At = [ { type: "ask", name: "\u826f\u5e08\u5728\u7ebf\u7b54\u9898", tips: "", match: () => location.host.includes("ls365.net") && (location.href.includes("student/examing.aspx") || location.href.includes("Student/myhomework.aspx")), types: [ "0", "1" ], question: { html: ".exam_question", question: ".exam_question_title", options: ".question_select .select_detail", type: ".exam_question_title strong", workType: "ls365", pageType: "ls365" }, init: async () => { await waitUntil((function() { return isExist(".exam_question"); })); }, ischecked: isParentChecked, questionHook: e => { let t = O(e.html).find(".exam_question_title").clone(); t.find(".question_number").remove(), t.find("strong").remove(), t.find(".exam_feed_back").remove(), e.question = removeHtml(t.html()); let n = O(e.html).find(".exam_question_title strong").text(); return n = n.replace(/\[|\]/g, "").trim(), e.type = typeConvert(n), e; } }, { type: "save", name: "\u826f\u5e08\u5728\u7ebf\u8003\u8bd5\u6536\u5f55", match: () => location.host.includes("ls365.net") && location.href.includes("User/Student/ViewPaper.aspx"), question: { html: "[name^='anchor_']", question: ".title-img-ctr", options: ".pold .phtml", type: ".QuestionsType", workType: "ls365", pageType: "ls365" }, init: async () => { await waitUntil((function() { return isExist("[name^='anchor_']"); })); }, answerHook: e => { let t = O(e.html).find(".QuestionsType").text(); t = t.replace(/\[|\]/g, "").trim(), e.type = typeConvert(t); let n = O(e.html).find(".my-work-answer>p").filter(((e, t) => t.innerText.includes("\u53c2\u8003\u7b54\u6848"))).map(((e, t) => O(t).find(".two").text())).get(); if (0 !== n.length) return e.answer = n[0].split("").map((t => e.options[t.charCodeAt(0) - 65])), e; } }, { type: "save", name: "\u826f\u5e08\u5728\u7ebf\u4f5c\u4e1a\u6536\u5f55", match: () => location.host.includes("ls365.net") && location.href.includes("Student/myhomework_after.aspx"), question: { html: "[name^='anchor_']", question: ".my-work-nav>.col-md-10", options: ".pold .phtml", type: ".QuestionsType", workType: "ls365", pageType: "ls365" }, init: async () => { await waitUntil((function() { return isExist("[name^='anchor_']"); })); }, answerHook: e => { let t = O(e.html).find(".my-work-nav>div:eq(0)>span:eq(0)").text(); t = t.replace(/\[|\]/g, "").trim(), e.type = typeConvert(t); let n = O(e.html).find(".my-work-answer>p").filter(((e, t) => t.innerText.includes("\u53c2\u8003\u7b54\u6848"))).map(((e, t) => O(t).find(".two").text())).get(); if (0 !== n.length) return e.answer = n[0].split("").map((t => e.options[t.charCodeAt(0) - 65])), e; } }, { type: "hook", name: "hook", match: "hbnun.lsedu.vip" === location.host, main: e => { observeVuePageChange(O("#app")[0], (() => getUrl())); } }, { type: "ask", name: "\u826f\u5e08\u5728\u7ebf\u4f5c\u4e1a\u7b54\u9898", tips: "", match: () => location.href.includes("/#/homework/") && !location.href.includes("scene=history"), types: [ "0", "1" ], question: { html: "[id^='question-']", question: ".question-content", options: "button .flex-1.text-left", type: ".self-start.text-3.self-end", workType: "ls365", pageType: "ls365" }, init: async () => { await waitUntil((function() { return isExist("[id^='question-']"); })); }, ischecked: e => O(e).closest("button").hasClass("is-checked") || O(e).closest("button").hasClass("el-button--primary"), questionHook: e => { let t = O(e.html).find(".self-start.text-3.self-end").text(); return t && (t = t.replace(/\[|\]/g, "").trim(), e.type = typeMatch(t)), e; } }, { type: "save", name: "\u826f\u5e08\u5728\u7ebf\u4f5c\u4e1a\u6536\u5f55", match: () => location.href.includes("/#/homework/") && location.href.includes("scene=history"), question: { html: "[id^='question-']", question: ".question-content", options: ".flex.flex-col.space-y-2 .f-c-c.space-x-3 .flex-1", type: ".self-start.text-3.self-end", workType: "ls365", pageType: "ls365" }, init: async () => { await waitUntil((function() { return isExist("[id^='question-']"); })); }, answerHook: e => { let t = O(e.html).find(".self-start.text-3.self-end").text(); t && (t = t.replace(/\[|\]/g, "").trim(), e.type = typeMatch(t)); let n = ""; if (O(e.html).find("div").each(((e, t) => { const a = O(t); if ((a.find("span").filter(((e, t) => O(t).text().trim().includes("\u6807\u51c6\u7b54\u6848\uff1a"))).length > 0 || a.text().trim().includes("\u6807\u51c6\u7b54\u6848\uff1a")) && (n = a.find(".question-content").text().trim(), n)) return false; })), n) return e.answer = n.split("").map((t => { const n = t.charCodeAt(0) - 65; return e.options && e.options[n] ? e.options[n] : null; })).filter((e => null !== e)), e; } } ], _t = [ { type: "hook", name: "hook", match: location.host.includes("jijiaox.com"), main: e => { observeVuePageChange(O("#app")[0], (() => O("#app")[0].__vue__.$route.path)); } }, { type: "ask", name: "\u7ee7\u6559\u4e91\u8003\u8bd5\u7b54\u9898", tips: "", match: () => location.host.includes("jijiaox.com") && (location.href.includes("/mg/studentindexexam/") || !location.href.includes("examrec")), types: [ "0", "1", "3", "4" ], question: { html: ".question>div", question: ".topic-title", options: ".ml_2 label", type: ".question-box .tag", workType: "jijiaox", pageType: "jijiaox" }, init: async () => { await waitUntil((function() { return isExist(".question>div"); })); }, ischecked: e => e.hasClass("is-checked"), questionHook: (e, t) => { const n = O(".page")[0].__vue__.$data.testInfo.studentPraxisList[t]; switch (e.options = n.options ? n.options : [], "string" == typeof e.options && (e.options = []), e.question = removeHtml(n.title), n.type) { case "single": e.type = "0"; break; case "muti": e.type = "1"; break; case "charge": e.type = "3"; break; case "text": e.type = "4"; break; default: console.log(n.type, "\u672a\u77e5\u7c7b\u578b"); } return e; }, setAnswer: e => "4" !== e.type || (O(e.html).find(".editor")[0].__vue__.editor.txt.html(e.answer[0]), false) }, { type: "save", name: "\u7ee7\u6559\u4e91\u8003\u8bd5\u6536\u5f55", match: () => location.host.includes("jijiaox.com") && location.href.includes("/mg/studentindexexam/examrec/"), question: { html: ".question>div", question: ".topic-title", options: ".el-radio-group label .label,.el-checkbox-group label .label", type: ".question-box .tag", workType: "jijiaox", pageType: "jijiaox" }, init: async () => { await waitUntil((function() { return isExist(".question>div"); })); }, answerHook: (e, t) => { const n = O(".page")[0].__vue__.$data.testInfo.studentPraxisList[t], a = n.answer; switch (e.options = n.options ? n.options : [], "string" == typeof e.options && (e.options = []), e.question = removeHtml(n.title), n.type) { case "single": e.type = "0"; break; case "muti": e.type = "1"; break; case "charge": e.type = "3", e.answer = "1" == a ? [ "\u6b63\u786e" ] : "-1" == a ? [ "\u9519\u8bef" ] : []; break; case "text": e.type = "4", e.answer = [ removeHtml(a) ]; break; default: console.log(n.type, "\u672a\u77e5\u7c7b\u578b"); } switch (e.type) { case "0": case "1": console.log("________", a), e.answer = "string" == typeof a ? a.split("").map((t => e.options[t.charCodeAt(0) - 65])) : a.map((t => (console.log(t), e.options[t.charCodeAt(0) - 65]))); } return console.log(e), e; } } ], Tt = /^(?:\u5bf9|\u9519|\u6b63\u786e|\u9519\u8bef|\u662f|\u5426|\u221a|\xd7|true|false|T|F)$/i; function parseWencaiHomework(e, t) { var n, a; const r = e.querySelectorAll('table[isitem="1"]'); if (1 !== r.length) return null; const i = r[0], s = null == (n = i.rows[0]) ? void 0 : n.cells[0]; if (!s) return null; const o = s.cloneNode(true); o.querySelectorAll("script, input, textarea").forEach((e => e.remove())), o.querySelectorAll("font, nobr").forEach((e => { /\[\u53c2\u8003\u7b54\u6848[\uff1a:]/.test(e.textContent ?? "") && e.remove(); })); const l = t(o.innerHTML); if (!l) return null; const c = i.querySelectorAll('table[isitemoption="1"]'); if (c.length > 1) return null; const u = c[0], p = Array.from((null == u ? void 0 : u.querySelectorAll("label")) ?? []), d = p.map((e => t(e.innerHTML))), m = null == (a = null == u ? void 0 : u.getAttribute("optiontype")) ? void 0 : a.toLowerCase(), h = Array.from(s.querySelectorAll('input[type="text"], input:not([type])')); let f; if ("radio" === m || "checkbox" === m) { if (h.length || d.length < 2 || d.some((e => !e)) || new Set(d).size !== d.length) return null; const e = 2 === d.length && d.every((e => Tt.test(e))) && 2 === new Set(d.map((e => judgeAnswer(e)[0]))).size; f = "checkbox" === m ? "1" : e ? "3" : "0"; } else { if (u || !h.length) return null; f = "2"; } const g = p.map((e => { var t, n; const a = e.closest("tr"), r = null == a ? void 0 : a.querySelector('input[type="radio"],input[type="checkbox"]'); return (null == r ? void 0 : r.value) || (null == (n = null == (t = null == a ? void 0 : a.textContent) ? void 0 : t.match(/\(([A-Z])\)/)) ? void 0 : n[1]) || ""; })); return p.length && (g.some((e => !/^[A-Z]$/.test(e))) || new Set(g).size !== g.length) ? null : { question: l, options: "3" === f ? [] : d, type: f, labels: p, inputs: h, codes: g, optionTexts: d, table: i, title: s }; } const isJudgeOptions$1 = e => Array.isArray(e) && 2 === e.length && e.every((e => isTrue(e) || isFalse(e))), Ct = [ { type: "hook", name: "hook", match: location.host.includes("wencaischool.net") && O("#app").length, main: e => { observeVuePageChange(O("#app")[0], (() => O("#app")[0].__vue__.$route.path)); const t = document.createElement("style"); t.type = "text/css", t.innerHTML = "* {\n font-size: 13px !important;\n }", document.head.appendChild(t); } }, { type: "save", name: "\u67e0\u6aac\u6587\u624d\u8003\u8bd5\u6536\u5f55", match: () => location.host.includes("wencaischool.net") && location.href.includes("/separation/exam/index.html"), question: { html: ".tmList", question: ".tmTitleTxt", options: ".perRad .opCont", type: ".question-box .tag", workType: "wencai", pageType: "wencai" }, init: async () => { await waitUntil((function() { return isExist(".tmList") && O("#onlineExamArea")[0].__vue__._data.itemsList.length > 0; })); return !(true !== O("#onlineExamArea")[0].__vue__._data.ifShowResult); }, answerHook: (e, t) => { const n = O("#onlineExamArea")[0].__vue__._data.itemsList[t]; e.question = removeHtml(n.itemName), e.options = n.optionNodes.map((e => removeHtml(e.optionContent))); e.type = typeConvert({ 1: "\u586b\u7a7a\u9898", 2: "\u7b80\u7b54\u9898", 3: "\u5355\u9009\u9898", 4: "\u591a\u9009\u9898", 5: "\u9605\u8bfb\u7406\u89e3", 12: "\u5b8c\u5f62\u586b\u7a7a" }[n.itemType]); let a = n.itemAnswer[0].optionContent; if ("0" === e.type && isJudgeOptions$1(e.options)) { const t = e.options[a.charCodeAt(0) - 65]; return e.type = "3", e.answer = judgeAnswer(t), e.options = [], e; } switch (e.type) { case "0": case "1": e.answer = a.split("").map((t => e.options[t.charCodeAt(0) - 65])); break; case "4": e.answer = removeHtml(a); break; case "2": e.answer = n.itemAnswer.map((e => removeHtml(e.optionContent))); } return e; } }, { type: "ask", name: "\u67e0\u6aac\u6587\u624d\u8003\u8bd5\u7b54\u9898", tips: "\u6b64\u5e73\u53f0\u7b54\u9898\u95f4\u9694\u5c3d\u91cf3s\u5de6\u53f3\uff0c\u5426\u5219\u53ef\u80fd\u9009\u4e0d\u4e0a\u7b54\u6848", match: () => location.host.includes("wencaischool.net") && location.href.includes("/separation/exam/index.html"), types: [ "0", "1", "2", "3", "4", "5", "6", "7", "14" ], minDelay: 4e3, answerDelay: 1e3, question: { html: ".tmList", question: ".tmTitleTxt", options: ".perRad .opCont", type: ".question-box .tag", workType: "wencai", pageType: "wencai" }, init: async () => { await waitUntil((function() { return isExist(".tmList") && O("#onlineExamArea")[0].__vue__._data.itemsList.length > 0; })); }, ischecked: e => e[0].checked, questionHook: e => { let t = O(e.html).find(".tmc.tm").attr("ttype"); return e.type = typeConvert({ 1: "\u586b\u7a7a\u9898", 2: "\u7b80\u7b54\u9898", 3: "\u5355\u9009\u9898", 4: "\u591a\u9009\u9898", 5: "\u9605\u8bfb\u7406\u89e3", 12: "\u5b8c\u5f62\u586b\u7a7a" }[t]), e.$options = O(e.html).find(".perRad input"), "0" === e.type && isJudgeOptions$1(e.options) && (e.type = "3", e.options = []), e; }, setAnswer: async e => { const fillInput = (e, t) => { const n = null == t ? "" : String(t), a = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(e), "value"); e.focus(), a && a.set ? a.set.call(e, n) : e.value = n, e.dispatchEvent(new Event("input", { bubbles: true })), e.dispatchEvent(new Event("change", { bubbles: true })), e.blur(); }; switch (e.type) { case "4": { const t = O(e.html).find("textarea")[0]; return t && fillInput(t, e.answer[0]), false; } case "2": { const t = O(e.html).find(".ansbox.inputAnswer input").toArray(), n = Array.isArray(e.answer) ? e.answer : [ e.answer ]; for (let e = 0; e < t.length; e++) { const a = n[e]; null != a && (fillInput(t[e], a), await sleep(300)); } return false; } case "3": { const t = Array.isArray(e.answer) ? e.answer[0] : e.answer; return O(e.html).find(".perRad").each(((e, n) => { const a = removeHtml(O(n).find(".opCont").html()), r = O(n).find("input")[0]; r && (isTrue(t) && isTrue(a) || isFalse(t) && isFalse(a)) && r.click(); })), false; } } return true; } }, { type: "ask", name: "\u67e0\u6aac\u6587\u624d\u4f5c\u4e1a\u7b54\u9898", tips: "", match: () => location.host.includes("wencaischool.net") && location.href.includes("/exam/portal/exam.jsp"), types: [ "0", "1", "2", "3" ], question: { html: "table[id^='tblItem_'][islabel='0']", question: "table>tbody>tr:eq(0)>td:eq(0)", options: "table>tbody>tr:eq(1)>td:eq(0) table>tbody>tr>td>label", type: ".question-box .tag", workType: "wencai", pageType: "wencai" }, init: async () => { await waitUntil((function() { return isExist("table[id^='tblItem_'][islabel=0]"); })), O(".aah_wrapper>div").css("z-index", 9999); }, ischecked: e => { var t; return (null == (t = e[0]) ? void 0 : t.control) && e[0].control.checked; }, questionHook: e => { const t = parseWencaiHomework(e.html, removeHtml); return t ? t.labels.some(((n, a) => { const r = n.control; return !r || r.disabled || !e.html.contains(r) || r.value !== t.codes[a] || r.type !== ("1" === t.type ? "checkbox" : "radio"); })) ? null : (e.question = t.question, e.options = t.options, e.type = t.type, e.$options = O(t.labels), e) : null; }, setAnswer: e => { if ("2" === e.type) { if (!function(e, t, n) { var a; const r = parseWencaiHomework(e, n); if (!r || "2" !== r.type || !Array.isArray(t) || r.inputs.length !== t.length || t.some((e => "string" != typeof e || !e.trim()))) return false; const i = e.ownerDocument.defaultView; if (!i) return false; const s = null == (a = Object.getOwnPropertyDescriptor(i.HTMLInputElement.prototype, "value")) ? void 0 : a.set; if (!s || r.inputs.some((e => e.disabled || e.readOnly || !e.isConnected))) return false; for (let o = 0; o < r.inputs.length; o++) s.call(r.inputs[o], t[o]), r.inputs[o].dispatchEvent(new i.Event("input", { bubbles: true })), r.inputs[o].dispatchEvent(new i.Event("change", { bubbles: true })); return true; }(e.html, e.answer, removeHtml)) throw new Error("\u586b\u7a7a\u7b54\u6848\u4e0e\u5f53\u524d\u7a7a\u4f4d\u4e0d\u5339\u914d\uff0c\u5df2\u62d2\u7edd\u56de\u586b"); return false; } return true; } }, { type: "save", name: "\u67e0\u6aac\u6587\u624d\u4f5c\u4e1a\u6536\u5f55", match: () => location.host.includes("wencaischool.net") && location.href.includes("/exam/portal/view_answer.jsp"), question: { html: "tr[id^='trScore_']", question: "table>tbody>tr:eq(0)>td:eq(0)", options: "table>tbody>tr:eq(1)>td:eq(0) table>tbody>tr>td>label", type: ".question-box .tag", workType: "wencai", pageType: "wencai" }, init: async () => {}, answerHook: e => { const t = function(e, t) { const n = parseWencaiHomework(e, t); if (!n) return null; const a = /^\[\u53c2\u8003\u7b54\u6848[\uff1a:]([^\[\]]*)\](?:\s*\u5206\u503c[\uff1a:]\s*\d+(?:\.\d+)?)?$/, r = Array.from(n.table.querySelectorAll("div, font")).filter((e => { var t; return !e.querySelector("div, font") && a.test((null == (t = e.textContent) ? void 0 : t.trim()) ?? ""); })).map((e => e.textContent.trim().match(a)[1].trim())); if ("2" === n.type) { const e = r.map(t); return e.length !== n.inputs.length || e.some((e => !e)) ? null : { ...n, answer: e }; } if (1 !== r.length || !/^[A-Z]+$/.test(r[0])) return null; const i = [ ...r[0] ]; if (new Set(i).size !== i.length || "1" !== n.type && 1 !== i.length) return null; const s = i.map((e => n.codes.indexOf(e))); if (s.some((e => e < 0))) return null; const o = s.map((e => n.optionTexts[e])); return { ...n, answer: "3" === n.type ? judgeAnswer(o[0]) : o }; }(e.html, removeHtml); return t ? { ...e, question: t.question, options: t.options, type: t.type, answer: t.answer } : null; } } ], St = [ { type: "save", name: "yxlearning\u6536\u5f55", match: () => location.host.includes("yxlearning.com") && location.href.includes("exam/start?myExamRecordId"), question: { html: ".subject>.mb20.sub", question: ".ls1.lh30.text-f666", options: "ul.options>li.cursor-p", type: ".question-box .tag", workType: "yxlearning", pageType: "yxlearning" }, init: async () => { if (await waitUntil((function() { return isExist(".mb20.sub"); })), !ie.yxques) return false; }, answerHook: (e, t) => { const n = []; ie.yxques.questionStemRPS.forEach(((e, t) => { e.listPaperQuestionRP.forEach(((e, t) => { n.push(e); })); })); const a = n[t]; e.question = titleClean(removeHtml(a.questionName)); const r = a.type, i = []; switch (e.options = removeStartChar(a.paperOptionRPS.map((e => removeHtml(e.context)))), a.paperOptionRPS.forEach(((t, n) => { 1 == t.standardAnswer && i.push(e.options[n]); })), e.answer = i, r) { case 1: e.type = "3", e.options = [], e.answer = judgeAnswer(e.answer[0]); break; case 2: e.type = "0"; break; case 3: e.type = "1"; } return e; } }, { type: "ask", name: "\u65e5\u7167\u4e13\u4e1a\u6280\u672f\u4eba\u5458\u7b54\u9898", tips: "", match: () => location.host.includes("yxlearning.com") && location.href.includes("exam/start?myExamRecordId"), types: [ "0", "1", "3" ], question: { html: ".mb20.sub", question: ".ls1.lh30.text-f666", options: ".cursor-p", type: ".question-box .tag", workType: "yxlearning", pageType: "yxlearning" }, init: async () => { await waitUntil((function() { return isExist(".mb20.sub"); })); }, ischecked: e => e.hasClass("active"), questionHook: e => { if (e.options = removeStartChar(O(e.html).find("ul>li").map(((e, t) => removeHtml(O(t).html()))).get()), e.$options = O(e.html).find("ul>li"), e.type = typeConvert(O(e.html).parent().prevAll(".title").first().find("[du-html='questionStemName']").text().trim()), "3" === e.type) e.options = [], e.$options = O(e.html).find("ul>li"); return e; } } ], It = [ { type: "ask", name: "\u9ea6\u80fd\u7f51\u7b54\u9898", tips: "", match: () => location.href.includes("lms/web/onlineexam/exambegin"), types: [ "0", "1", "3" ], question: { html: "#exam_form>.sdiv", question: ".eptimu_name", options: ".ansdiv > .optiondiv", type: ".eptimu_title", workType: "cjnep", pageType: "cjnep" }, init: async () => { await waitUntil((function() { return isExist(".sdiv"); })); }, toquestion: e => { O(`.controldiv > a:eq(${e})`), O(`.epcl_circle:eq(${e})`)[0].click(); }, ischecked: isParentChecked, questionHook: e => { if (e.question = e.question.replace(/^[0-9]+\u3001/, "").trim(), e.question = titleClean(e.question), e.options = removeStartChar(e.options), e.type = typeMatch(O(e.html).find(".eptimu_title").text().trim()), e.$options = O(e.html).find(".ansdiv input"), "3" === e.type) e.options = []; return e; }, setAnswer: e => { switch (e.type) { case "3": let t = e.answer; return O(e.html).find(".ansdiv input").each(((e, n) => { isTrue(t) && "1" == O(n).val() && O(n).click(), isFalse(t) && "0" == O(n).val() && O(n).click(); })), false; case "2": case "4": case "5": case "6": const n = O(e.html).find(".ansdiv textarea"), a = e.answer.join(";"); n.val(a), n.trigger("input"), n.trigger("keydown"), n.trigger("change"), n.trigger("blur"), n.trigger("focus"); const r = n[0]; if (r) { [ "input", "change", "blur", "focus" ].forEach((e => { const t = new Event(e, { bubbles: true }); r.dispatchEvent(t); })); } return false; } return true; } }, { type: "save", name: "\u9ea6\u80fd\u7f51\u7b54\u9898\u6536\u5f55", match: () => location.href.includes("lms/web/exam/examshow"), question: { html: "#exam_form>.sdiv", question: ".eptimu_name", options: ".ansdiv > .optiondiv", type: ".eptimu_title", workType: "cjnep", pageType: "cjnep" }, init: async () => { await waitUntil((function() { return isExist(".sdiv"); })); }, answerHook: e => { switch (e.type = typeMatch(O(e.html).find(".eptimu_title").text().trim()), e.question = e.question.replace(/^[0-9]+\u3001/, "").trim(), e.question = titleClean(e.question), e.options = removeStartChar(e.$options.map(((e, t) => { let n = O(t).clone(); return O(n).find("img").remove(), removeHtml(O(n).html()).trim(); })).get()), e.type) { case "0": case "1": e.answer = e.$options.map(((t, n) => { var a; return (null == (a = O(n).find("img").attr("src")) ? void 0 : a.includes("exam-yes")) && e.options[t]; })).get().filter((e => void 0 !== e)); break; case "3": e.answer = e.$options.map(((t, n) => { var a; return (null == (a = O(n).find("img").attr("src")) ? void 0 : a.includes("exam-yes")) && e.options[t]; })).get().filter((e => void 0 !== e)), e.answer = judgeAnswer(e.answer), e.options = []; break; case "4": e.options = []; let t = removeHtml(O(e.html).find(".eptimu_answer.ansdiv").html()).trim(); t.includes("\u6b63\u786e\u7b54\u6848\uff1a") ? e.answer = t.split("\u6b63\u786e\u7b54\u6848\uff1a")[1].trim() : e.answer = []; } return e; } } ], Et = [ { type: "ask", name: "\u9ea6\u80fd\u7f51\u7b54\u9898", tips: "", match: () => location.host.includes("mynep.com") && location.href.includes("my-exam/exambegin"), types: [ "0", "1" ], question: { html: ".et_test", question: ".et_title", options: "ul>.et_answer>label", type: ".question-box .tag", workType: "mynep", pageType: "mynep" }, init: async () => {}, toquestion: e => { ie.select_num(e + 1); }, ischecked: e => e.parent().find("input").prop("checked"), questionHook: e => { e.question = e.question.replace(/\u7b2c\d+\u9898\uff1a/, ""), e.options = removeStartChar(e.options); const t = O(e.html).find('input[id^="question-num-isdone"]').attr("question_num_type_id"); switch (t) { case "1": e.type = "0"; break; case "2": e.type = "1"; } return e; } }, { type: "save", name: "\u9ea6\u80fd\u7f51\u6536\u5f55", match: () => location.host.includes("mynep.com") && location.href.includes("web/my-exam/examshow"), question: { html: ".et_test", question: ".et_title", options: "ul>.et_answer>label", type: ".question-box .tag", workType: "mynep", pageType: "mynep" }, init: async () => {}, answerHook: e => { const t = O(e.html).find(".et_title").clone(); t.find(".exam-btn").remove(), t.find("div").remove(), e.question = removeHtml(t.html()).replace(/\u7b2c\d+\u9898\uff1a/, "").trim(), e.options = []; const n = []; O(e.html).find(".et_answer>.et_answer>.et_answer>label").map(((t, a) => { e.options.push(removeHtml(O(a).html()).trim()), O(a).parent().find("input").prop("checked") && n.push(t); })).get(), e.options = removeStartChar(e.options), e.answer = n.map((t => e.options[t])); const a = O(e.html).find('input[id^="question-num-isdone"]').attr("question_num_type_id"); switch (a) { case "1": e.type = "0"; break; case "2": e.type = "1"; break; default: return false; } return e; } } ], Ut = [ { type: "hook", name: "hook", match: location.host.includes("91huayi.com"), main: e => { observeVuePageChange(O(".box")[0], (() => O(".dd_01").attr("questionid")), { beforeChange: async e => { "homework-detail-container" === e && await waitUntil((function() { return 0 === O(".el-loading-mask").length; })); } }); } }, { type: "ask", name: "\u534e\u533b\u7f51\u7b54\u9898", tips: "", match: () => location.host.includes("91huayi.com") && location.href.includes("/ExamInterface/ComputerExamIndex"), types: [ "0", "1" ], question: { html: "#exampage", question: ".dd_01", options: ".dd_02", type: ".big_type", workType: "huayi", pageType: "huayi" }, init: async () => {}, next: () => { var e; null == (e = O("#btnNext")) || e.click(); }, ischecked: e => e.prop("checked"), questionHook: e => { const t = O(e.html).find(".dd_01").clone(); return t.find(".dd_01_red").remove(), e.question = removeHtml(t.html()), e.options = removeStartChar(e.options), e.type = typeMatch(O(e.html).find(".big_type").text()), e.$options = O(e.html).find("dd.q-content input"), e; }, setAnswer: e => { switch (console.log(e), e.type) { case "0": case "1": return e.ques.$options.each(((t, n) => { if (e.answer.includes(t)) { if (e.rule.ischecked && e.rule.ischecked(O(n))) return; n.click(); } else e.rule.ischecked && e.rule.ischecked(O(n)) && n.click(); })), false; } return true; } }, { type: "ask", name: "\u534e\u533b\u7f51\u8003\u8bd5", tips: "", match: () => location.host.includes("91huayi.com") && location.href.includes("/pages/exam.aspx?cwid="), types: [ "0" ], question: { html: ".test>table", question: "thead", options: "tbody>tr>td>label", type: ".big_type", workType: "huayi", pageType: "huayi" }, init: async () => {}, next: () => { var e; null == (e = O("#btnNext")) || e.click(); }, ischecked: e => e.prop("checked"), questionHook: e => (e.question = titleClean(e.question), e.question = e.question.replace(/^\d+\u3001/, ""), e.options = removeStartChar(e.options), 0 !== e.options.length && (e.type = "0"), e) } ], $t = [ { type: "ask", name: "\u4e91\u5357\u5f00\u653e\u5927\u5b66\u7b54\u9898", tips: "", match: () => location.href.includes("hw/student/studentStartHomework.action") && location.host.includes("teach.ynou.edu.cn"), types: [ "0", "1", "3" ], question: { html: ".e_juan02biaoti", question: ".qcontent > p:first", options: ".signDefault>.label", type: ".question-box .tag", workType: "ynou", pageType: "ynou" }, init: async () => { await waitUntil((function() { return 0 !== O(".e_juan02biaoti").length; })), O("body").css("text-align", "left"); }, ischecked: e => (e.find("input").is(":checked"), e.find("input").is(":checked")), questionHook: e => { e.options = []; const t = O(e.html).find(".e_juan02daan").clone(); t.find(".clear").nextAll().remove(); const n = removeHtml(t.html()), a = n.split(/[A][\u3001\.\uff0e]/)[0].trim(); null !== a && (e.question = a), e.question = a, e.question = a; const r = n.match(/(?:[A-G](?:[\u3001.]|\s)?\s?.*?)(?=\s*[A-G](?:[\u3001.]|\s)?|\s*$)/gs); if (null !== r) { const t = removeOptionsStartChar(r.map((e => e.trim()))); false !== t && (e.options = t); } const i = O(e.html).find(".signDefault").attr("answer_control"); return "radio" === i && e.options.length > 1 && (e.type = "0"), "checkbox" === i && e.options.length > 1 && (e.type = "1"), "radio" === i && 0 === e.options.length && (e.type = "3"), e; }, setAnswer: e => { if (console.log(e), "3" === e.type) { let t = e.answer; return e.ques.$options.each(((e, n) => { isTrue(t) && isTrue(removeHtml(O(n).html())) && O(n).click(), isFalse(t) && isFalse(removeHtml(O(n).html())) && O(n).click(); })), false; } return true; } }, { type: "save", name: "\u6536\u5f55", match: () => location.href.includes("/hw/student/studentViewHomework.action") && location.host.includes("teach.ynou.edu.cn"), question: { html: ".e_juan02biaoti", question: ".qcontent > p:first", options: ".signDefault>.label", type: ".question-box .tag", workType: "ynou", pageType: "ynou" }, init: async () => { await waitUntil((function() { return 0 !== O(".e_juan02biaoti").length; })), O("body").css("text-align", "left"); }, answerHook: e => { e.options = []; const t = O(e.html).find(".e_juan02daan").clone(); t.find(".clear").nextAll().remove(); const n = removeHtml(t.html()), a = n.split(/[A][\u3001\.\uff0e]/)[0].trim(); if (null === a) return null; e.question = a; const r = n.match(/(?:[A-G](?:[\u3001.]|\s)?\s?.*?)(?=\s*[A-G](?:[\u3001.]|\s)?|\s*$)/gs); if (null !== r) { const t = removeOptionsStartChar(r.map((e => e.trim()))); if (0 == t) return null; e.options = t; } const i = O(e.html).find(".signDefault").attr("answer_control"); "radio" === i && e.options.length > 1 && (e.type = "0"), "checkbox" === i && e.options.length > 1 && (e.type = "1"), "radio" === i && 0 === e.options.length && (e.type = "3"); const s = O(e.html).find(".right_answer>font").text(); switch (e.type) { case "0": case "1": e.answer = s.split("").map((t => e.options[t.charCodeAt(0) - 65])); break; case "3": e.answer = isTrue(s) ? "\u6b63\u786e" : isFalse(s) ? "\u9519\u8bef" : ""; } return e; } } ], Ht = [ { type: "hook", name: "hook", match: location.host.includes("21tb.com"), main: e => { observeVuePageChange(O("#examIngEmsRightPanel")[0], (() => O("#examIngEmsRightPanel").attr("class"))); } }, { type: "ask", name: "21tb\u7b54\u9898", tips: "", match: () => location.host.includes("21tb.com") && location.href.includes("exercise/newExercise.fullExerciseTemp.do"), types: [ "0", "1", "3" ], question: { html: ".paper-content > .question-panel-middle", question: ".question-stem>.name", options: "ul.question-options>li>label", type: ".question-box .tag", workType: "21tb", pageType: "21tb" }, init: async () => { if (O(".view-paper-content").length > 0) return false; }, ischecked: e => e.parent().find("input").prop("checked"), questionHook: e => { e.question = titleClean(e.question), e.question = e.question.replace(/\uff08\d+\u5206\uff09$/, "").trim(), e.options = e.options.map((e => e.replace(/^[A-Z]\s*\.\s*/, ""))), e.options = removeStartChar(e.options); const t = O(e.html).attr("class") || ""; switch (console.log(t), true) { case t.includes("SINGLE"): e.type = "0"; break; case t.includes("MULTIPLE"): e.type = "1"; break; case t.includes("JUDGMENT"): e.type = "3", e.options = []; } return e; } }, { type: "save", name: "21tb\u6536\u5f55", match: () => location.host.includes("21tb.com") && location.href.includes("exercise/newExercise.fullExerciseTemp.do"), question: { html: "form > .question-panel-middle", question: ".question-stem>.name", options: "ul.question-options>li>label", type: ".question-box .tag", workType: "21tb", pageType: "21tb" }, init: async () => { if (console.log(O(".view-paper-content").length), 0 == O(".view-paper-content").length) return false; }, answerHook: e => { e.question = titleClean(e.question), e.question = e.question.replace(/\uff08\d+\u5206\uff09$/, "").trim(), e.options = e.options.map((e => e.replace(/^[A-Z]\s*\.\s*/, ""))), e.options = removeStartChar(e.options); const t = O(e.html).attr("questtype") || "", n = O(e.html).find(".true-answer").text().split("\uff1a")[1].trim(); switch (true) { case t.includes("SINGLE"): e.type = "0", e.answer = n.split(", ").map((t => e.options[t.charCodeAt(0) - 65])); break; case t.includes("MULTIPLE"): e.type = "1", e.answer = n.split(", ").map((t => e.options[t.charCodeAt(0) - 65])); break; case t.includes("JUDGMENT"): e.type = "3", e.options = [], e.answer = judgeAnswer(n); } return console.log(e), e; } }, { type: "ask", name: "21tb\u8003\u8bd5\u7b54\u9898", tips: "", match: () => location.host.includes("21tb.com") && location.href.includes("ems/html/examCenter/fullExamTemp.do"), types: [ "0", "1", "3" ], question: { html: ".paper-content > .question-panel-middle", question: ".question-stem", options: "ul.question-options>li>label", type: ".question-box .tag", workType: "21tb", pageType: "21tb" }, init: async () => { if (O(".view-paper-content").length > 0) return false; }, ischecked: e => e.parent().find("input").prop("checked"), questionHook: e => { const t = O(e.html).find(".question-stem").clone(); t.find(".num").remove(), e.question = titleClean(removeHtml(t.html())).replace(/^\./, ""), e.question = e.question.replace(/\uff08\d+\u5206\uff09$/, "").trim(), e.options = e.options.map((e => e.replace(/^[A-Z]\s*\.\s*/, ""))), e.options = removeStartChar(e.options); const n = O(e.html).attr("class") || ""; switch (console.log(n), true) { case n.includes("SINGLE"): e.type = "0"; break; case n.includes("MULTIPLE"): e.type = "1"; break; case n.includes("JUDGMENT"): e.type = "3", e.options = []; } return e; } } ], setEditorText = (e, t) => { var n, a; const r = null == e ? void 0 : e.ownerDocument; if (null == r ? void 0 : r.createElement) { const n = r.createElement("p"); n.textContent = t, e.innerHTML = "", e.appendChild(n); } else e.textContent = t; null == (a = null == (n = null == e ? void 0 : e.classList) ? void 0 : n.remove) || a.call(n, "ql-blank"), ((e, t) => { var n, a, r, i; const s = null == (a = null == (n = null == e ? void 0 : e.ownerDocument) ? void 0 : n.defaultView) ? void 0 : a.InputEvent, o = s ? new s("input", { bubbles: true, inputType: "insertText", data: t }) : new Event("input", { bubbles: true }); null == (r = null == e ? void 0 : e.dispatchEvent) || r.call(e, o), null == (i = null == e ? void 0 : e.dispatchEvent) || i.call(e, new Event("change", { bubbles: true })); })(e, t); }, fill168WxRichTextAnswer = (e, t) => { var n; const a = (e => Array.isArray(e) ? String(e[0] ?? "") : String(e ?? ""))(t).trim(); if (!a) return false; const r = Array.from((null == (n = null == e ? void 0 : e.querySelectorAll) ? void 0 : n.call(e, ".quill-editor")) || []); return !r.length || (r.forEach(((e, n) => { var r, i; const s = String((null == t ? void 0 : t[n]) ?? a), o = null == (r = null == e ? void 0 : e.__vue__) ? void 0 : r.quill; if (null == o ? void 0 : o.setText) return void o.setText(s, "user"); const l = null == (i = null == e ? void 0 : e.querySelector) ? void 0 : i.call(e, ".ql-editor"); l && setEditorText(l, s); })), false); }, Pt = [ { type: "hook", name: "hook", match: location.host.includes("168wangxiao.com"), main: e => { observeVuePageChange(O("#app")[0], (() => (O(".question-submit-btn").text(), O(".question-submit-btn").text() || O(".listTit>span").text())), { beforeChange: async e => { "homework-detail-container" === e && await waitUntil((function() { return 0 === O(".el-loading-mask").length; })); } }), O("#app").length >= 1 && O("#app")[0]; } }, { type: "ask", name: "168\u7f51\u6821\u7b54\u9898", tips: "168\u7f51\u6821\u76ee\u524d\u652f\u6301\u9009\u62e9\u3001\u5224\u65ad\u3001\u586b\u7a7a\u3001\u7b80\u7b54\uff0c\u5176\u4ed6\u9898\u578b\u8bf7\u53cd\u9988\u7ed9\u4f5c\u8005", match: () => location.host.includes("168wangxiao.com") && location.href.includes("/web/learningCenter/details/"), types: [ "0", "1", "2", "3", "4" ], question: { html: ".question-item-container", question: ".title-content", options: ".options .opt-content", type: ".type", workType: "168wx", pageType: "168wx" }, init: async () => (await waitUntil((function() { return 0 !== O(".question-item-container").length; })), !O(".question-submit-btn").text().includes("\u91cd\u65b0\u7b54\u9898")), ischecked: isParentChecked, questionHook: e => { const t = O(e.html).find(".type").text(); return e.type = typeMatch(t), e; }, setAnswer: e => { switch (e.type) { case "2": return fill168WxRichTextAnswer(e.html, e.answer); case "4": return O(e.html).find(".ql-editor"), O(e.html).find(".ql-editor")[0].innerHTML = e.answer[0], false; } return true; } }, { type: "save", name: "168\u7f51\u6821\u7b54\u9898", match: () => location.host.includes("168wangxiao.com") && location.href.includes("/web/learningCenter/details/"), question: { html: ".question-item-container", question: ".title-content", options: ".options .opt-content", type: ".type", workType: "168wx", pageType: "168wx" }, init: async () => (await waitUntil((function() { return 0 !== O(".question-item-container").length; })), O(".question-submit-btn").text().includes("\u91cd\u65b0\u7b54\u9898")), answerHook: e => { const t = O(e.html).find(".type").text(); switch (e.type = typeMatch(t), e.answer = O(e.html).find(".options .opt-content.is-correct-answer").map(((e, t) => removeHtml(O(t).html()))).get(), e.type) { case "2": e.options = [], e.answer = O(e.html).find(".analyze-container>.answer>.text-container>p").map(((e, t) => removeHtml(O(t).html()))).get(); break; case "3": e.options = [], e.answer = [ judgeAnswer(e.answer[0]) ]; break; case "4": e.options = [], e.answer = O(e.html).find(".analyze-container>.answer>.text-container").map(((e, t) => removeHtml(O(t).html()))).get(); } return e; } }, { type: "ask", name: "168\u7f51\u6821\u8003\u8bd5", tips: "", match: () => location.host.includes("168wangxiao.com") && location.href.includes("/web/examination/answer"), types: [ "0", "1", "2", "3", "4" ], question: { html: ".Answer-area", question: ".listTit>span", options: ".el-checkbox-group>label", type: ".type", workType: "168wx", pageType: "168wx" }, init: async () => { await waitUntil((function() { return 0 !== O(".Answer-area").length; })); }, next: () => { O('button:contains("\u4e0b\u4e00\u9898")').click(); }, ischecked: isParentChecked, questionHook: e => (e.options = removeOptionsStartChar(e.options), e.type = typeMatch(O(".tit-type").text()), e), setAnswer: e => { switch (e.type) { case "2": return fill168WxRichTextAnswer(e.html, e.answer); case "4": return O(e.html).find(".ql-editor"), O(e.html).find(".ql-editor")[0].innerHTML = e.answer[0], false; } return true; } } ], Lt = /^\/web\/cc-detail\/([^/]+)\/act\/quiz-answer\/([^/?#]+)/, Mt = /^\/web(?:-old)?\/index\.php$/, jt = { SINGLE: "0", MULTI: "1", TF: "3" }, getMosoteachQuizIds = (e = location.href) => { try { const t = new URL(e); if ("www.mosoteach.cn" !== t.hostname) return null; const n = t.pathname.match(Lt); return n ? { ccId: n[1], quizId: n[2] } : null; } catch { return null; } }, isMosoteachQuizAnswerUrl = (e = location.href) => null !== getMosoteachQuizIds(e), isMosoteachLegacyQuizReplyUrl = (e = location.href) => { try { const t = new URL(e); return "www.mosoteach.cn" === t.hostname && (!!Mt.test(t.pathname) && ("interaction_quiz" === t.searchParams.get("c") && "reply" === t.searchParams.get("m"))); } catch { return false; } }, isMosoteachAskUrl = (e = location.href) => isMosoteachQuizAnswerUrl(e) || isMosoteachLegacyQuizReplyUrl(e), isMosoteachReviewUrl = (e = location.href) => { try { const t = new URL(e); return "https:" === t.protocol && "www.mosoteach.cn" === t.hostname && (/^\/web\/cc-detail\/[^/]+\/act\/quiz-single-result\/[^/]+\/?$/.test(t.pathname) || Mt.test(t.pathname) && "interaction_quiz" === t.searchParams.get("c") && "person_quiz_result" === t.searchParams.get("m")); } catch { return false; } }, getOptionNo = e => e.itemNo ?? e.item_no ?? 0, getSortedOptions = e => [ ...e.options || [] ].sort(((e, t) => getOptionNo(e) - getOptionNo(t))), getMosoteachTopicOptions = (e, t) => { var n; return "TF" !== e.type || (null == (n = e.options) ? void 0 : n.length) ? t(getSortedOptions(e).map((e => e.content || ""))) : [ "\u6b63\u786e", "\u9519\u8bef" ]; }, Ot = ".topic-answer-align,label.d-flex.align-center:has(.v-radio)", zt = `.pt-10.d-flex.list-item:has(.topic-subject):has(${Ot})`, Dt = `${Ot},.t-option.t-item label,.t-judge.t-item label`, Ft = ".v-chip__content,.t-type", Nt = "__aiAskMosoteachRouteHook", Rt = "__aiAskMosoteachHref", Bt = "__aiAskMosoteachRouteTimer"; let Gt = []; const Kt = { cleanText: (e = "") => titleClean(removeHtml(e)), cleanOptions: e => removeStartChar(e.map((e => removeHtml(e)))), judgeAnswer: judgeAnswer }, getMosoteachQuestionType = (e = "", t = []) => ((e = "", t = []) => { const n = jt[e.trim()]; return "0" === n && (e => 2 === e.length && e.every((e => /^(\u6b63\u786e|\u9519\u8bef|\u5bf9|\u9519|\u662f|\u5426|T|F|true|false)$/i.test(e.trim()))))(t) ? "3" : n || ""; })(e, t) || typeMatch(e), getMosoteachQuestionElements = () => isMosoteachReviewUrl() ? O(location.pathname.endsWith("/index.php") ? ".topic-item" : ".quiz-topic-content") : isMosoteachLegacyQuizReplyUrl() ? O(".topic-item") : O(zt), getMosoteachLegacyTopics = () => { var e, t; const n = O("#app")[0], a = null == (t = null == (e = null == n ? void 0 : n.__vue__) ? void 0 : e.$data) ? void 0 : t.topics; return Array.isArray(a) ? a : []; }, waitForMosoteachQuestionElements = async () => { for (let e = 0; e < 30; e++) { if (getMosoteachQuestionElements().length > 0) return true; await sleep(200); } return false; }, cacheMosoteachAnswer = e => { const t = ((e, t, n, a) => { const r = a.cleanText(e), i = ((e, t) => t(e).sort().join("\n"))(t, a.cleanOptions); return n.find((e => { const t = getMosoteachTopicOptions(e, a.cleanOptions).sort().join("\n"); return a.cleanText(e.subject || "") === r && t === i; })); })(e.question, e.options, Gt, Kt); if (!t) return; const n = ((e, t) => { const n = t.cleanOptions(getSortedOptions(e).map((e => e.content || ""))); return Array.isArray(e.answers) && e.answers.length > 0 ? e.answers.map((e => n[e] || "")).filter(Boolean) : "TF" === e.type ? t.judgeAnswer(e.tfAnswer || "") : []; })(t, Kt); if (!n.length) return; const a = { type: e.type, question: e.question, options: "3" === e.type ? [] : e.options, answer: n }; Answer.cacheAnswer(a); }, parseMosoteachDomQuestion = e => { const t = O(e.html), n = t.find(".topic-subject").first().html(), a = t.find(Ot); if (!n || !a.length) return e; e.question = Kt.cleanText(n); const r = a.map(((e, t) => O(t).find(".topic-answer").first().html() || O(t).html())).get(); return e.options = Kt.cleanOptions(r), e.$options = (e => O(e.map(((e, t) => O(t).closest("label,.d-flex.align-start")[0] || t)).get()))(a), e.type = getMosoteachQuestionType(t.find(".v-chip__content").first().text(), e.options), cacheMosoteachAnswer(e), e; }, parseMosoteachLegacyQuestion = (e, t) => { const n = O(e.html), a = getMosoteachLegacyTopics()[t], r = n.find(Dt), i = r.map(((e, t) => O(t).html())).get(); if (a) e.question = Kt.cleanText(a.subject || ""), e.options = ((e, t, n) => { const a = n(t); return a.length ? a : getMosoteachTopicOptions(e || {}, n); })(a, i, Kt.cleanOptions), e.type = getMosoteachQuestionType(a.type, e.options); else { const t = n.find(".t-subject").first().html(); e.question = Kt.cleanText(t || e.question), e.options = Kt.cleanOptions(i.length ? i : e.options), e.type = getMosoteachQuestionType(n.find(Ft).first().text() || e.type, e.options); } return r.length && (e.$options = r), cacheMosoteachAnswer(e), e; }, watchMosoteachRouteChange = () => { const e = ie; if (e[Nt]) return; e[Nt] = true, e[Rt] = location.href; const checkRouteChange = () => { e[Rt] !== location.href && (e[Rt] = location.href, clearTimeout(e[Bt]), e[Bt] = setTimeout((() => vuePageChange()), 100)); }, bindHistoryChange = e => { const t = history[e]; history[e] = function(...e) { const n = t.apply(this, e); return setTimeout(checkRouteChange, 0), n; }; }; bindHistoryChange("pushState"), bindHistoryChange("replaceState"), window.addEventListener("popstate", (() => setTimeout(checkRouteChange, 0))); }, Vt = [ { type: "hook", name: "\u4e91\u73ed\u8bfe\u8def\u7531\u76d1\u542c", match: () => "www.mosoteach.cn" === location.host, main: () => { watchMosoteachRouteChange(); } }, { type: "ask", name: "\u4e91\u73ed\u8bfe\u7b54\u9898", tips: "", match: () => "www.mosoteach.cn" === location.host && isMosoteachAskUrl(), types: [ "0", "1", "3" ], question: { html: getMosoteachQuestionElements, question: ".topic-subject,.t-subject", options: Dt, type: Ft, workType: "mosoteach", pageType: "mosoteach" }, init: async () => { if (await sleep(500), !isMosoteachAskUrl()) return Gt = [], false; return !!(await waitForMosoteachQuestionElements()) && (Gt = isMosoteachQuizAnswerUrl() ? await (async () => { const e = getMosoteachQuizIds(), t = localStorage.getItem("teach_token") || ""; if (!e || !t) return []; try { const n = await fetch(`https://coreapi.mosoteach.cn/ccs/${e.ccId}/quizzes/${e.quizId}/topics?_ts=${Date.now()}`, { headers: { accept: "application/json, text/plain, */*", "x-client-app-id": "MTWEB", "x-client-version": "6.0.0", "x-security-type": "SECURITY_TYPE_TOKEN", "x-token": t }, credentials: "omit" }); if (!n.ok) return []; const a = await n.json(); return Array.isArray(null == a ? void 0 : a.topics) ? a.topics : []; } catch (n) { return []; } })() : getMosoteachLegacyTopics(), true); }, ischecked: e => { const t = e.find("input").add(e.closest("label,.d-flex.align-start").find("input")).first(); return e.hasClass("is-checked") || e.hasClass("v-item--active") || t.prop("checked") || "true" === t.attr("aria-checked"); }, questionHook: (e, t) => isMosoteachLegacyQuizReplyUrl() ? parseMosoteachLegacyQuestion(e, t) : parseMosoteachDomQuestion(e) }, { type: "save", name: "\u4e91\u73ed\u8bfe\u5c0f\u6d4b\u6b63\u786e\u7b54\u6848\u6536\u5f55", tips: "\u6536\u5f55\u65b0\u65e7\u7248\u4e2a\u4eba\u7ed3\u679c\u9875\u5df2\u516c\u5e03\u7684\u6b63\u786e\u7b54\u6848\uff0c\u4fdd\u7559\u9898\u5e72\u548c\u9009\u9879\u56fe\u7247\u3002", match: () => isMosoteachReviewUrl(), question: { html: getMosoteachQuestionElements, question: ".topic-subject,.t-subject", options: ".topic-answer,.opt-content", type: Ft, workType: "mosoteach", pageType: "mosoteach" }, init: waitForMosoteachQuestionElements, answerHook: e => { var t, n; const a = e.html, r = a.matches(".topic-item"), i = a.querySelector(r ? ".t-subject" : ".topic-subject"), s = Kt.cleanText((null == i ? void 0 : i.innerHTML) || ""), o = getMosoteachQuestionType((null == (t = a.querySelector(r ? ".t-type" : ".v-chip__content")) ? void 0 : t.textContent) || ""); if (!s || ![ "0", "1", "3" ].includes(o)) return null; const l = Array.from(a.querySelectorAll(r ? ".answer-l" : ".label")).filter((e => { var t; return /^\u6b63\u786e\u7b54\u6848[\uff1a:]/.test((null == (t = e.textContent) ? void 0 : t.replace(/\s/g, "")) || ""); })); if (1 !== l.length) return null; const c = r ? l[0] : l[0].nextElementSibling; if (!c || !r && !c.classList.contains("flex-grow-1")) return null; let u = c; for (let v = 0; u && v < 64; v++, u = u.parentElement) { const e = null == (n = u.ownerDocument.defaultView) ? void 0 : n.getComputedStyle(u); if (u.hasAttribute("hidden") || "true" === u.getAttribute("aria-hidden") || "none" === (null == e ? void 0 : e.display) || "hidden" === (null == e ? void 0 : e.visibility)) return null; } if (u) return null; const p = (c.textContent || "").replace(/^\s*\u6b63\u786e\u7b54\u6848\s*[\uff1a:]/, "").trim(); if ("3" === o) { const t = normalizeJudgeAnswer(p); return t ? { ...e, question: s, type: o, options: [], answer: [ t ] } : null; } const d = Array.from(a.querySelectorAll(r ? ".opt-content" : ".topic-answer")); if (d.length < 2 || d.length > 26) return null; const m = d.map((e => { var t, n; const a = e.previousElementSibling; return (null == a ? void 0 : a.matches(r ? ".opt-index" : ".vote-option-index")) ? null == (n = null == (t = a.textContent) ? void 0 : t.trim().match(/^([A-Z])[.\u3001\uff0e]$/)) ? void 0 : n[1] : void 0; })), h = d.map((e => removeHtml(e.innerHTML))); if (m.some((e => !e)) || new Set(m).size !== d.length || h.some((e => !e)) || new Set(h).size !== h.length) return null; if (!/^[A-Z]+(?:[\s,\uff0c\u3001]+[A-Z]+)*$/.test(p)) return null; const f = p.replace(/[\s,\uff0c\u3001]/g, "").split(""); if (new Set(f).size !== f.length || "0" === o && 1 !== f.length) return null; const g = f.map((e => h[m.indexOf(e)])); return g.every(Boolean) ? { ...e, question: s, type: o, options: h, answer: g } : null; } } ], Wt = ".store-question-item-container", buttonCount = e => O("button").filter(((t, n) => { var a; return (null == (a = n.textContent) ? void 0 : a.trim()) === e; })).length, paperState = e => "https://www.learnin.com.cn" === location.origin && "/user/" === location.pathname && /^#\/user\/student\/course\/[a-f0-9]{32}\/topic\/[a-f0-9]{32}\/do$/.test(location.hash) && (e ? 0 === buttonCount("\u63d0\u4ea4\u4f5c\u4e1a") && 0 === buttonCount("\u4fdd\u5b58\u5e76\u79bb\u5f00") && 1 === buttonCount("\u5173\u95ed") && isExist(".question-answer-exhibition") : 1 === buttonCount("\u63d0\u4ea4\u4f5c\u4e1a") && 1 === buttonCount("\u4fdd\u5b58\u5e76\u79bb\u5f00") && !isExist(".question-answer-exhibition")), waitPaper = async () => { try { return await waitUntil((() => isExist(Wt)), { timeout: 1e4 }), !0; } catch { return false; } }; function parseItem(e, t) { var n; if (!paperState(t)) return null; const a = O(e.html), r = a.find(">.item-question-header>.header-left"), i = null == (n = r.text().match(/\u3010(.+)\u3011/)) ? void 0 : n[1], s = "\u5355\u9009\u9898" === i ? "0" : "\u591a\u9009\u9898" === i ? "1" : "\u5224\u65ad\u9898" === i ? "3" : null, o = a.find(">.item-question-body>.question-title>div:first-child"), l = a.find(".question-info>.question-option-list>.option-item"); if (!s || 1 !== r.length || 1 !== o.length || l.length < 2 || l.length > 26 || "3" === s && 2 !== l.length) return null; const c = [], u = [], p = []; for (const m of l.toArray()) { const e = O(m), n = e.find(">.option-index"), a = e.find(">.option-content>div:first-child"), r = n.text().trim(); if (1 !== n.length || 1 !== a.length || !t && !n.hasClass("can-do") || !("3" === s ? /^[TF]$/ : /^[A-Z]$/).test(r)) return null; c.push(n[0]), p.push(r), u.push(removeHtml(a.html()) ?? ""); } const d = titleClean(removeHtml(o.html()) ?? ""); return !d || u.some((e => !e)) || new Set(u).size !== u.length || new Set(p).size !== p.length ? null : (e.question = d, e.type = s, e.options = "3" === s ? [] : u, e.$options = O(c), { item: e, codes: p, options: u }); } const Qt = [ { type: "hook", name: "hook", match: "www.learnin.com.cn" === location.host, main: () => observeVuePageChange(O("#app")[0], (() => `${location.href}:${buttonCount("\u63d0\u4ea4\u4f5c\u4e1a")}:${O(Wt).length}`)) }, { type: "ask", name: "learnin\u7b54\u9898", tips: "", match: () => paperState(false), types: [ "0", "1", "3" ], question: { html: Wt, question: ".question-title>div:first-child", options: ".question-info>.question-option-list>.option-item>.option-content>div:first-child", type: ".item-question-header>.header-left", workType: "learnin", pageType: "learnin" }, init: waitPaper, ischecked: e => e.hasClass("active"), questionHook: e => { var t; return (null == (t = parseItem(e, false)) ? void 0 : t.item) ?? null; } }, { type: "save", name: "learnin\u6536\u5f55", match: () => paperState(true), question: { html: Wt, question: ".question-title>div:first-child", options: ".question-info>.question-option-list>.option-item>.option-content>div:first-child", type: ".item-question-header>.header-left", workType: "learnin", pageType: "learnin" }, init: waitPaper, answerHook: e => { const t = parseItem(e, true); if (!t || "3" === e.type) return null; const n = O(e.html).find(".question-answer-exhibition>.topic-teacher-check-content").filter(((e, t) => "\u53c2\u8003\u7b54\u6848" === O(t).find(".content-title>span").first().text().trim())), a = n.find(".check-content>.answer-content"), r = a.text().trim(); if (1 !== n.length || 1 !== a.length || !/^[A-Z](?:\u3001[A-Z])*$/.test(r)) return null; const i = r.split("\u3001"); if (new Set(i).size !== i.length || "1" !== e.type && 1 !== i.length) return null; const s = i.map((e => t.options[t.codes.indexOf(e)])); return s.some((e => void 0 === e)) ? null : (e.answer = s, e); } } ], Jt = [ { type: "hook", name: "hook", match: location.host.includes("ouchn.edu.cn"), main: e => { observeVuePageChange(O("#app")[0], (() => getUrl())); } }, { type: "ask", name: "\u7535\u5927\u7b54\u9898", tips: "", match: () => location.host.includes("ouchn.edu.cn") && location.href.includes("learningPlatform/#/myExamDetails/examQuestion"), types: [ "0" ], question: { html: ".everyQuest", question: ".topicTitle", options: ".optionList .topicTitle", type: ".question-box .tag", workType: "ouchn", pageType: "ouchn" }, init: async () => { await waitUntil((function() { return isExist(".everyQuest"); })); }, ischecked: isParentChecked, questionHook: e => (e.type = "0", e) }, { type: "save", name: "\u7535\u5927\u6536\u5f55", match: () => location.host.includes("ouchn.edu.cn") && location.href.includes("learningPlatform/#/myExamDetails/testPaper"), question: { html: ".everyQuest", question: ".topicTitle", options: ".optionList .topicTitle", type: ".question-box .tag", workType: "ouchn", pageType: "ouchn" }, init: async () => { await waitUntil((function() { return isExist(".everyQuest"); })); }, answerHook: e => { const t = O(e.html).find('.rightAndWrong>span:contains("\u6b63\u786e\u7b54\u6848")').text().replace("\u6b63\u786e\u7b54\u6848\uff1a", "").trim(), n = e.options; let a = []; return t.split("").forEach((e => { a.push(n[e.charCodeAt(0) - 65]); })), 1 == a.length ? e.type = "0" : e.type = "1", e.answer = a, e; } } ], Zt = [ { type: "hook", name: "mooc", match: "www.icourse163.org" === location.host, main: e => { observeVuePageChange(O("#courseLearn-inner-box")[0], (() => O("#courseLearn-inner-box > div:eq(0)").attr("class")), { beforeChange: async e => { "homework-detail-container" === e && await waitUntil((function() { return 0 === O(".el-loading-mask").length; })); } }); } }, { type: "ask", name: "mooc\u7b54\u9898", tips: "\u4e2d\u56fd\u5927\u5b66MOOC\u9650\u5236\u7b54\u9898\u901f\u5ea6\uff0c\u8bf7\u4e0d\u8981\u8fc7\u5feb", match: () => "www.icourse163.org" === location.host && location.href.includes("#/learn/quiz?id="), types: [ "0", "1", "2", "3" ], question: { html: ".u-questionItem", question: ".f-richEditorText", options: "ul.choices>li>input", type: ".qaCate.j-qacate.f-fl", workType: "mooc", pageType: "mooc" }, init: async () => { await waitUntil((function() { return O(".u-questionItem").length, 0 !== O(".u-questionItem").length; })); }, ischecked: isParentChecked, questionHook: (e, t) => { O(e.html).find(".qaCate.j-qacate.f-fl > span:eq(0)").attr("class"); const n = ie.learnUtilQuestionList[t]; switch (e.question = removeHtml(n.title), e.options = n.options.map((e => removeHtml(e.content))), n.type) { case 1: e.type = "0"; break; case 2: e.type = "1"; break; case 3: e.type = "2"; break; case 4: e.type = "3", e.options = []; break; default: n.type, e.type = "8"; } return e; }, setAnswer: e => { switch (e.type) { case "2": return O(e.html).find(".u-baseinputui>textarea").each(((t, n) => { O(n).val(e.answer[t]), O(n).focus(), O(n).blur(); })), false; case "3": let t = e.answer; O(e.html).find("ul.choices>li").each(((e, n) => { isTrue(t) && O(n).find(".u-icon-correct").length > 0 && O(n).find("input").click(), isFalse(t) && O(n).find(".u-icon-wrong").length > 0 && O(n).find("input").click(); })); } return true; } }, { type: "save", name: "\u4e2d\u56fd\u5927\u5b66mooc\u6536\u5f55", match: () => "www.icourse163.org" === location.host && location.href.includes("#/learn/quizscore?id="), question: { html: ".u-questionItem", question: ".f-richEditorText", options: "ul.choices li>input", type: ".qaCate.j-qacate.f-fl", workType: "mooc", pageType: "mooc" }, init: async () => { await waitUntil((function() { return O(".u-questionItem").length, 0 !== O(".u-questionItem").length; })); }, answerHook: (e, t) => { const n = ie.learnUtilQuestionList[t]; e.question = removeHtml(n.title); let a = [], r = []; switch (n.options.forEach((e => { a.push(removeHtml(e.content)), e.answer && r.push(removeHtml(e.content)); })), e.options = a, e.answer = r, n.type) { case 1: e.type = "0"; break; case 2: e.type = "1"; break; case 3: e.type = "2", e.answer = [ n.stdAnswer ]; break; case 4: e.type = "3", e.options = []; break; default: n.type; } return e; } } ], Yt = [ { host: "swufe-online.com", display: "\u897f\u8d22\u5728\u7ebf", key: "swufe" }, { host: "jsnu.edu.cn", display: "\u6c5f\u82cf\u5e08\u5927", key: "jsnu" } ], matchSite = () => Yt.find((e => location.host.includes(e.host))), siteDisplay = () => { var e; return (null == (e = matchSite()) ? void 0 : e.display) ?? "learnspace"; }, siteKey = () => { var e; return (null == (e = matchSite()) ? void 0 : e.key) ?? "learnspace"; }, Xt = [ "learnspace/course/test/coursewareTest_intoRedoTestPage.action", "learnspace/learn/learn/templateeight/index.action", "learnspace/course/test/coursewareTest_intoTestPage.action" ], en = [ "learnspace/course/test/coursewareTest_intoTestAnswerPage.action", "learnspace/learn/learn/templateeight/index.action" ], pathHit = e => e.some((e => location.href.includes(e))), titleCleanup = e => e.replace(/^[.*?]\s*/, "").replace(/^\u3010.*?\u3011\s*/, "").replace(/\s*\uff08\d+\.\d+\u5206\uff09$/, "").replace(/^\d+\./, "").trim().replace(/^\d+\uff0e/, "").trim().replace(/^\d+ ./, "").trim(), tn = [ { type: "ask", get name() { return `${siteDisplay()}\u7b54\u9898`; }, tips: "", match: () => Boolean(matchSite()) && pathHit(Xt), types: [ "0", "1", "3" ], question: { html: ".bank_test > .test_item", question: ".test_item_tit", options: ".test_item_theme>ul>li>label, .test_item_theme>label", type: ".question-box .tag", get workType() { return siteKey(); }, get pageType() { return siteKey(); } }, init: async () => { await waitUntil((function() { return isExist(".bank_test > .test_item"); })); }, ischecked: isParentChecked, questionHook: e => { const t = O(e.html).find(".test_item_tit").clone(); if (t.find(".tipNodo").remove(), e.question = removeHtml(t.html()), e.question = titleClean(e.question), e.type = typeMatch(O(e.html).prevAll(".test_item_type").first().text()), e.question = titleCleanup(e.question), e.options = removeStartChar(e.options), "3" === e.type) e.options = []; return e; } }, { type: "save", get name() { return `${siteDisplay()}\u9636\u6bb5\u6d4b\u9a8c\u6536\u5f55`; }, match: () => Boolean(matchSite()) && pathHit(en), question: { html: ".bank_test > .test_item", question: ".test_item_tit", options: ".test_item_theme>ul>li>.zdh_op_con", type: ".question-box .tag", get workType() { return siteKey(); }, get pageType() { return siteKey(); } }, init: async () => {}, answerHook: e => { e.type = typeMatch(O(e.html).prevAll(".test_item_type").first().text()), e.question = titleCleanup(e.question), e.options = removeStartChar(e.options); const t = O(e.html).find(".test_item_key_tit").text().replace("\u53c2\u8003\u7b54\u6848\uff1a", "").trim(); switch (e.type) { case "0": case "1": e.answer = t.split("").map((t => { let n = t.charCodeAt() - 65; return e.options[n]; })); break; case "3": e.answer = judgeAnswer(t), e.options = []; } return e; } }, { type: "ask", name: "\u897f\u8d22\u5728\u7ebf\u7efc\u5408\u7ec3\u4e60\u7b54\u9898", tips: "\u897f\u8d22\u5728\u7ebf\u6536\u5f55\u8bf7\u91cd\u65b0\u70b9\u51fb\u9898\u578b\u5207\u6362\u89e6\u53d1", match: () => location.host.includes("swufe-online.com") && location.href.includes("/learnspace/userDefine/t_test.jsp?courseId="), types: [ "0", "1", "3" ], question: { html: ".timu_title", question: ".timu_title", options: ".test_item_theme>ul>li", type: ".question-box .tag", workType: "swufe", pageType: "swufe" }, init: async () => { if (await waitUntil((function() { return isExist(".timu_title"); })), !document.body.innerHTML.includes("\u63d0\u4ea4\u7b54\u9898\u540e\u663e\u793a")) return false; O(".layui-tab-title>li").on("click", (function() { vuePageChange(); })); }, ischecked: isParentChecked, questionHook: (e, t) => { const n = O(e.html).attr("id"); return e.type = typeMatch(O(".layui-this").text()), e.question = removeHtml(O(e.html).html()), e.options = O(`#${n}`).map((function() { let t = [], n = O(this).next(), a = []; for (;n.length && n.hasClass("question-item-opt"); ) a.push(removeHtml(n[0].outerHTML)), t.push(n), n = n.next(); return e.$options = O(t.map((e => e[0]))).find("label"), a; })).get(), e.options = removeStartChar(e.options), e; } }, { type: "save", name: "\u897f\u8d22\u5728\u7ebf\u7efc\u5408\u4f5c\u4e1a\u6536\u5f55", match: () => location.host.includes("swufe-online.com") && location.href.includes("/learnspace/userDefine/t_test.jsp?courseId="), question: { html: ".timu_title", question: ".timu_title", options: ".test_item_theme>ul>li", type: ".question-box .tag", workType: "swufe", pageType: "swufe" }, init: async () => { if (await waitUntil((function() { return isExist(".timu_title"); })), document.body.innerHTML.includes("\u63d0\u4ea4\u7b54\u9898\u540e\u663e\u793a")) return false; O(".layui-tab-title>li").on("click", (function() { vuePageChange(); })); }, answerHook: e => { const t = O(e.html).attr("id"); switch (e.type = typeMatch(O(".layui-this").text()), e.question = removeHtml(O(e.html).html()), e.options = O(`#${t}`).map((function() { let t = [], n = O(this).next(), a = []; for (;n.length && n.hasClass("question-item-opt"); ) a.push(removeHtml(n[0].outerHTML)), t.push(n), n = n.next(); return e.$options = O(t.map((e => e[0]))).find("label"), a; })).get(), e.options = removeStartChar(e.options), e.type) { case "0": case "1": const n = O(`#${t}`).nextAll(".ans").first().find("span:eq(0)").text(); e.answer = n.trim().split("").map((t => { let n = t.charCodeAt() - 65; return e.options[n]; })); break; case "3": e.answer = judgeAnswer(O(`#${t}`).nextAll(".ans").first().find("span:eq(0)").text().trim()), e.options = []; break; case "7": case "4": e.answer = removeHtml(O(`#${t}`).nextAll(".ans").first().html()).replace("\u6b63\u786e\u7b54\u6848\uff1a", "").trim(), e.options = []; break; default: e.type; } return e; } } ], nn = [ { type: "ask", name: "\u91cd\u5e86\u6cd5\u6cbb\u8003\u8bd5\u7b54\u9898", tips: "\u672c\u5e73\u53f0\u65e0\u7b54\u6848\u6536\u5f55\uff0c\u9700\u8981\u81ea\u884c\u8865\u5145\u9898\u5e93\uff0c\u5efa\u8bae\u4f7f\u7528\u9898\u5e93\u5bfc\u5165\u529f\u80fd", match: () => "ks.cqsdx.cn" === location.host && location.pathname.includes("/exam/user/bind"), types: [ "0", "1", "3" ], question: { html: ".qlist", question: "span:eq(1)", options: "label", type: ".badge.badge-danger", workType: "cqsdx", pageType: "cqsdx" }, init: async () => { await waitUntil((function() { return isExist(".qlist"); })); }, toquestion: e => { O(`#question_card button:eq(${e})`).click(); }, ischecked: e => e.find("div").hasClass("checked"), questionHook: e => { const t = O(e.html).find(".badge.badge-danger").text(); if (e.type = typeMatch(t), e.question = e.question.replace(/\u206B/g, "").trim(), e.options = e.options.map((e => e.replace(/\u206B/g, "").trim())), "3" === e.type) e.options = []; return e; } } ], isOlearnHost = () => location.host.includes("telfri-edu.com") || "cjzzxylearning.o-learn.cn" === location.host, isHomeworkRoute = e => "cjzzxylearning.o-learn.cn" === location.host ? "/student/" === location.pathname && new RegExp(`^#/course/[A-Za-z0-9_-]+/learn/(?:outline/)?homework/${e}/[A-Za-z0-9_-]+$`).test(location.hash) : new RegExp(`/learn/(?:outline/)?homework/${e}/`).test(location.href), an = ".topic-group>.topic-container", rn = [ "0", "1", "3" ], topicType = e => typeMatch(O(e).prevAll(".topic-title").first().find(".title-bold").text().trim()), waitTextPaper = async () => (await waitUntil((() => isExist(an) || isExist(".card-all-topic-container"))), !!isExist(an) || (addLog("O-Learn \u6587\u6863\u578b\u4f5c\u4e1a\u9898\u9762\u4e0d\u5728\u9875\u9762\u5185\uff0c\u6682\u4e0d\u652f\u6301\u7b54\u9898\u4e0e\u6536\u5f55", "warning"), false)), sn = [ { type: "hook", name: "hook", match: isOlearnHost(), main: e => { observeVuePageChange(O("#app")[0], (() => getUrl())); } }, { type: "ask", name: "olearn\u7b54\u9898", tips: "", match: () => isOlearnHost() && isHomeworkRoute("do"), types: [ "0", "1", "3" ], question: { html: ".topic-group>.topic-container", question: ".topic-title", options: ".topic-answer .radio-wrap .radio-text", type: ".question-box .tag", workType: "olearn", pageType: "olearn" }, init: waitTextPaper, ischecked: e => e.hasClass("is-active") || e.hasClass("is-checked"), questionHook: e => (e.$options = O(e.html).find(".topic-answer .radio-wrap>label"), e.type = topicType(e.html), rn.includes(e.type) && (e.$options.length < 2 || e.$options.length !== e.options.length || e.$options.toArray().some((t => { const n = t.querySelectorAll("input"); return 1 !== n.length || t.control !== n[0] || n[0].disabled || n[0].type !== ("1" === e.type ? "checkbox" : "radio"); }))) ? null : e) }, { type: "save", name: "olearn\u6536\u5f55", match: () => isOlearnHost() && isHomeworkRoute("show"), question: { html: ".topic-group>.topic-container", question: ".topic-title", options: ".topic-answer .radio-wrap .radio-text", type: ".question-box .tag", workType: "olearn", pageType: "olearn" }, init: waitTextPaper, answerHook: e => { e.type = topicType(e.html); const t = O(e.html).find(".topic-answer .radio-wrap>label input").map(((e, t) => t.value)).get(), n = O(e.html).find(".standard-answer>.analysis-text"), a = (1 === n.length ? n.text().trim() : "").split(""); if (!rn.includes(e.type) || !e.question || t.length < 2 || t.length !== e.options.length || t.some((e => !/^[A-Z]$/.test(e))) || new Set(t).size !== t.length || e.options.some((e => !e)) || new Set(e.options).size !== e.options.length || !a.length || new Set(a).size !== a.length || "1" !== e.type && 1 !== a.length) return null; const r = a.map((n => e.options[t.indexOf(n)])); return r.some((e => void 0 === e)) ? null : "3" === e.type ? (e.options = [], e.answer = judgeAnswer(r[0]), e.answer.length ? e : null) : (e.answer = r, e); } } ], on = [ { type: "hook", name: "hook", match: () => location.host.includes("yxbyun.com") && !location.host.includes("yxb4student"), main: e => { observeVuePageChange(O("#app")[0], (() => O("#app")[0].__vue__.$route.path)); } }, { type: "hook", name: "\u4ebf\u5b66\u5b9d\u65b0\u7248hook", match: () => location.host.includes("yxb4student.yxbyun.com"), main: e => { O("#app")[0] && observeVuePageChange(O("#app")[0], (() => O(".danxuan .tm").map(((e, t) => t.id)).get().join(","))); } }, { type: "save", name: "\u4ebf\u5b66\u5b9d\u6536\u5f55", match: () => location.host.includes("yxbyun.com") && (location.href.includes("yxbstudent/#/testPaper") || location.href.includes("yxbstudent/#/finalExam")), question: { html: ".test_wrap", question: ".content", options: ".el-radio-group input", type: ".question-box .tag", workType: "yxbyun", pageType: "yxbyun" }, init: async () => { await waitUntil((function() { return isExist(".test_wrap"); })); }, answerHook: e => { var t; const n = O(e.html).find("div:eq(0)")[0].__vue__, a = (null == (t = n.pagerData) ? void 0 : t.question) || n.smallPaper.questionTopic; return e.type = typeMatch(n.queTypeName), e.question = titleClean(removeHtml(a.questionTitle)), e.options = (a.optionList || a.questionOptionList).map((e => removeHtml(e.questionContent))), [ "0", "1", "3" ].includes(e.type) && (e.answer = a.questionAnswer.split(",").map((t => e.options[t.charCodeAt(0) - 65]))), "3" === e.type && (e.options = [], e.answer = judgeAnswer(e.answer)), e; } }, { type: "save", name: "\u4ebf\u5b66\u5b9d\u8003\u8bd5\u6536\u5f55", match: () => location.host.includes("yxb4student.yxbyun.com") && location.pathname.includes("/kaoshicenter"), question: { html: ".danxuan", question: ".tm", options: ".xxbh", type: ".tx", workType: "yxbyun", pageType: "yxbyun" }, init: async () => { if (!isExist(".danxuan")) return false; try { return await waitUntil((() => isExist(".danxuan .yuejuanqu")), { timeout: 8e3 }), !0; } catch { return false; } }, answerHook: e => { const t = O(e.html); e.type = typeMatch(t.find(".tx").text()), e.question = titleClean(removeHtml(t.find(".tm").html())), e.options = e.$options.map(((e, t) => removeHtml(O(t).siblings(".xxnr").html()))).get(); let n = ""; t.find(".yuejuanqu > div").each(((e, t) => { const a = removeHtml(O(t).html()); a.startsWith("\u7b54\u6848\uff1a") && (n = a.replace("\u7b54\u6848\uff1a", "").trim()); })); const lettersToOptions2 = () => (n.match(/[A-Za-z]/g) || []).map((t => e.options[t.toUpperCase().charCodeAt(0) - 65])).filter((e => null != e && "" !== e)); switch (e.type) { case "0": case "1": e.answer = lettersToOptions2(); break; case "3": { const t = lettersToOptions2(); e.answer = judgeAnswer(t[0] || n), e.options = []; break; } default: e.answer = n ? [ n ] : []; } return e; } }, { type: "ask", name: "\u4ebf\u5b66\u5b9d\u7b54\u9898", match: () => location.host.includes("yxbyun.com") && (location.href.includes("yxbstudent/#/testPaper") || location.href.includes("yxbstudent/#/finalExam")), types: [ "0", "1", "3" ], question: { html: ".test_wrap", question: ".content", options: ".answer>.daan,.el-radio-group>label", type: ".question-box .tag", workType: "yxbyun", pageType: "yxbyun" }, init: async () => { await waitUntil((function() { return isExist(".test_wrap"); })); }, ischecked: e => e.hasClass("active"), questionHook: e => { var t; const n = O(e.html).find("div:eq(0)")[0].__vue__, a = (null == (t = n.pagerData) ? void 0 : t.question) || n.smallPaper.questionTopic; if (e.type = typeMatch(n.queTypeName), e.question = titleClean(removeHtml(a.questionTitle)), e.options = (a.optionList || a.questionOptionList).map((e => removeHtml(e.questionContent))), "3" === e.type) e.options = []; return e; }, setAnswer: e => { if ("3" === e.type) { let t = e.answer; return e.ques.$options.each(((e, n) => { isTrue(t) && isTrue(removeHtml(O(n).parent().html())) && O(n).click(), isFalse(t) && isFalse(removeHtml(O(n).parent().html())) && O(n).click(), removeHtml(O(n).parent().html()); })), false; } return true; } }, { type: "ask", name: "\u4ebf\u5b66\u5b9d\u4f5c\u4e1a/\u8003\u8bd5\u7b54\u9898", match: () => location.host.includes("yxb4student.yxbyun.com") && (location.pathname.includes("/zuoye") || location.pathname.includes("/exam")), types: [ "0", "1", "3" ], question: { html: ".danxuan", question: ".tm", options: ".xxbh", type: ".tx", workType: "yxbyun", pageType: "yxbyun" }, init: async () => { await waitUntil((function() { return isExist(".danxuan .xuanxiang"); })); }, ischecked: e => e.hasClass("active"), questionHook: e => (e.type = typeMatch(O(e.html).find(".tx").text()), e.options = e.$options.map(((e, t) => removeHtml(O(t).siblings(".xxnr").html()))).get(), "3" === e.type && (e.options = []), e), setAnswer: e => { if ("3" === e.type) { const t = e.answer; return e.ques.$options.each(((e, n) => { const a = removeHtml(O(n).siblings(".xxnr").html()); isTrue(t) && isTrue(a) && O(n).click(), isFalse(t) && isFalse(a) && O(n).click(); })), false; } return true; } } ], ln = [ { type: "hook", name: "hook", match: location.host.includes("wdjycj.com") || location.host.includes("iwdjy.com"), main: e => { observeVuePageChange(O("#app")[0], (() => getUrl())); } }, { type: "save", name: "\u6587\u9876\u5728\u7ebf\u6536\u5f55", match: () => location.href.includes("/testpaper-test-result?resultId=") || location.href.includes("/testpaper-test?id"), question: { html: ".st-item", question: ".st-title", options: ".st-main>p", type: ".question-box .tag", workType: "wdzx", pageType: "wdzx" }, init: async () => { await waitUntil((function() { return isExist(".st-item"); })); let e = []; try { O(".exam-html")[0].__vue__.test.lists.forEach(((t, n) => { t.question_lists.forEach(((t, n) => { e.push(t); })); })); } catch (t) {} unsafeWindow.ques = e; }, answerHook: (e, t) => { var n; const a = unsafeWindow.ques[t], r = []; switch (e.question = titleClean(removeHtml(a.content)), e.options = (null == (n = a.appanswer) ? void 0 : n.map((e => { const t = removeHtml(e.text); return e.right && r.push(t), removeHtml(t); }))) || [], a.tm_type) { case 4: e.type = "3", e.answer = judgeAnswer("1" == a.answer ? "\u6b63\u786e" : "0" == a.answer ? "\u9519\u8bef" : ""); break; case 5: e.type = "2", e.question = e.question.replace(/{#answer}/g, "_____"), e.answer = a.answer.split("|").map((e => e.includes("\u203b") ? e.split("\u203b")[0] : e)); break; case 2: e.type = "0", e.answer = r; break; case 3: e.type = "1", e.answer = r; break; case 1: e.type = "4", e.answer = removeHtml(a.answer); break; default: a.tm_type; } return e; } }, { type: "ask", name: "\u6587\u9876\u5728\u7ebf\u7b54\u9898", tips: "", match: () => location.href.includes("/testpaper-test?id=") || location.href.includes("/final-exam"), types: [ "0", "1", "2", "3" ], question: { html: ".st-item", question: ".st-title", options: ".st-main>p", type: ".question-box .tag", workType: "wdzx", pageType: "wdzx" }, init: async () => { await waitUntil((function() { return isExist(".st-item"); })); }, toquestion: e => { O(`.card-box .bj:eq(${e})`).click(); }, ischecked: e => O(e).find("input").prop("checked"), questionHook: (e, t) => { e.options = removeOptionsStartChar(e.options); const n = O(e.html).find(".st-title").clone(); O(n).find("strong").remove(), e.question = removeHtml(O(n).html()); let a = O(e.html).prevAll(".title").first().text().trim(); return e.type = typeMatch(a), e.$options = O(e.html).find(".answer-box>.answer>label"), e; }, setAnswer: e => { switch (e.type) { case "4": case "5": case "6": case "7": return O(e.html).find(".answer-text>div")[0].__vue__.msg.yourAnswer = e.answer[0], O(e.html).find(".quill-editor").map(((t, n) => { n.__vue__.value = e.answer[t]; })), false; case "2": let setYourAnswerById = function(e, t, n) { for (let a of e) if (Array.isArray(a.itemlists)) for (let e of a.itemlists) if (e.id === t) return e.yourAnswer = n, true; return false; }; const t = O(e.html).find("span.bj input").attr("name"); return setYourAnswerById(O(".exam-html")[0].__vue__.answerCard, Number(t), e.answer), e.answer, false; } return true; } } ], cleanOptionText = e => e.replace(/ /g, " ").replace(/\uff08\u60a8\u7684\u9009\u62e9\uff09/g, "").replace(/\uff08\u6b63\u786e\u7b54\u6848\uff09/g, "").replace(/^\s*[A-Z]\s*[\.\u3001\uff0e]\s*/, "").replace(/\s+/g, " ").trim(), getSectionType = e => { const t = O(e)[0]; if (!t) return typeMatch(""); const n = (t.closest(".exam-section") || document).querySelectorAll(".section-title, .exam-title"); let a = ""; for (let r = 0; r < n.length; r++) { const e = n[r]; if (!(e.compareDocumentPosition(t) & Node.DOCUMENT_POSITION_FOLLOWING)) break; a = e.textContent || ""; } return typeMatch(a); }, cn = [ { type: "ask", name: "\u6b66\u6c49\u7406\u5de5\u7ee7\u7eed\u6559\u80b2\u7b54\u9898", tips: "\u6b66\u6c49\u7406\u5de5\u7ee7\u7eed\u6559\u80b2\u4ec5\u652f\u6301\u9009\u62e9\u3001\u5224\u65ad\u9898\u5176\u4ed6\u9898\u578b\u6682\u4e0d\u652f\u6301\uff0c\u82e5\u6709\u9700\u8981\u8bf7\u53cd\u9988\u7ed9\u4f5c\u8005", match: () => location.href.includes("/student/study/examPage") && !location.href.includes("/student/study/examPageShow"), question: { html: ".question-item", question: ".question-content", options: ".answer-option .el-radio, .answer-option .el-checkbox", type: "", workType: "whut", pageType: "whut" }, init: async () => { await waitUntil((function() { return 0 !== O(".question-item").length; })); }, ischecked: e => e.find("input").is(":checked"), questionHook: e => { e.question = titleClean(e.question), e.question = e.question.replace(/^\d+\s*[\u3001.\uff09)]/, "").trim(); const t = []; return e.$options.each(((e, n) => { const a = O(n).clone(); a.find(".el-radio__input, .el-checkbox__input, input").remove(), t.push(cleanOptionText(a.text())); })), e.options = t, e.type = getSectionType(e.html), e.type, e; } }, { type: "save", name: "\u6b66\u6c49\u7406\u5de5\u7ee7\u7eed\u6559\u80b2\u6536\u5f55", match: () => location.href.includes("/student/study/examPageShow"), question: { html: ".question-item", question: ".question-content", options: ".option-item", type: "", workType: "whut", pageType: "whut" }, init: async () => { await waitUntil((function() { return 0 !== O(".question-item").length && 0 !== O(".question-item .correct-answer, .question-item .option-item.correct").length; })); }, answerHook: e => { e.question = titleClean(e.question), e.question = e.question.replace(/^\d+\s*[\u3001.\uff09)]/, "").trim(); const t = []; e.$options.each(((e, n) => { const a = O(n).clone(); a.find(".option-label, .user-choice, .correct-answer").remove(), t.push(cleanOptionText(a.text())); })), e.options = t, e.type = getSectionType(e.html); const n = []; return e.$options.each(((t, a) => { (O(a).hasClass("correct") || O(a).find(".correct-answer").length > 0) && n.push(e.options[t]); })), "3" === e.type ? (e.answer = n.length ? n[0] : "", e.options = []) : e.answer = n, e; } } ], un = [ { type: "save", name: "\u4e1c\u5317\u8d22\u7ecf\u5927\u5b66\u6210\u6559\u6536\u5f55", match: () => location.host.includes("dufe.edu.cn") && (location.href.includes("/HomeWorkPaper") || location.href.includes("/HomeWorkHistoryPaper") || location.href.includes("/ExercisesPaper")), question: { html: ".QuestTrunk,.HistoryQuestTrunk", question: ".CBTPaperMain-divInline", options: ".CBTPaperMain-options li", type: ".question-box .tag", workType: "dufe", pageType: "dufe" }, init: async () => { await waitUntil((function() { return isExist(".QuestTrunk,.HistoryQuestTrunk"); })); }, answerHook: e => { const t = e.html.vtree[0].vmodel._trunks[0], n = e.html.vtree[0].vmodel._type; let a = [], r = []; const getOption = () => { t.QUESTION_OPTIONS.forEach((e => { const t = removeHtml(e.OPTION_CONTENT); "1" === e.ISTRUE && a.push(t), r.push(t); })); }; switch (n) { case "001": e.type = "0", getOption(); break; case "002": e.type = "1", getOption(); break; case "004": e.type = "3", e.options = [], a = "1" === t.QUESTION_OPTIONS[0].ISTRUE ? [ "\u6b63\u786e" ] : "0" === t.QUESTION_OPTIONS[0].ISTRUE ? [ "\u9519\u8bef" ] : []; break; case "005": e.type = "4", a = [ removeHtml(t.QUESTION_OPTIONS[0].OPTION_CONTENT) ]; } return e.question = titleClean(t.QUESTION_TITLE), e.options = r, e.answer = a, e; } }, { type: "ask", name: "\u4e1c\u5317\u8d22\u7ecf\u5927\u5b66\u6210\u6559\u7b54\u9898", match: () => location.host.includes("dufe.edu.cn") && (location.href.includes("/HomeWorkPaper") || location.href.includes("/ExercisesPaper")), types: [ "0", "1", "3", "4" ], question: { html: ".QuestTrunk", question: ".CBTPaperMain-divInline", options: ".CBTPaperMain-options li>label", type: ".question-box .tag", workType: "dufe", pageType: "dufe" }, init: async () => {}, ischecked: e => e.parent().find("input").prop("checked"), questionHook: e => { const t = e.html.vtree[0].vmodel._trunks[0], n = e.html.vtree[0].vmodel._type; let a = [], r = []; const getOption = () => { t.QUESTION_OPTIONS.forEach((e => { const t = removeHtml(e.OPTION_CONTENT); "1" === e.ISTRUE && a.push(t), r.push(t); })); }; switch (n) { case "001": e.type = "0", getOption(); break; case "002": e.type = "1", getOption(); break; case "004": e.type = "3", e.options = [], a = "1" === t.QUESTION_OPTIONS[0].ISTRUE ? [ "\u6b63\u786e" ] : "0" === t.QUESTION_OPTIONS[0].ISTRUE ? [ "\u9519\u8bef" ] : []; break; case "005": e.type = "4", a = [ removeHtml(t.QUESTION_OPTIONS[0].OPTION_CONTENT) ]; } return e.question = titleClean(t.QUESTION_TITLE), e.options = r, e.answer = a, e; }, setAnswer: e => { if ("4" === e.type) { const t = O(e.html).find("textarea")[0]; return t._ms_context_._answer = e.answer[0], t._ms_context_._save(), false; } return true; } }, { type: "ask", name: "\u4e1c\u5317\u8d22\u7ecf\u5927\u5b66\u6210\u6559\u7b54\u9898(\u7efc\u5408)", match: () => location.host.includes("dufe.edu.cn") && location.href.includes("/CompHomeworkPaper"), types: [ "0", "1", "3", "4" ], question: { html: ".Question", question: ".CBTPaperMain-trunkTitle", options: "ul.Question-options>li", type: ".question-box .tag", workType: "dufe", pageType: "dufe" }, init: async () => {}, ischecked: e => e.parent().find("input").prop("checked"), questionHook: e => { const t = (e => { var t; if (e) { const n = Object.keys(e).find((e => e.startsWith("__reactEventHandlers"))); if (n) { const t = e[n]; return console.log("React \u4e8b\u4ef6\u5904\u7406\u5bf9\u8c61:", t), t; } if (!n) { const n = Object.keys(e).find((e => e.startsWith("__reactInternalInstance$") || e.startsWith("__reactFiber$"))); if (n && (null == (t = e[n]) ? void 0 : t.memoizedProps)) return console.log("React \u5185\u90e8\u6570\u636e:", e[n].memoizedProps), e[n].memoizedProps; } } else console.error("\u672a\u627e\u5230 .Question \u5143\u7d20"); })(e.html).children[0]._owner.memoizedProps; return e.type = { SingleChoice: "0", MultipleChoice: "1" }[t.type], e.options = removeStartChar(e.options), e; }, setAnswer: e => { if ("4" === e.type) { const t = O(e.html).find("textarea")[0]; return t._ms_context_._answer = e.answer[0], t._ms_context_._save(), false; } return true; } } ], pn = { single: "0", multiple: "1", judge: "3" }, parseCfyOptions = e => JSON.parse(e).map((e => removeHtml(e.content))), dn = [ { type: "hook", name: "hook", match: location.host.includes("lygtc.edu.cn") || location.host.includes("cfyedu.com"), main: () => { observeVuePageChange(O("#app")[0], (() => O("#app")[0].__vue__.$route.path)); } }, { type: "save", name: "\u6625\u98ce\u96e8\u6536\u5f55", match: () => location.host.includes("lygtc.edu.cn") && (location.href.includes("/student/#/my-study/homework/records/detail") || location.href.includes("/student/#/my-study/homework")), question: { html: ".questions>div>div[id],.question>div>div[id]", question: ".topic-title", options: ".el-radio-group label .label,.el-checkbox-group label .label", type: ".question-box .tag", workType: "cfy", pageType: "cfy" }, init: async () => { await waitUntil((() => 0 !== O(".questions>div>div[id],.question>div>div[id]").length)); }, answerHook: e => { const t = O(e.html).find(">div")[0].__vue__.question; return e.question = titleClean(removeHtml(t.title)), e.options = parseCfyOptions(t.options), e.answer = t.answer.split("").map((t => e.options[t.charCodeAt(0) - 65])).filter(Boolean), e.type = pn[t.type] || "", "judge" === t.type && (e.options = [], e.answer = [ judgeAnswer(t.answer) ]), t.type, e; } }, { type: "ask", name: "\u6625\u98ce\u96e8\u7b54\u9898", tips: "\u516c\u544a", match: () => location.host.includes("lygtc.edu.cn") && location.href.includes("/student/#/my-study/homework"), types: Object.values(pn), question: { html: ".question>div>div[id]", question: ".question-title>.title", options: ".radio-option", type: ".question-box .tag", workType: "cfy", pageType: "cfy" }, init: async () => { await waitUntil((() => 0 !== O(".question>div>div[id]").length)); }, ischecked: e => e.find(".el-radio__input.is-checked").length > 0, questionHook: e => { const t = O(e.html).find(">div")[0].__vue__.question; return e.question = titleClean(removeHtml(t.title)), e.options = parseCfyOptions(t.options), e.type = pn[t.type] || "", "judge" === t.type && (e.options = [], e.answer = [ judgeAnswer(t.answer) ]), e; } }, { type: "save", name: "\u6625\u98ce\u96e8\u6d4b\u9a8c\u6536\u5f55", match: () => location.host.includes("cfyedu.com") && location.href.includes("/student/#/my-exam/detail"), question: { html: ".questions>div>div[id]", question: ".question-title>.title", options: ".radio-option,.checkbox-option", type: ".question-box .tag", workType: "cfy", pageType: "cfy" }, init: async () => { await waitUntil((() => 0 !== O(".questions>div>div[id]").length)); }, answerHook: e => { const t = O(e.html).find(">div")[0].__vue__.question; return e.question = titleClean(removeHtml(t.title)), e.options = parseCfyOptions(t.options), e.answer = t.answer.split("").map((t => e.options[t.charCodeAt(0) - 65])).filter(Boolean), e.type = pn[t.type] || "", "judge" === t.type && (e.options = [], e.answer = [ judgeAnswer(t.answer) ]), t.type, e; } }, { type: "ask", name: "\u6625\u98ce\u96e8\u6d4b\u9a8c\u7b54\u9898", tips: "\u516c\u544a", match: () => location.host.includes("cfyedu.com") && location.href.includes("/student/#/my-test/do-test"), types: Object.values(pn), question: { html: ".answer div[id]", question: ".question-title>.title", options: ".radio-option,.checkbox-option", type: ".question-box .tag", workType: "cfy", pageType: "cfy" }, init: async () => { await waitUntil((() => 0 !== O(".answer div[id]").length)); }, ischecked: e => e.find(".el-radio__input.is-checked,.el-checkbox__input.is-checked").length > 0, questionHook: e => { const t = O(e.html).find(">div")[0].__vue__.question; return e.question = titleClean(removeHtml(t.title)), e.options = parseCfyOptions(t.options), e.type = pn[t.type] || "", "judge" === t.type && (e.options = [], e.answer = [ judgeAnswer(t.answer) ]), e; } } ], mn = [ { type: "hook", name: "hook", match: location.host.includes("jijiaool.com"), main: e => { observeVuePageChange(O(".contentIframe")[0], (() => O(".contentIframe").attr("src"))); } }, { type: "ask", name: "\u7ee7\u6559\u5728\u7ebf\u7b54\u9898", match: () => location.href.includes("jijiaool.com") && location.href.includes("/Learning/CourseOnlineExamination"), types: [ "0", "1" ], question: { html: ".bank_test>.test_item", question: ".test_item_tit", options: ".test_item_theme>ul>li>label", type: ".question-box .tag", workType: "jijiaool", pageType: "jijiaool" }, init: async () => { await waitUntil((function() { return isExist(".bank_test>.test_item"); })); }, ischecked: isParentChecked, questionHook: e => { const t = O(e.html).find(".test_item_tit").clone(); t.find(".tipNodo").remove(), e.question = titleClean(removeHtml(t.html())); const n = removeOptionsStartChar(e.options); n && (e.options = n); const a = O(e.html).prevAll(".test_item_type").first().text().trim(); return e.type = typeMatch(a), e; } }, { type: "save", name: "\u7ee7\u6559\u5728\u7ebf\u6536\u5f55", match: () => location.href.includes("jijiaool.com") && location.href.includes("/Learning/CourseExamWorkPageDetail"), question: { html: ".bank_test>.test_item", question: ".test_item_tit", options: ".test_item_theme>ul>li>label", type: ".question-box .tag", workType: "jijiaool", pageType: "jijiaool" }, init: async () => { await waitUntil((function() { return isExist(".bank_test>.test_item"); })); }, answerHook: e => { const t = O(e.html).find(".test_item_tit").clone(); t.find(".tipNodo").remove(), e.question = titleClean(removeHtml(t.html())); const n = removeOptionsStartChar(e.options); n && (e.options = n); const a = O(e.html).prevAll(".test_item_type").first().text().trim(); e.type = typeMatch(a); const r = O(e.html).find(".test_item_tit:eq(1)"), i = r.length ? removeHtml(r.html()).replace(/\u6b63\u786e\u7b54\u6848\uff1a/g, "").trim() : ""; if (i) switch (e.type) { case "0": case "1": e.answer = i.split("").map((t => e.options[t.charCodeAt(0) - 65])).filter(Boolean); break; case "3": e.answer = judgeAnswer(i), e.options = []; } else switch (e.type) { case "0": case "1": { const t = []; O(e.html).find(".test_item_theme>ul>li").each(((e, n) => { O(n).find("input:checked").length && t.push(e); })), e.answer = t.map((t => e.options[t])).filter(Boolean); break; } case "3": e.answer = judgeAnswer(O(e.html).find(".test_item_theme input:checked").attr("value") || ""), e.options = []; } return e.answer, e; } } ], hn = [ { type: "save", name: "\u5317\u4eac\u8054\u5927\u5b66\u5802\u6536\u5f55", match: () => location.host.includes("jxjypt.cn") && location.href.includes("/paper/start?pid="), question: { html: "#questionModule>ul>li", question: ".sub-dotitle>pre", options: "dl.sub-answer>dd", type: ".sub-dotitle>i", workType: "jhjypt", pageType: "jhjypt" }, init: async () => {}, answerHook: e => { let t = removeHtml(O(e.html).find(".refer-answer>span>em.right ,.solution .so-timu .wenzi:eq(0)").html()); if (void 0 === t || "undefined" == t) return null; switch (e.options = removeStartChar(e.options), e.type = typeMatch(removeHtml(O(e.html).find(".sub-dotitle>i").text().replace("\n", "").replace(" ", ""))), e.type) { case "0": case "1": e.answer = [], t.split("").forEach((t => { e.answer.push(e.options[t.charCodeAt() - 65]); })); break; case "2": case "4": case "5": case "6": case "7": e.answer = t; } return e; } }, { type: "ask", name: "\u5317\u4eac\u8054\u5927\u5b66\u5802\u7b54\u9898", tips: "\u516c\u544a", match: () => location.host.includes("jxjypt.cn") && location.href.includes("/paper/start?pid="), types: [ "0", "1", "2", "3", "4", "5", "6", "7" ], minDelay: 1e3, answerDelay: 1e3, question: { html: "#questionModule>ul>li", question: ".sub-dotitle>pre", options: "dl.sub-answer>dd", type: ".sub-dotitle>i", workType: "jhjypt", pageType: "jhjypt" }, init: async () => { if (await waitUntil((function() { return 0 !== O("#questionModule>ul>li").length; })), !isExist("#btn_submit")) return false; try { const e = ie.addEventListener; ie.addEventListener = function(t, n, a) { if ("visibilitychange" !== t) return e.call(this, t, n, a); }, ie.paper && void 0 !== ie.paper.isCut && (ie.paper.isCut = 0), Object.defineProperty(ie.document, "visibilityState", { get: function() { return "visible"; }, configurable: !0 }), Object.defineProperty(ie.document, "hidden", { get: function() { return !1; }, configurable: !0 }); } catch (e) {} }, ischecked: e => e.hasClass("cho-this"), questionHook: e => (e.options = removeStartChar(e.options), e.type = typeMatch(removeHtml(O(e.html).find(".sub-dotitle>i").text().replace("\n", "").replace(" ", ""))), e), setAnswer: e => { switch (e.type) { case "2": case "4": case "5": case "6": case "7": const t = O(e.html).find(".e__textarea"); if (t.length > 0) { const n = t[0]; n.value = e.answer, t.focus(); [ "input", "change", "keyup", "keydown", "blur", "paste" ].forEach((e => { const t = new Event(e, { bubbles: true, cancelable: true }); n.dispatchEvent(t); })), t.trigger("input").trigger("change").trigger("keyup").trigger("blur"), setTimeout((() => { t.trigger("change"); }), 100), e.answer; } return false; } return true; } } ], parseAntaiQuestion = e => { const t = "string" == typeof e.options ? e.options : "", n = []; t.split(/[;\uff1b]/).map((e => e.trim())).filter(Boolean).forEach((e => { const t = e.match(/^([A-Za-z])\s*[:\uff1a]\s*([\s\S]*)$/); n.push(removeHtml(t ? t[2] : e).trim()); })); const a = (("string" == typeof e.answer ? e.answer : "").toUpperCase().match(/[A-Z]/g) || []).map((e => e.charCodeAt(0) - 65)).filter((e => e >= 0 && e < n.length)), r = a.map((e => n[e])); let i; 1 === e.type ? i = "0" : 2 === e.type ? i = "3" : (i = r.length > 1 ? "1" : "0", e.type); const s = { question: titleClean(removeHtml(e.content || "")), options: n, answer: r, answerIndexes: a, type: i }; return "3" === i && (s.options = [], s.answer = judgeAnswer(r[0] || ""), s.answerIndexes = []), s; }, isAntai = () => "antai.geovisearth.com" === location.host, fn = [ { type: "save", name: "\u5b89\u6cf0\u5b89\u57f9\u6536\u5f55", match: () => isAntai() && !!ie.antaiques, question: { html: () => ie.antaiques || [], question: "", options: "", type: "", workType: "antai", pageType: "antai" }, init: async () => { await waitUntil((() => !!ie.antaiques)); }, answerHook: e => { const t = e.html; if (!t || "object" != typeof t) return null; const n = parseAntaiQuestion(t); return e.question = n.question, e.options = n.options, e.answer = n.answer, e.type = n.type, e; } }, { type: "ask", name: "\u5b89\u6cf0\u5b89\u57f9\u7b54\u9898", tips: "", match: () => isAntai() && !!ie.antaiques && O(".n-card.n-modal .el-carousel__item").length > 0, types: [ "0", "1", "3" ], question: { html: ".n-card.n-modal .el-carousel__item", question: ".el-tag", options: ".el-radio", type: ".el-tag__content", workType: "antai", pageType: "antai" }, init: async () => { await waitUntil((() => O(".n-card.n-modal .el-carousel__item").length > 0 && !!ie.antaiques)); }, ischecked: e => e.hasClass("is-checked"), toquestion: e => { const t = String(e + 1); O(".n-card.n-modal button").filter((function() { return O(this).text().trim() === t; })).first().click(); }, questionHook: (e, t) => { const n = (ie.antaiques || [])[t]; if (!n) return null; const a = parseAntaiQuestion(n); e.question = a.question, e.options = a.options, e.type = a.type, e.$options = O(e.html).find(".el-radio"), "3" === a.type && (e.options = []); const r = normalizeQuestionForAsk({ type: a.type, question: titleClean(a.question), options: "3" === a.type ? [] : a.options }), i = "3" === a.type ? a.answer : a.answerIndexes.map((e => r.options[e])).filter((e => null != e && "" !== e)); return i.length > 0 && Answer.cacheAnswer({ type: r.type, question: r.question, options: r.options, answer: i }), e; } } ], gn = { 1: "0", 2: "1", 3: "4", 4: "15", 5: "2", 6: "3", 7: "5", 8: "4", 9: "7", 11: "6", 14: "14" }, parseBgzkQuestion = e => { const t = (e => gn[Number(e.questionType)] || "8")(e), n = e.options ?? [], a = n.map((e => (null == e ? void 0 : e.description) ?? "")), r = ((e, t) => { const n = []; return e.forEach(((e, a) => { const r = String((null == e ? void 0 : e.label) ?? "").trim().toUpperCase(), i = /^[A-Z]$/.test(r) ? r.charCodeAt(0) - 65 : a; n[i] = t[a]; })), n; })(n, a), i = buildQingshuAnswer(t, e, r), s = "0" === t || "1" === t ? (o = e.solution, o ? o.split("").filter((e => /^[A-Za-z]$/.test(e))) : []).map((e => n.findIndex((t => String((null == t ? void 0 : t.label) ?? "").trim().toUpperCase() === e.toUpperCase())))).filter((e => e >= 0)) : []; var o; return { question: e.description ?? "", options: "3" === t ? [] : a, answer: i.answer, answerIndexes: s, type: t }; }, hasBgzkSolution = e => !!(null == e ? void 0 : e.solution) || ((null == e ? void 0 : e.subQuestions) ?? []).some((e => !!(null == e ? void 0 : e.solution))), vn = [ 2, 3, 4 ], yn = [ -1, 0, 1 ], bn = [ /\/Student\/Course\/Quiz\/Detail/i, /\/Student\/course\/resource\/quizDetail/i, /\/Student\/exam\/quiz/i ], wn = ".question-quiz > .question-detail-container", isQuizPage = () => location.host.endsWith("bgzk-edu.cn") && bn.some((e => e.test(location.pathname))), getQuestions$1 = () => ie.bgzkques || [], hasSolutions = () => getQuestions$1().some(hasBgzkSolution), isAnalysisMode = () => (e => { if (!e) return false; const t = Number(e.answerStatus); return !!vn.includes(t) || 2 === Number(e.quizStatus) && yn.includes(t); })(ie.bgzkquiz || null), questionsLoaded = () => getQuestions$1().length > 0, containersReady = () => isExist(wn) && questionsLoaded(), waitOrSkip = async e => { try { return await waitUntil(e, { timeout: 3e4 }), !0; } catch { return false; } }; let xn = false; const kn = [ { type: "hook", name: "\u5e7f\u897f\u81ea\u8003\u52a9\u5b66hook", match: () => isQuizPage(), main: () => { if (xn) return; xn = true; const getHash = () => `${getQuestions$1().map((e => (null == e ? void 0 : e.questionId) ?? "")).join(",")}|${hasSolutions()}|${isAnalysisMode()}`; waitUntil(questionsLoaded, { timeout: 6e4 }).then((() => { const e = O("#app")[0]; e ? observeVuePageChange(e, getHash, { beforeChange: () => { xn = false; } }) : xn = false; })).catch((() => { xn = false; })); } }, { type: "save", name: "\u5e7f\u897f\u81ea\u8003\u52a9\u5b66\u6536\u5f55", match: () => isQuizPage(), question: { html: () => getQuestions$1(), question: "", options: "", type: "", workType: "bgzk", pageType: "bgzk" }, init: async () => !!(await waitOrSkip(questionsLoaded)) && hasSolutions(), answerHook: e => { const t = e.html; if (!t || "object" != typeof t) return null; const n = parseBgzkQuestion(t); return e.question = n.question, e.options = n.options, e.answer = n.answer, e.type = n.type, e; } }, { type: "ask", name: "\u5e7f\u897f\u81ea\u8003\u52a9\u5b66\u7b54\u9898", tips: "", match: () => isQuizPage(), types: [ "0", "1", "3" ], question: { html: wn, question: ".question-detail-description", options: ".question-detail-options .question-detail-option > label, .question-detail-judgment .el-radio", type: ".question-detail-type-desc", workType: "bgzk", pageType: "bgzk" }, init: async () => !!(await waitOrSkip(questionsLoaded)) && (!isAnalysisMode() && await waitOrSkip(containersReady)), ischecked: e => e.hasClass("choice-active") || e.hasClass("is-checked"), toquestion: e => { O(".question-card .question-item").eq(e).click(); }, questionHook: (e, t) => { const n = getQuestions$1()[t]; if (!n) return null; const a = parseBgzkQuestion(n); return e.question = a.question, e.options = a.options, e.type = a.type, e; } } ], qn = "data-aiask-line", isPageClaimedByNewLine = e => { var t; return "new" === (null == (t = e.documentElement) ? void 0 : t.getAttribute(qn)); }, idText = e => ("string" == typeof e || "number" == typeof e && Number.isSafeInteger(e)) && /^[1-9]\d{0,15}$/.test(String(e)) ? String(e) : "", getUmuAttemptRoot = e => { const t = e.querySelectorAll(".card-quiz, .single-quiz"); if (1 !== t.length) return null; const n = t[0], a = n.querySelectorAll(".question-section").length; return a > 0 && a <= 500 && (n.matches(".single-quiz") || 1 === a) ? n : null; }, parseUmuSections = (e, t) => { if (!Array.isArray(e) || e.length > 500) return []; const n = []; for (const r of e) { const e = null == r ? void 0 : r.questionInfo, a = idText(null == e ? void 0 : e.questionId); if (!a || "radio" !== (null == e ? void 0 : e.domType) || "string" != typeof e.questionTitle || !Array.isArray(r.answerArr)) continue; const i = cleanQuestionTitle(t(e.questionTitle)), s = r.answerArr.map((e => idText(null == e ? void 0 : e.answerId))), o = r.answerArr.map((e => "string" == typeof (null == e ? void 0 : e.answerContent) ? t(e.answerContent) : "")); !i || o.length < 2 || o.length > 26 || o.some((e => !e)) || s.some((e => !e)) || new Set(s).size !== o.length || n.push({ id: a, type: "0", question: i, options: o, optionIds: s }); } const a = new Map; return n.forEach((e => a.set(e.id, (a.get(e.id) || 0) + 1))), n.filter((e => 1 === a.get(e.id))); }, resolveUmuTargets = (e, t, n) => { var a, r; const i = getUmuAttemptRoot(e); if (!i) return null; const s = Array.from(i.querySelectorAll(".question-section")).filter((e => e.querySelector(`input[name="radio_${t.id}"]`))); if (1 !== s.length) return null; const o = s[0], l = Array.from(o.querySelectorAll(".questionOption")); if (l.length !== t.optionIds.length || !/\uff08\u5355\u9009[\uff0c,]/.test((null == (a = o.querySelector(".titleTypeDesc")) ? void 0 : a.textContent) || "")) return null; const c = []; for (const d of t.optionIds) { const e = l.filter((e => { const n = e.querySelector("input"); return "radio" === (null == n ? void 0 : n.type) && n.name === `radio_${t.id}` && n.value === d; })); if (1 !== e.length) return null; c.push(e[0]); } const u = normalizeQuestionForAsk({ type: "0", question: n((null == (r = o.querySelector(".question-title-content .title")) ? void 0 : r.innerHTML) || ""), options: c.map((e => { var t, a; return removeKnownOptionPrefix(n((null == (t = e.querySelector(".option-detail")) ? void 0 : t.innerHTML) || ""), (null == (a = e.querySelector(".letter-index")) ? void 0 : a.textContent) || ""); })) }), p = normalizeQuestionForAsk(t); return u.question === p.question && JSON.stringify(u.options) === JSON.stringify(p.options) ? c : null; }, isUmuOptionSelected = e => e.classList.contains("checked"), getQuestions = () => { var e, t; return parseUmuSections(null == (t = null == (e = ie.pageData) ? void 0 : e.data) ? void 0 : t.sectionArr, removeHtml); }; let An = false, _n = true, Tn = ""; const getPageKey = () => { var e, t, n, a; return `${location.href}|${null == (e = getUmuAttemptRoot(document)) ? void 0 : e.className}|${document.querySelectorAll(".question-section, .section-item").length}|${null == (a = null == (n = null == (t = ie.pageData) ? void 0 : t.data) ? void 0 : n.sectionArr) ? void 0 : a.length}`; }, Cn = [ { type: "hook", name: "UMU \u9875\u9762\u5207\u6362", match: () => "https:" === location.protocol && "m.umu.cn" === location.hostname, main: () => { if (An) return; An = true, Tn = getPageKey(); let e = false, t = 14400; const n = setInterval((async () => { if (--t <= 0) return void clearInterval(n); const a = getPageKey(); if (isPageClaimedByNewLine(document)) Tn = a; else if (_n && !e && a !== Tn) { e = true, Tn = a; try { getAskStore().pause(), await vuePageChange(); } catch (r) {} finally { e = false; } } }), 500); window.addEventListener("pagehide", (e => { e.persisted || clearInterval(n); })); } }, { type: "ask", name: "UMU \u5355\u9009\u7b54\u9898", tips: "\u652f\u6301\u5361\u7247\u5f0f\u4e0e\u6574\u9875\u5355\u9009\u9898\uff1b\u9010\u9898\u539f\u751f\u6682\u5b58\uff0c\u4e0d\u81ea\u52a8\u4ea4\u5377\u3002", match: () => (e => { const t = new URL(e); return "m.umu.cn" === t.hostname && /^\/session\/quiz\/[\w-]+\/?$/.test(t.pathname) && !/\/result\/?$/.test(t.pathname); })(location.href), types: [ "0" ], question: { html: getQuestions, question: "", options: "", type: "", workType: "umu", pageType: "umu" }, init: async () => { _n = false; try { await waitUntil((() => !!getUmuAttemptRoot(document)), { timeout: 1e4, timeoutMessage: "UMU \u5f53\u524d\u672a\u8fdb\u5165\u652f\u6301\u7684\u4f5c\u7b54\u9875" }); } catch (e) { return false; } finally { Tn = getPageKey(), _n = true; } return getQuestions().length > 0; }, questionHook: e => { const t = e.html; return { ...e, ...t, umu: t, html: getUmuAttemptRoot(document), $options: O() }; }, ischecked: e => !!e[0] && isUmuOptionSelected(e[0]), setAnswer: async ({answer: e, ques: t, rule: n}) => { const a = (e => { var t, n, a; const r = getUmuAttemptRoot(e), i = (null == r ? void 0 : r.matches(".single-quiz")) ? r : null == r ? void 0 : r.querySelector(".controller-panel"); if (!i) return null; const s = Object.keys(i).find((e => e.startsWith("__reactFiber$"))); if (!s) return null; let o, l, c = i[s]; for (let u = 0; c && u < 100; u++, c = c.return) { const e = c.stateNode; "function" == typeof (null == e ? void 0 : e.displayCard) && Array.isArray(null == (t = e.props) ? void 0 : t.sections) && (o = e), "function" == typeof (null == e ? void 0 : e.saveQuiz) && e.oldSaveData && "object" == typeof e.oldSaveData && (l = e); } return l && (o || (null == r ? void 0 : r.matches(".single-quiz")) && Array.isArray(null == (a = null == (n = l.props) ? void 0 : n.pageData) ? void 0 : a.sectionArr)) ? { controller: o, exam: l } : null; })(document); if (!a) throw new Error("UMU \u539f\u751f\u5207\u9898\u6216\u6682\u5b58\u5165\u53e3\u4e0d\u53ef\u7528"); const r = getAskStore(), i = r.runToken, shouldContinue = () => r.runToken === i; return await (async (e, t, n, a, r, i, s) => { var o, l, c, u; const check = () => assertFillShouldContinue({ shouldContinue: s }); if (check(), 1 !== n.length || !Number.isInteger(n[0]) || !t.optionIds[n[0]]) throw new Error("UMU \u5355\u9009\u7b54\u6848\u4e0d\u660e\u786e"); const {controller: p, exam: d} = a, m = (null == p ? void 0 : p.props.sections) ?? (null == (l = null == (o = d.props) ? void 0 : o.pageData) ? void 0 : l.sectionArr); if (!Array.isArray(m) || !p && !(null == (c = getUmuAttemptRoot(e)) ? void 0 : c.matches(".single-quiz"))) throw new Error("UMU \u539f\u751f\u8bd5\u5377\u6570\u636e\u4e0d\u53ef\u7528"); const h = m.map(((e, t) => ({ s: e, index: t }))).filter((({s: e}) => { var n; return idText(null == (n = null == e ? void 0 : e.questionInfo) ? void 0 : n.questionId) === t.id; })), f = parseUmuSections(h.map((({s: e}) => e)), r)[0], g = new Map(null == f ? void 0 : f.optionIds.map(((e, t) => [ e, f.options[t] ]))); if (1 !== h.length || !f || f.question !== t.question || g.size !== t.optionIds.length || t.optionIds.some(((e, n) => g.get(e) !== t.options[n]))) throw new Error("UMU \u8bd5\u5377\u6570\u636e\u5df2\u53d8\u5316\uff0c\u62d2\u7edd\u56de\u586b"); null == p || p.displayCard(h[0].index); let v = null; await waitUntil((() => (check(), v = resolveUmuTargets(e, t, r), !!v)), { timeout: 5e3, timeoutMessage: "UMU \u5207\u9898\u672a\u786e\u8ba4\uff0c\u62d2\u7edd\u56de\u586b" }), check(), await i(v); const y = t.optionIds[n[0]]; let b; await waitUntil((() => { check(); const n = resolveUmuTargets(e, t, r); return !!n && n.every((e => { const t = e.querySelector("input"); return isUmuOptionSelected(e) === (t.value === y); })); }), { timeout: 3e3, timeoutMessage: "UMU \u9009\u4e2d\u72b6\u6001\u672a\u786e\u8ba4" }), check(); try { await Promise.race([ d.saveQuiz(), new Promise(((e, t) => { b = setTimeout((() => t(new Error("UMU \u539f\u751f\u6682\u5b58\u8d85\u65f6"))), 15e3); })) ]); } finally { clearTimeout(b); } check(); const w = null == (u = d.oldSaveData[t.id]) ? void 0 : u.answer_ids; if (!Array.isArray(w) || 1 !== w.length || String(w[0]) !== y) throw new Error("UMU \u6682\u5b58\u56de\u6267\u672a\u786e\u8ba4"); })(document, t.umu, e, a, removeHtml, (async a => { t.$options = O(a), await defaultSetAnswer("xx", e, t, n, { shouldContinue: shouldContinue }); }), shouldContinue), false; } }, { type: "save", name: "UMU \u6b63\u786e\u7b54\u6848\u6536\u5f55", tips: "\u6536\u5f55\u5df2\u52a0\u8f7d\u7684\u5355\u9009\u9898\u6b63\u786e\u7b54\u6848\uff1b\u5411\u4e0b\u6eda\u52a8\u4f1a\u7ee7\u7eed\u52a0\u8f7d\u5e76\u6536\u5f55\uff0c\u4e0d\u8bfb\u53d6\u5b66\u751f\u9009\u4e2d\u6001\u3002", match: () => (e => { const t = new URL(e); return "m.umu.cn" === t.hostname && "/session/quiz/result" === t.pathname; })(location.href), init: () => { _n = false; }, question: { html: ".section-item.show-result", question: ".section-title", options: ".form-option-item .option-detail", type: "", workType: "umu", pageType: "umu" }, answerHook: e => { const t = ((e, t) => { var n; if (!e.matches(".section-item.show-result") || !/\uff08\u5355\u9009[\uff0c,]/.test((null == (n = e.querySelector(".section-title-desc")) ? void 0 : n.textContent) || "")) return null; const a = e.querySelector(".section-title"), r = a ? cleanQuestionTitle(t(a.innerHTML)) : "", i = Array.from(e.querySelectorAll(".form-option-item")), s = i.map((e => { var n; return t((null == (n = e.querySelector(".option-detail")) ? void 0 : n.innerHTML) || ""); })), o = i.filter((e => e.classList.contains("is-right"))); return !r || s.length < 2 || s.length > 26 || s.some((e => !e)) || 1 !== o.length ? null : { question: r, options: s, type: "0", answer: [ s[i.indexOf(o[0])] ] }; })(e.html, removeHtml); return t ? { ...e, ...t } : null; }, next: () => { _n = true; } } ], isQuanshianPracticeUrl = e => { try { const t = new URL(e); return "https:" === t.protocol && "new.oberyun.com" === t.hostname && "/learn-course/attend-class" === t.pathname; } catch { return false; } }, isVisible = e => { var t; let n = e; for (let a = 0; n && a < 32; a++, n = n.parentElement) { const e = null == (t = n.ownerDocument.defaultView) ? void 0 : t.getComputedStyle(n); if (n.hasAttribute("hidden") || "none" === (null == e ? void 0 : e.display) || "hidden" === (null == e ? void 0 : e.visibility)) return false; } return null === n; }, getQuanshianPractice = e => { var t; const n = e.querySelectorAll(".practice-wrap"); if (1 !== n.length || !isVisible(n[0])) return null; const a = n[0].__vue__; return "Sexercise" !== (null == (t = null == a ? void 0 : a.$options) ? void 0 : t.name) || a.$el !== n[0] || !Array.isArray(a.list) || a.list.length > 20 || !Number.isSafeInteger(a.activeIndex) || a.activeIndex < 0 || a.activeIndex >= a.list.length || "string" != typeof a.activeId || !a.totalMap || "object" != typeof a.totalMap ? null : a; }, parseQuanshianQuestion = (e, t) => { if (!e || "object" != typeof e) return null; const n = e, a = "\u5355\u9009\u9898" === n.typeName ? "0" : "\u5224\u65ad\u9898" === n.typeName ? "3" : null; if (!a || "string" != typeof n.id || !/^\d{1,24}$/.test(n.id) || !Number.isSafeInteger(n.serialNumber) || Number(n.serialNumber) < 1 || "string" != typeof n.content || n.content.length > 2e4 || n.resource || n.attachment || n.posterImage || /<(?:img|svg|audio|video|canvas|iframe|object)\b/i.test(n.content) || !Array.isArray(n.options) || n.options.length < 2 || n.options.length > 26) return null; const r = []; for (const l of n.options) { if (!l || "string" != typeof l.optText || !l.optText.trim() || l.optText.length > 5e3 || l.optAttachment || /<(?:img|svg|audio|video|canvas|iframe|object)\b/i.test(l.optText)) return null; r.push(l.optText); } const i = cleanQuestionTitle(t(n.content)), s = r.map((e => t(e))), o = s.map(normalizeComparableText); return i && !o.some((e => !e)) && new Set(o).size === o.length && ("3" !== a || 2 === s.length && s.includes("\u6b63\u786e") && s.includes("\u9519\u8bef")) ? { id: n.id, serialNumber: Number(n.serialNumber), type: a, question: i, options: s, values: r } : null; }, parseQuanshianGroup = (e, t) => { const n = e.list, count2 = (e, t) => n.filter((n => (null == n ? void 0 : n[e]) === t)).length; return n.flatMap((e => { const n = parseQuanshianQuestion(e, t); return n && 1 === count2("id", n.id) && 1 === count2("serialNumber", n.serialNumber) ? [ n ] : []; })); }, getQuanshianCard = (e, t, n) => { var a, r, i, s, o; const l = getQuanshianPractice(e); if (!l || l.activeId !== t.id) return null; const c = l.list.filter((e => (null == e ? void 0 : e.id) === t.id)), u = 1 === c.length ? parseQuanshianQuestion(c[0], n) : null; if (!u || u.serialNumber !== t.serialNumber || u.type !== t.type || u.question !== t.question || JSON.stringify([ u.options, u.values ]) !== JSON.stringify([ t.options, t.values ]) || (null == (a = l.list[l.activeIndex]) ? void 0 : a.id) !== t.id || 1 !== l.list.filter((e => (null == e ? void 0 : e.serialNumber) === t.serialNumber)).length) return null; const p = Array.from(l.$el.querySelectorAll(".pc-l")).filter(isVisible); if (1 !== p.length || 1 !== p[0].querySelectorAll(".item-card").length) return null; const d = p[0], m = d.querySelectorAll(".icc-top > div > span"); return (null == (i = null == (r = d.querySelector(".ict-l > span")) ? void 0 : r.textContent) ? void 0 : i.trim()) !== String(t.serialNumber) || (null == (o = null == (s = d.querySelector(".ict-type")) ? void 0 : s.textContent) ? void 0 : o.trim()) !== ("0" === t.type ? "\u5355\u9009\u9898" : "\u5224\u65ad\u9898") || 1 !== m.length || m[0].querySelector("img, svg, audio, video, iframe") || cleanQuestionTitle(n(m[0].innerHTML)) !== t.question ? null : d.querySelector(".item-card"); }, resolveQuanshianTargets = (e, t, n) => { var a; const r = getQuanshianCard(e, t, n), i = null == (a = getQuanshianPractice(e)) ? void 0 : a.totalMap[t.id]; if (!r || (null == i ? void 0 : i.id) !== t.id || 0 !== i.flag) return null; const s = Array.from(r.querySelectorAll(".ic-ops label.el-radio")); if (s.length !== t.options.length || r.querySelector('.ic-ops input:not([type="radio"])')) return null; const o = t.values.map(((e, a) => { const r = s.filter((t => { var n; return (null == (n = t.querySelector("input")) ? void 0 : n.value) === e; })); if (1 !== r.length) return null; const i = r[0], o = i.querySelectorAll("input"), l = i.querySelectorAll(".judgmentContainer > div > span"); return 1 !== o.length || "radio" !== o[0].type || o[0].disabled || "true" === i.getAttribute("aria-disabled") || i.classList.contains("is-disabled") || 1 !== l.length || l[0].querySelector("img, svg, audio, video, iframe") || normalizeComparableText(n(l[0].innerHTML)) !== normalizeComparableText(t.options[a]) ? null : i; })); return o.every((e => !!e)) && new Set(o).size === o.length ? o : null; }, switchQuanshianQuestion = async (e, t, n, a) => { const check = () => assertFillShouldContinue({ shouldContinue: a }); if (check(), getQuanshianCard(e, t, n)) return; const r = getQuanshianPractice(e); if (!r || !parseQuanshianGroup(r, n).some((e => e.id === t.id))) throw new Error("\u5168\u65f6\u5b89\u9898\u76ee\u4e0d\u5728\u5f53\u524d\u9898\u7ec4\uff0c\u8bf7\u91cd\u65b0\u89e3\u6790"); const i = Array.from(r.$el.querySelectorAll(".pw-bottom .pbc-btn button")).filter((e => { var n; return isVisible(e) && (null == (n = e.textContent) ? void 0 : n.trim()) === String(t.serialNumber); })); if (1 !== i.length) throw new Error("\u5168\u65f6\u5b89\u9898\u53f7\u6309\u94ae\u4e0d\u552f\u4e00\uff0c\u62d2\u7edd\u5207\u9898"); i[0].click(), await waitUntil((() => (check(), !!getQuanshianCard(e, t, n))), { interval: 25, timeout: 3e3, timeoutMessage: "\u5168\u65f6\u5b89\u5207\u9898\u672a\u786e\u8ba4\uff0c\u62d2\u7edd\u56de\u586b" }); }, Sn = { judg: "\u5224\u65ad\u9898", sing: "\u5355\u9009\u9898" }, getQuanshianExam = e => { var t; const n = Array.from(e.querySelectorAll(".el-dialog__wrapper")).flatMap((e => { var t, n; let a = e.__vue__; for (let r = 0; a && r < 4 && "CourseTest" !== (null == (t = a.$options) ? void 0 : t.name); r++) a = a.$parent; return "CourseTest" === (null == (n = null == a ? void 0 : a.$options) ? void 0 : n.name) && a.$el === e && isVisible(e) ? [ a ] : []; })); if (1 !== n.length) return null; const a = n[0]; return "string" != typeof (null == (t = a.examInfo) ? void 0 : t.historyId) || !a.examInfo.historyId || !Array.isArray(a.stmpList) || !a.mapVal || "object" != typeof a.mapVal || a.isFiling || a.isInner || a.isTimeOver || a.isStop || a.disabled || a.isPreview ? null : a; }, parseQuanshianExam = (e, t) => { const n = e.stmpList.flatMap((e => e && "string" == typeof e.typeCode && Sn[e.typeCode] && Array.isArray(e.questions) ? e.questions.map((t => ({ raw: t, typeCode: e.typeCode }))) : [])), a = n.map((({raw: e}) => null == e ? void 0 : e.questionId)), r = Object.values(e.mapVal).map((e => null == e ? void 0 : e.key)); return n.flatMap((({raw: n, typeCode: i}) => { if (!n || n.typeCode !== i || "string" != typeof n.questionId) return []; const s = Object.prototype.hasOwnProperty.call(e.mapVal, n.questionId) ? e.mapVal[n.questionId] : void 0; if (!s || s.type !== i || false !== s.disable || 1 !== a.filter((e => e === n.questionId)).length || 1 !== r.filter((e => e === s.key)).length) return []; const o = parseQuanshianQuestion({ ...n, id: n.questionId, typeName: Sn[i], serialNumber: s.key }, t); return o ? [ o ] : []; })); }, getQuanshianExamCard = (e, t) => { const n = getQuanshianExam(e); if (!n) return null; const a = Array.from(n.$el.querySelectorAll(".answer-right .aw-topic")).filter((e => { var n, a; return (null == (a = null == (n = e.querySelector(".awt-no")) ? void 0 : n.textContent) ? void 0 : a.trim()) === String(t.serialNumber); })); return 1 === a.length && isVisible(a[0]) ? a[0] : null; }, resolveQuanshianExamTargets = (e, t, n) => { var a; const r = getQuanshianExam(e), i = r ? parseQuanshianExam(r, n).filter((e => e.id === t.id)) : []; if (1 !== i.length || JSON.stringify(i[0]) !== JSON.stringify(t)) return null; const s = getQuanshianExamCard(e, t), o = null == s ? void 0 : s.querySelectorAll(".awt-desc > div > div > span"); if (!s || !o || 1 !== o.length || (null == (a = s.querySelector(".awt-desc")) ? void 0 : a.querySelector("img, svg, audio, video, iframe")) || cleanQuestionTitle(n(o[0].innerHTML)) !== t.question) return null; const l = Array.from(s.querySelectorAll(".awt-ops label.el-radio")); if (l.length !== t.options.length || s.querySelector('.awt-ops input:not([type="radio"])')) return null; const c = t.values.map(((e, a) => { const r = l.filter((t => { var n; return (null == (n = t.querySelector("input")) ? void 0 : n.value) === e; })); if (1 !== r.length) return null; const i = r[0], s = i.querySelectorAll("input"), o = i.querySelectorAll(".el-radio__label > div > span"); return 1 !== s.length || "radio" !== s[0].type || s[0].disabled || "true" === i.getAttribute("aria-disabled") || i.classList.contains("is-disabled") || 1 !== o.length || o[0].querySelector("img, svg, audio, video, iframe") || normalizeComparableText(n(o[0].innerHTML)) !== normalizeComparableText(t.options[a]) ? null : i; })); return c.every((e => !!e)) && new Set(c).size === c.length ? c : null; }, pageDocument = () => ie.document, getGroup = () => { if (!isQuanshianPracticeUrl(location.href)) return null; const e = getQuanshianPractice(pageDocument()); return e ? { component: e, questions: parseQuanshianGroup(e, removeHtml) } : null; }, getAttempts = () => { const e = getGroup(); return e ? e.questions.filter((t => { var n; return 0 === (null == (n = e.component.totalMap[t.id]) ? void 0 : n.flag); })) : []; }, getAnswers = () => { const e = getGroup(); if (!e) return []; const t = new Set(e.questions.map((e => e.id))); return e.component.list.flatMap((e => { const n = ((e, t) => { const n = parseQuanshianQuestion(e, t); if (!n) return null; const a = e.answer, r = "string" == typeof a ? n.values.indexOf(a) : -1; return r >= 0 ? { ...n, answer: [ n.options[r] ] } : null; })(e, removeHtml); return n && t.has(n.id) ? [ n ] : []; })); }, getExamQuestions = () => { if (!isQuanshianPracticeUrl(location.href)) return []; const e = getQuanshianExam(pageDocument()); return e ? parseQuanshianExam(e, removeHtml) : []; }; let In = false; const En = [ { type: "hook", name: "\u5168\u65f6\u5b89\u7ec3\u4e60\u5207\u6362", match: () => "https:" === location.protocol && "new.oberyun.com" === location.hostname, main: () => { if (In) return; In = true; const key = () => { var e; return JSON.stringify([ location.pathname, null == (e = getGroup()) ? void 0 : e.component.list.map((e => null == e ? void 0 : e.id)), getExamQuestions().map((e => e.id)) ]); }; let e = key(), t = false, n = 14400; const stop = () => { clearInterval(a), In = false; }, a = setInterval((async () => { if (--n <= 0 || isPageClaimedByNewLine(document)) return void stop(); const a = key(); if (t || e === a) return; let r; e = a, t = true; try { const e = getAskStore(); e.pause(), e.clearQuestion(), await Promise.race([ vuePageChange(), new Promise(((e, t) => { r = setTimeout((() => t(new Error("\u5168\u65f6\u5b89\u9875\u9762\u89e3\u6790\u8d85\u65f6\uff0c\u8bf7\u5237\u65b0\u540e\u91cd\u8bd5"))), 2e4); })) ]); } catch (i) { stop(), getAskStore().pause(); } finally { clearTimeout(r), t = false; } }), 500); window.addEventListener("pagehide", (e => { e.persisted || stop(); }), { once: true }); } }, { type: "save", name: "\u5168\u65f6\u5b89\u9898\u7ec4\u6536\u5f55", tips: "\u6536\u5f55\u5f53\u524d\u9898\u7ec4\u5168\u90e8\u5355\u9009\u3001\u5224\u65ad\u9898\u7684\u5e73\u53f0\u516c\u5e03\u7b54\u6848\uff0c\u7ffb\u7ec4\u540e\u81ea\u52a8\u6536\u5f55\u65b0\u7ec4\uff1b\u4e0d\u8bfb\u53d6\u5b66\u751f\u6240\u9009\u503c\u3002", match: () => getAnswers().length > 0, question: { html: getAnswers, question: "", options: "", type: "", workType: "quanshian", pageType: "quanshian" }, answerHook: e => { var t; return { ...e, ...e.html, html: null == (t = getGroup()) ? void 0 : t.component.$el }; } }, { type: "ask", name: "\u5168\u65f6\u5b89\u7ec3\u4e60\u5355\u9009\u4e0e\u5224\u65ad", tips: "\u5217\u51fa\u5f53\u524d\u9898\u7ec4\u672a\u505a\u7684\u5355\u9009\u3001\u5224\u65ad\u9898\uff0c\u70b9\u9009\u9898\u76ee\u6216\u7b54\u9898\u65f6\u539f\u751f\u5207\u9898\uff1b\u4e0d\u8de8\u7ec4\u3001\u4e0d\u81ea\u52a8\u63d0\u4ea4\u3002\u6b63\u5f0f\u8003\u8bd5\u3001\u591a\u9009\u548c\u56fe\u7247\u9898\u672a\u9a8c\u3002", match: () => getAttempts().length > 0, types: [ "0", "3" ], init: () => getAttempts().length > 0, question: { html: getAttempts, question: "", options: "", type: "", workType: "quanshian", pageType: "quanshian" }, questionHook: e => { var t; const n = e.html; return { ...e, ...n, quanshian: n, html: null == (t = getGroup()) ? void 0 : t.component.$el, $options: O() }; }, toquestion: e => { var t; const n = null == (t = getAskStore().questionList[e]) ? void 0 : t.quanshian; n && switchQuanshianQuestion(pageDocument(), n, removeHtml, (() => isQuanshianPracticeUrl(location.href))).catch((e => msg(`\u5168\u65f6\u5b89\u5207\u9898\u5931\u8d25\uff1a${e instanceof Error ? e.message : String(e)}`, "warning"))); }, ischecked: e => e.hasClass("is-checked") && !!e.find("input").prop("checked"), setAnswer: async ({answer: e, ques: t, rule: n}) => { const a = t.quanshian, r = "3" === a.type ? [ a.options.indexOf(normalizeJudgeAnswer(e) ?? "") ] : e, i = getAskStore(), s = i.runToken, shouldContinue = () => i.runToken === s && isQuanshianPracticeUrl(location.href); return await (async (e, t, n, a, r, i) => { var s, o, l; const check = () => assertFillShouldContinue({ shouldContinue: i }); if (check(), !Array.isArray(n) || 1 !== n.length || !Number.isInteger(n[0]) || n[0] < 0 || n[0] >= t.options.length) throw new Error("\u5168\u65f6\u5b89\u5355\u9009\u7b54\u6848\u65e0\u6548"); if (await switchQuanshianQuestion(e, t, a, i), check(), 0 !== (null == (o = null == (s = getQuanshianPractice(e)) ? void 0 : s.totalMap[t.id]) ? void 0 : o.flag)) throw new Error("\u5168\u65f6\u5b89\u8be5\u9898\u5df2\u4f5c\u7b54\uff0c\u4e0d\u56de\u586b"); const c = resolveQuanshianTargets(e, t, a); if (!c) throw new Error("\u5168\u65f6\u5b89\u5f53\u524d\u9898\u76ee\u6216\u9009\u9879\u5df2\u53d8\u5316\uff0c\u8bf7\u91cd\u65b0\u89e3\u6790"); const u = c[n[0]]; if (!(null == (l = u.querySelector("input")) ? void 0 : l.checked) || !u.classList.contains("is-checked")) { let e; try { await Promise.race([ r(u), new Promise(((t, n) => { e = setTimeout((() => n(new Error("\u5168\u65f6\u5b89\u56de\u586b\u8d85\u65f6"))), 3e3); })) ]); } finally { clearTimeout(e); } } check(), await waitUntil((() => { var r, i; check(); const s = resolveQuanshianTargets(e, t, a); if (!s) throw new Error("\u5168\u65f6\u5b89\u56de\u586b\u671f\u95f4\u9898\u76ee\u5df2\u53d8\u5316"); const o = s.filter((e => { var t; return (null == (t = e.querySelector("input")) ? void 0 : t.checked) && e.classList.contains("is-checked"); })); return 1 === o.length && o[0] === u && (null == (i = null == (r = getQuanshianPractice(e)) ? void 0 : r.totalMap[t.id]) ? void 0 : i.val) === t.values[n[0]]; }), { interval: 25, timeout: 3e3, timeoutMessage: "\u5168\u65f6\u5b89\u539f\u751f\u9009\u4e2d\u6001\u672a\u786e\u8ba4\uff0c\u672a\u63d0\u4ea4\u7b54\u6848" }); })(pageDocument(), a, r, removeHtml, (async e => { await defaultSetAnswer("xx", [ 0 ], { ...t, $options: O(e) }, n, { shouldContinue: shouldContinue }); }), shouldContinue), false; } }, { type: "ask", name: "\u5168\u65f6\u5b89\u7406\u8bba\u8003\u8bd5\u5355\u9009\u4e0e\u5224\u65ad", tips: "\u5217\u51fa\u6574\u5377\u5355\u9009\u3001\u5224\u65ad\u9898\uff0c\u9010\u9898\u641c\u9898\u56de\u586b\uff1b\u5e73\u53f0\u4f1a\u9010\u9898\u6682\u5b58\u6240\u9009\u7b54\u6848\uff0c\u811a\u672c\u4ece\u4e0d\u4ea4\u5377\uff0c\u8bf7\u81ea\u884c\u68c0\u67e5\u540e\u4ea4\u5377\u3002\u591a\u9009\u548c\u56fe\u7247\u9898\u672a\u9a8c\u3002", match: () => getExamQuestions().length > 0, types: [ "0", "3" ], init: () => getExamQuestions().length > 0, question: { html: getExamQuestions, question: "", options: "", type: "", workType: "quanshian", pageType: "quanshian" }, questionHook: e => { var t; const n = e.html; return { ...e, ...n, quanshian: n, html: getQuanshianExamCard(pageDocument(), n) ?? (null == (t = getQuanshianExam(pageDocument())) ? void 0 : t.$el), $options: O() }; }, toquestion: e => { var t, n; const a = null == (t = getAskStore().questionList[e]) ? void 0 : t.quanshian; a && (null == (n = getQuanshianExamCard(pageDocument(), a)) || n.scrollIntoView({ block: "center" })); }, ischecked: e => e.hasClass("is-checked") && !!e.find("input").prop("checked"), setAnswer: async ({answer: e, ques: t, rule: n}) => { const a = t.quanshian, r = "3" === a.type ? [ a.options.indexOf(normalizeJudgeAnswer(e) ?? "") ] : e, i = getAskStore(), s = i.runToken, shouldContinue = () => i.runToken === s && isQuanshianPracticeUrl(location.href); return await (async (e, t, n, a, r, i) => { var s; const check = () => assertFillShouldContinue({ shouldContinue: i }); if (check(), !Array.isArray(n) || 1 !== n.length || !Number.isInteger(n[0]) || n[0] < 0 || n[0] >= t.options.length) throw new Error("\u5168\u65f6\u5b89\u5355\u9009\u7b54\u6848\u65e0\u6548"); const o = resolveQuanshianExamTargets(e, t, a); if (!o) throw new Error("\u5168\u65f6\u5b89\u8003\u8bd5\u9898\u76ee\u6216\u9009\u9879\u5df2\u53d8\u5316\uff0c\u8bf7\u91cd\u65b0\u89e3\u6790"); const l = o[n[0]], c = t.values[n[0]], recordValue = () => { var n, a; return null == (a = null == (n = getQuanshianExam(e)) ? void 0 : n.mapVal[t.id]) ? void 0 : a.val; }; if (!(null == (s = l.querySelector("input")) ? void 0 : s.checked) || !l.classList.contains("is-checked") || recordValue() !== c) { let e; try { await Promise.race([ r(l), new Promise(((t, n) => { e = setTimeout((() => n(new Error("\u5168\u65f6\u5b89\u56de\u586b\u8d85\u65f6"))), 3e3); })) ]); } finally { clearTimeout(e); } } check(), await waitUntil((() => { check(); const n = resolveQuanshianExamTargets(e, t, a); if (!n) throw new Error("\u5168\u65f6\u5b89\u56de\u586b\u671f\u95f4\u9898\u76ee\u5df2\u53d8\u5316"); const r = n.filter((e => { var t; return (null == (t = e.querySelector("input")) ? void 0 : t.checked) && e.classList.contains("is-checked"); })); return 1 === r.length && r[0] === l && recordValue() === c; }), { interval: 25, timeout: 3e3, timeoutMessage: "\u5168\u65f6\u5b89\u539f\u751f\u9009\u4e2d\u6001\u672a\u786e\u8ba4\uff0c\u672a\u4ea4\u5377" }); })(pageDocument(), a, r, removeHtml, (async e => { await defaultSetAnswer("xx", [ 0 ], { ...t, $options: O(e) }, n, { shouldContinue: shouldContinue }); }), shouldContinue), false; } } ], Un = Object.freeze(Object.defineProperty({ __proto__: null, a21tb: Ht, ahjxjy: mt, antai: fn, bgzk: kn, cfy: dn, chaoxing: rt, chengjiaoyun: ct, chutou: qt, cjedu: gt, cjnep: It, cloudwis: xt, cnzx: dt, cqsdx: nn, dufe: un, gkks: bt, guokai: lt, huayi: Ut, jhjypt: hn, jijiaool: mn, jijiaox: _t, jsou: ut, learnin: Qt, learnspace: tn, ls365: At, mooc: Zt, mosoteach: Vt, mynep: Et, olearn: sn, openha: wt, ouchn: Jt, qingshu: ht, quanshian: En, sclecb: kt, umu: Cn, uooc: ft, wdjycj: ln, wencai: Ct, whut: cn, wx168: Pt, xinwei: st, xueqi: yt, ynou: $t, ytccr: vt, yunmuxueyuan: Qe, yxbyun: on, yxlearning: St, zhihuishu: it, zhijiaoyun: pt }, Symbol.toStringTag, { value: "Module" })), resolveRuleHtml = e => "function" == typeof e ? e() : e; const createQuestionData = (e, t) => { const n = O(t), a = removeHtml(n.find(e.question).html()), r = n.find(e.options).map(((e, t) => removeHtml(O(t).html()))).get(); return { question: titleClean(a ?? ""), options: r, $options: n.find(e.options), type: n.find(e.type).val(), html: n[0], workType: e.workType, pageType: e.pageType }; }, $n = []; // Native DOM fixture for end-to-end verification; production adapters follow. const privateDemoMatch = () => location.pathname === "/demo" && location.hostname === new URL(Ye).hostname; const privateDemoQuestion = {html: ".demo-question", question: ".demo-stem", options: ".demo-option span", type: ".demo-type", workType: "private-demo", pageType: "private-demo"}; $n.unshift({ type: "ask", name: "知库联调页面", match: () => privateDemoMatch() && !location.search.includes("review=1"), types: ["0", "1", "2", "3", "4"], question: privateDemoQuestion, questionHook: question => { question.$options = O(question.html).find(".demo-option"); if (["2", "4"].includes(question.type)) { question.options = []; question.$options = O(question.html).find("textarea"); } return question; }, setAnswer: ({type, answer, html}) => { if (["0", "1"].includes(type)) { html.querySelectorAll(".demo-option input").forEach((input, i) => {input.checked = answer.includes(i); input.dispatchEvent(new Event("change", {bubbles: true}));}); } else if (type === "3") { html.querySelectorAll(".demo-option input").forEach(input => {input.checked = input.value === answer; input.dispatchEvent(new Event("change", {bubbles: true}));}); } else { html.querySelectorAll("textarea").forEach((input, i) => {input.value = answer[i] || ""; input.dispatchEvent(new Event("input", {bubbles: true}));}); } return false; } }, { type: "save", name: "知库联调采集", match: () => privateDemoMatch() && location.search.includes("review=1"), question: {...privateDemoQuestion, answer: ".demo-answer"}, answerHook: question => ({...question, options: ["2", "3", "4"].includes(question.type) ? [] : question.options, answer: JSON.parse(question.html.dataset.answer)}) }); for (const eh in Un) $n.push(...Un[eh]); const isRuleMatched = e => "function" == typeof e.match ? e.match() : Boolean(e.match), parseRule = async e => { if (isPageClaimedByNewLine(document)) return; if (await waitUntil((() => void 0 !== ie[Ve + "app"])), isPageClaimedByNewLine(document)) return; const t = e.filter(isRuleMatched), n = getAppStore(), a = getAskStore(), r = { app: n, ask: a, ai: ie[Ve + "ai"] }; if (!t.length) return n.app.alert = "\u5f53\u524d\u6ca1\u6709\u4efb\u52a1", console.log("\u6ca1\u6709\u5339\u914d\u5230\u89c4\u5219", "error"), void addLog("\u6ca1\u6709\u5339\u914d\u5230\u89c4\u5219", "error"); for (const i of t) { if (isPageClaimedByNewLine(document) || getAskStore() !== a) return; if (console.log(`\u5339\u914d\u5230\u89c4\u5219\uff1a${i.name}`, "success"), addLog(`\u5339\u914d\u5230\u89c4\u5219\uff1a${i.name}`, "success"), i.init) { let e = await i.init(); if ("boolean" == typeof e && false === e) continue; } if (isPageClaimedByNewLine(document) || getAskStore() !== a) return; n.alert = `\u5f53\u524d\u4efb\u52a1:${i.name}`, "hook" === i.type && i.main(r), "ask" === i.type && await askParser(i, r), "save" === i.type && await saveParser(i, r); } }, saveParser = async (e, t) => { const n = t.app, a = t.ask; a.rule = e, e.tips && (a.tips = e.tips); const readSaveList = async () => (e.collect ? await e.collect() : questionSaveParser(e.question, e.answerHook || null)).filter((e => { return !(null == e || (t = e.answer, !flattenAnswerTexts(t).some((e => "" !== e.trim()))) || "8" == e.type); var t; })).map((e => (e.question = titleClean(e.question), e))).filter(e => Answer.workspaceLibrary.normalize(e)); let r = await readSaveList(); for (let i = 0; !r.length && i < 2; i++) await sleep(1200 + 800 * i), r = await readSaveList(); cacheUnresolvedReview(e, r); a.saveQuestionData = r, r.forEach((e => { cacheWorkspacePlatformAnswers([e]); })), await async function({questionList: e, pageType: t, paper: n, onPaperError: a, beforeSync: r, syncQuestionList: i}) { if (n) try { await n(e); } catch (o) { null == a || a(o); } const s = { questionList: e, pageType: t }; return null == r || r(s), e.length && await i(s), s; }({ questionList: r, pageType: e.question.pageType, paper: e.paper && "function" == typeof e.paper ? e.paper : void 0, onPaperError: () => addLog("\u6574\u5377\u7f13\u5b58\u5f02\u5e38", "error"), beforeSync: () => n.setPage("library", "saved"), syncQuestionList: e => Answer.syncQuestionList(e) }), n.app.alert = r.length ? `题库收录完成,本次共缓存${r.length}道题目` : "本页未识别到标准答案;已选答案保存在自选答案", msg(r.length ? `题库收录完成,本次共缓存${r.length}道题目` : "本页未识别到标准答案;已选答案保存在自选答案", r.length ? "success" : "info"), e.next && e.next(); }, askParser = async (e, t) => { const n = t.app, a = t.ask; a.rule = e, e.minDelay && (a.minDelay = e.minDelay, a.delay < a.minDelay && (a.delay = a.minDelay)), e.optionDelay && (a.optionMinDelay = e.optionDelay, a.optionDelay < a.optionMinDelay && (a.optionDelay = a.optionMinDelay), e.optionDelay = a.optionDelay), e.tips && (a.tips = e.tips), n.app.showFloat = !n.app.hideFloat && !!n.app.defaultShowFloat, n.setPage("ask"), a.clearQuestion(); let parsed; if (e.collect) parsed = (await e.collect()).filter((e => null != e)); else { var r, i; parsed = (r = questionParser(e.question, e.questionHook || null), i = titleClean, r.filter((e => null != e)).map((e => (e.question = i(e.question), e)))); } // Same timing model as aiask: parse once after init readiness, no extra sleep retries. parsed.map((e => normalizeQuestionForAsk(e))).filter(Boolean).forEach((e => { a.addQuestion(e); })), a.autoAnswer && a.toggleStart(); }, questionSaveParser = (e, t) => { const n = resolveRuleHtml(e.html); return O(n).map(((n, a) => { let r = { ...createQuestionData(e, a), $answer: O(a).find(e.answer), answer: [] }; try { t && (r = t(r, n)); } catch (s) { console.log("\u6536\u5f55hook\u62a5\u9519", s); } if (null == r || null == r) return null; const i = normalizeQuestionForSave(r); return { question: i.question, options: i.options, answer: i.answer, type: i.type, hash: questionHash(i.type, i.question, i.options) }; })).get(); }, questionParser = (e, t) => { const n = resolveRuleHtml(e.html), a = O(n).map(((n, a) => ((e, t, n, a = () => {}) => { if (!t) return e; try { return t(e, n) || null; } catch (r) { return a(r), null; } })(createQuestionData(e, a), t, n, (e => { console.log("\u7b54\u9898hook\u62a5\u9519", e); })))); return a.get(); }, vuePageChange = async () => { if (isPageClaimedByNewLine(document)) return; if (ie.vuePageChangeLock) return; ie.vuePageChangeLock = true; try { const e = getAppStore(), t = getAskStore(); t.questionInx = 0, e.setPage("ask"), t.clearQuestion(), t.scanning = true, t.scanText = "正在读取网页题目…"; try { await parseRule($n); } finally { t.scanning = false; t.scanText = ""; } } finally { ie.vuePageChangeLock = false; } }, observeVuePageChange = (e, t, n = {}) => { if (ie.mainClass = t(), !e) return; const a = new MutationObserver((async () => { const e = t(); ie.mainClass !== e && (ie.mainClass = e, n.beforeChange && await n.beforeChange(e), await vuePageChange()); })); a.observe(e, { subtree: true, attributes: true, childList: true }); }, installGlobalAutoScan = () => { if (ie.__zkGlobalScan) return; ie.__zkGlobalScan = true; let last = location.href; const kick = () => { clearTimeout(ie.__zkScanTimer); ie.__zkScanTimer = setTimeout((async () => { if (isPageClaimedByNewLine(document)) return; const now = location.href; if (now === last) return; last = now; try { await vuePageChange(); } catch {} }), 600); }; const wrap = kind => { const orig = history[kind]; if ("function" != typeof orig || orig.__zkWrapped) return; const wrapped = function() { const ret = orig.apply(this, arguments); return kick(), ret; }; wrapped.__zkWrapped = true, history[kind] = wrapped; }; wrap("pushState"), wrap("replaceState"); window.addEventListener("popstate", kick); window.addEventListener("hashchange", kick); setInterval((() => { location.href !== last && kick(); }), 1500); }, formatUpdateDate = e => new Date(e).toISOString().replace("T", " ").substring(0, 19), normalizeVersionParts = e => { var t; return ((null == (t = e.trim().replace(/^v/i, "").match(/\d+(?:\.\d+)*/)) ? void 0 : t[0]) || "0").split(".").map((e => Number(e) || 0)); }, compareVersionOrder = (e, t) => { const n = normalizeVersionParts(e), a = normalizeVersionParts(t), r = Math.max(n.length, a.length); for (let i = 0; i < r; i++) { const e = n[i] || 0, t = a[i] || 0; if (e > t) return 1; if (e < t) return -1; } return 0; }, compareVersions = (e, t) => compareVersionOrder(e, t) < 0, Hn = 864e5, formatDate = e => formatUpdateDate(e), Pn = [], updateFn = async (automatic = true) => { if (!automatic) window.dispatchEvent(new CustomEvent('zk-check-update')); }, ttfDownloadJson = async e => new Promise((t => { re({ method: "GET", url: e, onload: function(e) { try { const n = e.responseText, a = JSON.parse(n); t(a); } catch (n) { msg("\u5b57\u4f53\u6587\u4ef6\u4e0b\u8f7d\u5931\u8d25", "error"), t(null); } }, onerror: function(e) { msg("\u5b57\u4f53\u6587\u4ef6\u4e0b\u8f7d\u5931\u8d25", "error"), t(null); } }); })), randomIndex = (e, t) => Math.floor(t() * e), defaultResolveOptions = e => { const resolveTarget = e => { (null == e ? void 0 : e.$options) && "function" == typeof e.$options && (e.$options = e.$options()); }; return resolveTarget(e), Array.isArray(null == e ? void 0 : e.options) && e.options.forEach((e => { e && "object" == typeof e && resolveTarget(e); })), e; }; function getPreviewResumeAction(e, t) { const n = Math.max(t - 1, 0); return e >= n ? { shouldFinish: true, nextIndex: n } : { shouldFinish: false, nextIndex: e + 1 }; } function createNextRunToken(e) { return e.runToken = (e.runToken || 0) + 1, e.runToken; } function isRunTokenCurrent(e, t) { return e.runToken === t; } const Ln = new Set([ "2", "4", "5", "6", "7", "9", "14" ]), answerAsTextArray = e => (e => Array.isArray(e) ? e : "string" == typeof e && e.trim() ? [ e.trim() ] : [])(e).map((e => "string" == typeof e ? e.trim() : String(e ?? "").trim())).filter(Boolean), getLength = e => { if ("function" == typeof e) try { return getLength(e()); } catch { return 0; } if (Array.isArray(e)) return e.length; if (e && "object" == typeof e && "length" in e) { const t = e.length; return "number" == typeof t ? t : 0; } return 0; }, getBlankCount$1 = e => { var t; const n = getLength(e.$options); if (n > 0) return n; if (Array.isArray(e.options) && e.options.length > 0) return e.options.every((e => "string" == typeof e)) ? e.options.length : 0; const a = countBlankPlaceholders(e.question); if (a > 0) return a; const r = e.html; return r && "object" == typeof r && "function" == typeof r.querySelectorAll ? r.querySelectorAll("textarea").length : "string" == typeof r && (null == (t = r.match(/ { const n = answerAsTextArray(e.answer); if (0 === n.length || !Array.isArray(t.options)) return; if (!t.options.every((e => "string" == typeof e))) return; if ("0" === t.type && isJudgeChoiceOptions(t.options)) { if (1 !== n.length) return; const e = resolveJudgeAnswer(n[0], t.options); if (!e) return; return { kind: "choice", indexes: [ t.options.findIndex((t => normalizeJudgeAnswer(t) === e)) ] }; } const a = ((e, t) => { const n = e.map(normalizeComparableText); if (0 === n.length || n.some((e => "" === e))) return []; const a = t.map(normalizeComparableText), findIndexFor = e => { const t = a.findIndex((t => t === e)); if (-1 !== t) return t; const n = a.reduce(((t, n, a) => (n.includes(e) && t.push(a), t)), []); return 1 === n.length ? n[0] : -1; }, r = n.map(((t, n) => { const a = findIndexFor(t); if (-1 !== a) return a; const r = e[n].replace(/^\s*[A-Z]\s*[.\u3001\uff0e)\uff09:\uff1a]\s*/, ""); if (r === e[n]) return -1; const i = normalizeComparableText(r); return i ? findIndexFor(i) : -1; })); return r.includes(-1) ? [] : r; })(n, t.options); return 0 !== a.length ? { kind: "choice", indexes: a } : void 0; }, matchJudgeCandidate = (e, t) => { const n = answerAsTextArray(e.answer); if (1 !== n.length) return; const a = resolveJudgeAnswer(n[0], t.judgeOptions ?? t.options); return a ? { kind: "judge", value: a } : void 0; }, matchBlankCandidate = (e, t) => { const n = answerAsTextArray(e.answer); if (0 === n.length) return; const a = getBlankCount$1(t); return a > 0 && n.length !== a ? void 0 : { kind: "blank", values: n }; }, findPlan = (e, t) => { if (e.valid) return "0" === t.type || "1" === t.type ? matchChoiceCandidate(e, t) : "3" === t.type ? matchJudgeCandidate(e, t) : Ln.has(t.type) || "8" === t.type && getBlankCount$1(t) > 0 ? matchBlankCandidate(e, t) : "11" === t.type ? (e => { if (e.answer && "object" == typeof e.answer && !Array.isArray(e.answer)) return { kind: "link", value: e.answer }; })(e) : "15" === t.type ? ((e, t) => { if (!Array.isArray(e.answer) || !Array.isArray(t.options)) return; if (0 === t.options.length || e.answer.length !== t.options.length) return; const n = []; let a = 0; for (let r = 0; r < t.options.length; r++) { const i = t.options[r]; if (!i || "object" != typeof i || !("options" in i)) { n.push({ kind: "unsupported", reason: "\u5b50\u9898\u65e0\u6cd5\u5339\u914d" }); continue; } const s = { ...e, answer: e.answer[r] }, o = "3" === i.type ? matchJudgeCandidate(s, i) : Ln.has(i.type) ? matchBlankCandidate(s, i) : matchChoiceCandidate(s, i); o ? (a++, n.push(o)) : n.push({ kind: "unsupported", reason: "\u5b50\u9898\u65e0\u7b54\u6848" }); } return a > 0 ? { kind: "reading", subPlans: n } : void 0; })(e, t) : void 0; }, matchAnswerCandidates = (e, t) => { for (const n of e) { const a = findPlan(n, t); if (a) return { haveAnswer: true, source: n, fillPlan: a, displayAnswers: e }; } return ((e, t = "\u7b54\u6848\u6570\u91cf\u6216\u5185\u5bb9\u65e0\u6cd5\u5339\u914d\u5f53\u524d\u9898\u76ee") => ({ haveAnswer: false, displayAnswers: e, reason: t }))(e); }, isBlankAnswer = e => null == e || ("string" == typeof e ? "" === e.trim() : !!Array.isArray(e) && (0 === e.length || e.every(isBlankAnswer))), normalizeAnswerArray = e => e.map((e => Array.isArray(e) ? normalizeAnswerArray(e) : "string" == typeof e ? e.trim() : e)).filter((e => !isBlankAnswer(e))), normalizeAnswerCandidates = e => e.map(((e, t) => { const n = findNonAnswerText(null == e ? void 0 : e.answer), a = n ? [] : (e => { if (null == e) return []; if ("string" == typeof e) { return e.trim() || []; } return Array.isArray(e) ? e.map((e => Array.isArray(e) ? normalizeAnswerArray(e) : "string" == typeof e ? e.trim() : e)).filter((e => Array.isArray(e) || !isBlankAnswer(e))) : e; })(null == e ? void 0 : e.answer); return { source: (null == e ? void 0 : e.form) || (null == e ? void 0 : e.source) || "\u672a\u77e5\u6765\u6e90", answer: a, valid: !n && !isBlankAnswer(a), duration: null == e ? void 0 : e.duration, msg: n ? (null == e ? void 0 : e.msg) || `\u63a5\u53e3\u8fd4\u56de\u975e\u7b54\u6848\u6587\u6848\uff1a${n}` : null == e ? void 0 : e.msg, needLogin: null == e ? void 0 : e.needLogin, raw: (null == e ? void 0 : e.raw) ?? e, priority: "number" == typeof (null == e ? void 0 : e.priority) ? e.priority : t }; })), createManualAiDisplayMessage = (e, t, n) => e && t.trim() ? t : n, appendOptionLines = e => e.map(((e, t) => `${String.fromCharCode(65 + t)}\u3001${String(e)}`)).join("\n"), noAnswerMatch = e => ({ res: [ e ], haveAnswer: false }), createFallbackResult = (e, t, n = 0, a = "") => { const r = { action: "mark-no-answer", answer: [] }, i = { form: e, answer: [], msg: t, duration: n, aiStatus: r.action, rawText: a }; return { res: i, matchResult: noAnswerMatch(i), action: r }; }, getBlankCount = e => { var t, n; const a = e.$options, r = "function" == typeof a ? a() : a; return Array.isArray(r) ? r.length : (null == (t = e.html) ? void 0 : t.querySelectorAll) ? e.html.querySelectorAll("textarea").length : "string" == typeof e.html && (null == (n = e.html.match(/ e.html ? "string" == typeof e.html ? e.html : "string" == typeof e.html.outerHTML ? e.html.outerHTML : "string" == typeof e.html.innerHTML ? e.html.innerHTML : "" : "", stripImageTags = e => e.replace(/<\s*img\b[^>]*>/gi, ""), describeImageFailures = e => e.map((e => e.src ? `${e.src}\uff08${e.reason}\uff09` : e.reason)).join("\uff1b"), isTextAnswerUnknownQuestion = e => { var t, n; if ("8" !== e.type) return false; const a = getQuestionHtmlText(e); return /]*>/gi, jn = /\bsrc\s*=\s*["']([^"']+)["']/i, runAskAiFallback = async ({route: e, text: t, type: n, question: a, config: r, adoptionStrategy: i, usePureMatcher: s = false, runScene: o = runAiScene, matchAnswer: l, resolveImages: c = resolveQuestionImages}) => { const u = (null == r ? void 0 : r.name) || "AI", p = ((e, t) => hasQuestionImages(t, e))(t, a); if (p && !((e, t) => !!(null == e ? void 0 : e.enabled) && true === (e.capabilities || Oe)[t])(r, "image")) return createFallbackResult(u, "\u5f53\u524d AI \u914d\u7f6e\u4e0d\u652f\u6301\u56fe\u7247\u9898\u76ee\uff0c\u8bf7\u5728 AI \u8bbe\u7f6e\u4e2d\u9009\u62e9\u56fe\u7247\u9898\u6a21\u578b"); if (hasUnsupportedMedia(stripImageTags(t)) || hasUnsupportedMedia(stripImageTags(getQuestionHtmlText(a)))) return createFallbackResult(u, getAiErrorMessage(createAiError("AI_IMAGE_UNSUPPORTED"))); let d = [], m = []; if (p) { try { const e = await c({ ...a, question: `${a.question}\n${t}` }); d = (null == e ? void 0 : e.parts) || [], m = (null == e ? void 0 : e.failures) || []; } catch (k) { m = [ { src: "", reason: (null == k ? void 0 : k.message) || "\u56fe\u7247\u83b7\u53d6\u5931\u8d25" } ]; } if (!d.length && !(e => stripImageTags(e).replace(/<[^>]*>/g, " ").replace(/\[[^\]]*\]/g, " ").replace(/\s+/g, "").length > 0)(t)) return createFallbackResult(u, `\u9898\u76ee\u56fe\u7247\u83b7\u53d6\u5931\u8d25\uff1a${describeImageFailures(m)}`); } const h = m.length ? `\u90e8\u5206\u9898\u76ee\u56fe\u7247\u672a\u53d6\u5230\uff1a${describeImageFailures(m)}` : "", f = p ? ((e, t) => { const n = t.parts || [], a = t.failures || []; if (!n.length && !a.length) return { text: e.replace(Mn, ""), parts: [], markers: new Map }; const r = new Set(a.map((e => resolveImageSrc(e.src)))), i = new Map; n.forEach((e => { e.url && i.set(resolveImageSrc(e.url), e); })); const s = [], o = new Map, l = e.replace(Mn, (e => { var t; const n = resolveImageSrc((null == (t = e.match(jn)) ? void 0 : t[1]) || ""); if (!n) return ""; if (o.has(n)) return `[\u56fe${o.get(n)}]`; const a = i.get(n); return a ? (i.delete(n), s.push(a), o.set(n, s.length), `[\u56fe${s.length}]`) : r.has(n) ? "[\u56fe\u7247\u83b7\u53d6\u5931\u8d25]" : ""; })), c = n.filter((e => !s.includes(e))); if (!c.length) return { text: l, parts: s, markers: o }; const u = c.map(((e, t) => `[\u56fe${s.length + t + 1}]`)).join(""); return s.push(...c), { text: `${l}\n\uff08\u53e6\u9644\u672a\u5b9a\u4f4d\u7684\u9898\u76ee\u56fe\u7247\uff1a${u}\uff09`, parts: s, markers: o }; })(t, { parts: d, failures: m }) : { text: t, parts: d, markers: new Map }, g = p ? ((e, t) => { if (Array.isArray(e) && e.every((e => "string" == typeof e))) return e.map((e => e.replace(Mn, (e => { var n; const a = resolveImageSrc((null == (n = e.match(jn)) ? void 0 : n[1]) || ""), r = t.get(a); return r ? `[\u56fe${r}]` : ""; })))); })(a.options, f.markers) : void 0, v = ((e, t) => "8" === e && isTextAnswerUnknownQuestion(t) ? "4" : e)(n, a), y = await o("ask", r, ((e, t) => t.length ? [ { type: "text", text: e }, ...t ] : e)(f.text, f.parts), { questionType: v, stream: false, route: e }); if (!y.success) { const e = [ y.displayMessage || "AI \u672a\u8fd4\u56de\u53ef\u7528\u7b54\u6848", h ].filter(Boolean).join("\uff1b"); return createFallbackResult(u, e, y.duration, y.text); } const b = ((e, t, n) => t && Array.isArray(n) && Array.isArray(e.answer) ? { ...e, answer: e.answer.map((e => { if ("string" != typeof e) return e; const a = t.indexOf(e); return a >= 0 ? n[a] : e; })) } : e)(parseAiAnswer(y.text, { type: v, options: g || a.options || [], blankCount: getBlankCount(a) }), g, a.options), w = ((e, t) => "preview" === e ? t.valid ? { action: "preview", answer: t.answer } : { action: "mark-no-answer", answer: [] } : "conservative" === e ? t.valid ? { action: "fill", answer: t.answer } : { action: "mark-no-answer", answer: [] } : t.answer.length > 0 ? { action: "fill", answer: t.answer } : { action: "mark-no-answer", answer: [] })(i, b), x = { form: u, answer: b.answer, msg: [ b.error ? getAiErrorMessage(b.error) : "", h ].filter(Boolean).join("\uff1b"), duration: y.duration, aiStatus: w.action, rawText: y.text }; if ("fill" !== w.action) return { res: x, matchResult: noAnswerMatch(x), action: w }; try { return { res: x, matchResult: s || !l ? matchAnswerCandidates(normalizeAnswerCandidates([ x ]), { ...a, type: v }) : await l([ x ], a, !1), action: w }; } catch (k) { return createFallbackResult(u, "AI \u7b54\u6848\u586b\u5145\u5931\u8d25\uff0c\u8bf7\u624b\u52a8\u6838\u5bf9\u540e\u91cd\u8bd5", y.duration, y.text); } }, getErrorMessage = (e, t) => e instanceof Error && e.message ? `${t}\uff1a${e.message}` : "string" == typeof e && e ? `${t}\uff1a${e}` : t, runQuestionPipelineFromSources = async ({task: e, question: t, runToken: n, isCurrentRun: a, askAiEnabled: r, randomAnswerEnabled: i, sources: s}) => { if ("confirm-ai-preview" === e.kind) return ((e, t) => { var n, a; const r = { form: "AI \u9884\u89c8", answer: (null == (n = e.preview) ? void 0 : n.answer) || [], duration: 0, msg: "", aiStatus: "confirmed", rawText: (null == (a = e.preview) ? void 0 : a.rawText) || "" }, i = normalizeAnswerCandidates([ r ]), s = matchAnswerCandidates(i, t); return s.haveAnswer && s.source && s.fillPlan ? { status: "answered", displayAnswers: i, adoptedSource: s.source, fillPlan: s.fillPlan } : { status: "failed", displayAnswers: i, failureReason: "AI \u5efa\u8bae\u65e0\u6cd5\u5339\u914d\u5f53\u524d\u9898\u76ee" }; })(e, t); const o = "manual-ai" === e.kind, l = "random" === e.kind; return (async ({question: e, runToken: t, isCurrentRun: n, askAiEnabled: a, randomAnswerEnabled: r, getCacheAnswer: i, getRemoteAnswers: s, getAiAnswer: o, getRandomFillPlan: l}) => { var c, u, p, d; let m = "", h = "", f = []; try { const a = await i(e); if (!n(t)) return { status: "stale", displayAnswers: [] }; f = normalizeAnswerCandidates([ a ]); const r = matchAnswerCandidates(f, e); if (r.haveAnswer && r.source && r.fillPlan) return { status: "answered", displayAnswers: f, adoptedSource: r.source, fillPlan: r.fillPlan }; } catch (w) { if (!n(t)) return { status: "stale", displayAnswers: [] }; m = getErrorMessage(w, "\u7f13\u5b58\u7b54\u6848\u8bfb\u53d6\u5931\u8d25"); } let g = []; try { const a = await s(e); if (!n(t)) return { status: "stale", displayAnswers: [] }; g = normalizeAnswerCandidates(a); const r = matchAnswerCandidates(g, e); if (r.haveAnswer && r.source && r.fillPlan) return { status: "answered", displayAnswers: [ ...f, ...g ], adoptedSource: r.source, fillPlan: r.fillPlan }; h = (null == (c = g.find((e => e.msg))) ? void 0 : c.msg) || h; } catch (w) { if (!n(t)) return { status: "stale", displayAnswers: [] }; m = getErrorMessage(w, "\u8fdc\u7aef\u9898\u5e93\u8bf7\u6c42\u5931\u8d25"); } let v = [ ...f, ...g ]; if (a && o) try { const a = await o(e); if (!n(t)) return { status: "stale", displayAnswers: [] }; if ((e => { var t; return !!e && "object" == typeof e && "preview" === (null == (t = e.action) ? void 0 : t.action); })(a)) return { status: "preview", displayAnswers: v, preview: { answer: (null == (u = a.res) ? void 0 : u.answer) || [], rawText: (null == (p = a.res) ? void 0 : p.rawText) || "", reason: "\u7b49\u5f85\u7528\u6237\u786e\u8ba4 AI \u5efa\u8bae" } }; const r = normalizeAnswerCandidates([ (y = a, y && "object" == typeof y && "res" in y ? y.res : y) ]); v = [ ...v, ...r ]; const i = matchAnswerCandidates(r, e); if (i.haveAnswer && i.source && i.fillPlan) return { status: "answered", displayAnswers: v, adoptedSource: i.source, fillPlan: i.fillPlan }; h = (null == (d = r.find((e => e.msg))) ? void 0 : d.msg) || h; } catch (w) { if (!n(t)) return { status: "stale", displayAnswers: [] }; m = getErrorMessage(w, "AI \u7b54\u6848\u83b7\u53d6\u5931\u8d25"); } var y, b; if (r && l) { const t = l(e); if (t) return { status: "no-answer", displayAnswers: v, adoptedSource: { source: "\u968f\u673a\u7b54\u9898", answer: [], valid: true, priority: 999 }, fillPlan: t, failureReason: "\u968f\u673a\u7b54\u9898\uff0c\u4e0d\u4ee3\u8868\u6b63\u786e\u7b54\u6848" }; } return { status: m && !h ? "failed" : "no-answer", displayAnswers: v, failureReason: (b = h || m || "\u672a\u627e\u5230\u53ef\u5339\u914d\u7b54\u6848", cleanQuestionText(b).replace(/\s*\n\s*/g, " ").trim()) }; })({ question: t, runToken: n, isCurrentRun: a, askAiEnabled: !!o || r, randomAnswerEnabled: !!l || i, getCacheAnswer: o || l ? async () => ({ form: "\u672c\u5730\u7f13\u5b58", answer: "", duration: 0, msg: "\u624b\u52a8\u4efb\u52a1\u8df3\u8fc7\u7f13\u5b58" }) : s.getCacheAnswer, getRemoteAnswers: o || l ? async () => [] : s.getRemoteAnswers, getAiAnswer: l ? void 0 : s.getAiAnswer, getRandomFillPlan: s.getRandomFillPlan }); }; let On = 0; const createQuestionTaskId = (e, t, n, a) => `${e}:${t}:${n}:${a}`, createQuestionTask = ({kind: e, index: t, runToken: n, preview: a, now: r = Date.now, nextSeq: i = () => ++On}) => { const s = i(); return { id: createQuestionTaskId(e, t, n, s), kind: e, index: t, runToken: n, createdAt: r(), preview: a }; }, phaseToLegacyStatus = e => "done" === e ? 1 : "no-answer" === e || "failed" === e ? 2 : 0, finishWithPhase = (e, t, n, a) => (e.setPhase(t.index, n, t, a), { phase: n, reason: a }), runQuestionTask = async (e, t) => { var n; if (!t.isCurrentRun(e.runToken)) return { phase: "cancelled", reason: "\u7b54\u9898\u5df2\u53d6\u6d88" }; const a = t.getQuestion(e.index); if (!a) return finishWithPhase(t, e, "failed", "\u9898\u76ee\u4e0d\u5b58\u5728"); try { if (t.setPhase(e.index, "preparing", e), t.setLoadingText("\u52a0\u8f7d\u4e2d...."), !t.isCurrentRun(e.runToken)) return { phase: "cancelled", reason: "\u7b54\u9898\u5df2\u53d6\u6d88" }; t.setPhase(e.index, "searching", e); const n = await t.runPipeline(e, a); if ("stale" === n.status || !t.isCurrentRun(e.runToken)) return { phase: "cancelled", reason: "\u7b54\u9898\u5df2\u53d6\u6d88" }; const r = (e => e.displayAnswers.map((e => e.raw || e)))(n); if ("preview" === n.status && n.preview) return t.publishQuestion(e.index, { answer: r, phase: "preview", status: 0, taskId: e.id }), t.publishPreview(e.index, n.preview), t.setPhase(e.index, "preview", e), t.stopAutoRun(), { phase: "preview", reason: n.preview.reason }; const i = n.adoptedSource && n.fillPlan ? createLegacyMatchResult({ haveAnswer: !0, source: n.adoptedSource, fillPlan: n.fillPlan, displayAnswers: n.displayAnswers }) : createLegacyMatchResult({ haveAnswer: !1, displayAnswers: n.displayAnswers }); if (n.fillPlan && t.setPhase(e.index, "matched", e), t.publishQuestion(e.index, { answer: r, form: i.form, error: n.failureReason || "", phase: "published", status: 0, taskId: e.id }), t.setPhase(e.index, "published", e), await t.waitForRender(), !t.isCurrentRun(e.runToken)) return { phase: "cancelled", reason: "\u7b54\u9898\u5df2\u53d6\u6d88" }; if (t.setPhase(e.index, "rendering", e), n.fillPlan) { t.setPhase(e.index, "filling", e); const r = await t.fillAnswer(n.fillPlan, a); if (!t.isCurrentRun(e.runToken)) return { phase: "cancelled", reason: "\u7b54\u9898\u5df2\u53d6\u6d88" }; if (!r.success) return finishWithPhase(t, e, "failed", r.reason || "\u7b54\u6848\u586b\u5145\u5931\u8d25"); } return "answered" === n.status ? finishWithPhase(t, e, "done") : "failed" === n.status ? finishWithPhase(t, e, "failed", n.failureReason || "\u7b54\u6848\u83b7\u53d6\u5931\u8d25") : finishWithPhase(t, e, "no-answer", n.failureReason || "\u672a\u627e\u5230\u53ef\u5339\u914d\u7b54\u6848"); } catch (r) { if (!t.isCurrentRun(e.runToken)) return { phase: "cancelled", reason: "\u7b54\u9898\u5df2\u53d6\u6d88" }; null == (n = t.log) || n.call(t, "\u5355\u9898\u7b54\u9898\u5f02\u5e38", r); const a = r instanceof Error ? r.message : "string" == typeof r ? r : ""; return finishWithPhase(t, e, "failed", a ? `\u7b54\u9898\u5931\u8d25\uff1a${a}` : "\u7b54\u9898\u5931\u8d25\uff0c\u8bf7\u91cd\u8bd5"); } }, zn = [ "ask", "library", "settings" ], Dn = { page: "ask", subPage: "" }, Fn = { home: { page: "ask", subPage: "" }, overview: { page: "ask", subPage: "" }, ai: { page: "ask", subPage: "" }, Base: { page: "settings", subPage: "" }, question: { page: "library", subPage: "" }, preview: { page: "library", subPage: "" }, questionTool: { page: "library", subPage: "" }, log: { page: "settings", subPage: "about" }, user: { page: "settings", subPage: "account" } }, Nn = { settings: "", logs: "about", account: "account" }, Rn = { display: "general", hotkey: "general", system: "general", data: "general", logs: "about" }, Bn = new Set([ "manage", "preview", "tool" ]); function resolveNextPage(e, t) { return void 0 !== Fn[e] ? Fn[e] : "system" === e ? { page: "settings", subPage: Nn[t ?? ""] ?? "" } : "settings" === e && void 0 !== Rn[t ?? ""] ? { page: "settings", subPage: Rn[t ?? ""] } : "library" === e && Bn.has(t ?? "") ? { page: "library", subPage: "" } : zn.includes(e) ? { page: e, subPage: t ?? "" } : Dn; } function normalizeDialogWidth(e) { const t = "number" == typeof e ? e : Number(e); return Number.isFinite(t) ? Math.max(480, Math.min(1200, Math.round(t))) : 760; } const Gn = { debug: true, searchApi: [], defaultShowFloat: true, showFloat: true, showBoard: true, checkUpdate: false, hideFloat: false, alert: "点击展开主面板", alertBubble: true, examCacheEnabled: true, iframe: false, key: "", gpt: [], gptIndex: 0, askGpt: false, hotkey: "Ctrl+Shift+K", hotkeyEnabled: true, theme: "auto", page: "ask", subPage: "", dialogWidth: 760 }; const Kn = function() { const e = Cache.get("app") || {}, t = { ...Gn }; for (const [n, a] of Object.entries(e)) "gpt" !== n && "alert" !== n && void 0 !== a && (t[n] = a); if (e.gpt) { const n = new Map; e.gpt.forEach((e => { n.set(e.name, e.key); })), t.gpt = Gn.gpt.map((e => ({ ...e, key: n.get(e.name) || "" }))); } return t.alert = Gn.alert, t.gptIndex >= t.gpt.length && (t.gptIndex = 0), t.dialogWidth = normalizeDialogWidth(t.dialogWidth), t; }(); function getApp() { return Cache.get("app") || Gn; } !function(e) { const t = { ...Cache.get("app"), ...e }; Cache.set("app", t); }(Kn); const Vn = { display: [ { type: "switch", label: "\u9ed8\u8ba4\u663e\u793a\u60ac\u6d6e", name: "defaultShowFloat", value: Kn.defaultShowFloat, desc: "\u6253\u5f00\u9875\u9762\u65f6\u662f\u5426\u663e\u793a\u60ac\u6d6e\u7a97", options: [] }, { type: "switch", label: "\u5f3a\u5236\u9690\u85cf", name: "hideFloat", value: Kn.hideFloat, desc: "\u4ec5\u70ed\u952e\u6216\u70b9\u51fb\u53f3\u4e0b\u89d2\u56fe\u7247\u624d\u663e\u793a\u60ac\u6d6e\u7a97", options: [] }, { type: "switch", label: "\u6c14\u6ce1\u63d0\u793a", name: "alertBubble", value: Kn.alertBubble, desc: "\u53f3\u4e0b\u89d2\u6c14\u6ce1\u63d0\u793a\u662f\u5426\u5f00\u542f", options: [] } ], system: [ { type: "switch", label: "\u68c0\u6d4b\u66f4\u65b0", name: "checkUpdate", value: Kn.checkUpdate, desc: "\u6253\u5f00\u9875\u9762\u65f6\u662f\u5426\u68c0\u6d4b\u66f4\u65b0", options: [] }, { type: "switch", label: "iframe\u4f18\u5316(\u6d4b\u8bd5)", name: "iframe", value: Kn.iframe, desc: "\u9488\u5bf9\u6df1\u5ea6\u5d4c\u5957\u7f51\u9875\u7684\u4f18\u5316\uff0c\u9002\u5408\u5355\u4efb\u52a1\u9875\u4f7f\u7528\uff0c\u591a\u4efb\u52a1\u53ef\u80fd\u4f1a\u5bfc\u81f4\u5f39\u7a97\u8fc7\u591a\u3002\n \u6ce8\u610f\uff1a\u8be5\u529f\u80fd\u4e3a\u6d4b\u8bd5\u529f\u80fd\uff0c\u53ef\u80fd\u5b58\u5728\u672a\u77e5\u95ee\u9898\uff0c\u8bf7\u8c28\u614e\u4f7f\u7528", options: [] } ], ai: [], hotkey: [ { type: "switch", label: "\u542f\u7528\u5feb\u6377\u952e", name: "hotkeyEnabled", value: Kn.hotkeyEnabled, desc: "\u662f\u5426\u542f\u7528\u5feb\u6377\u952e\u663e\u9690\u60ac\u6d6e\u7a97", options: [] }, { type: "hotkey", label: "\u5feb\u6377\u952e\u8bbe\u7f6e", name: "hotkey", value: Kn.hotkey, desc: "\u70b9\u51fb\u8f93\u5165\u6846\u540e\u6309\u4e0b\u60f3\u8981\u8bbe\u7f6e\u7684\u5feb\u6377\u952e\u7ec4\u5408\uff08\u652f\u6301Ctrl\u3001Shift\u3001Alt\u7ec4\u5408\u952e\uff09", options: [] } ] }, Wn = pinia.defineStore("app", { state: () => { const e = resolveNextPage(Kn.page, Kn.subPage); return { app: Kn, script: We.script, page: e.page, subPage: e.subPage, ConfigInput: Vn, searchOpen: false, logs: [ { time: (new Date).toLocaleString(), type: "success", content: "\u521d\u59cb\u5316\u65e5\u5fd7\u6210\u529f" } ] }; }, actions: { setConfig(e) { const t = { ...this.app, ...e }; "dialogWidth" in e && (t.dialogWidth = normalizeDialogWidth(e.dialogWidth)), this.app = t, Cache.set("app", this.app); }, setPage(e, t) { const n = resolveNextPage(e, t); this.page = n.page, this.subPage = n.subPage, this.app = { ...this.app, page: n.page, subPage: n.subPage }, Cache.set("app", this.app); }, openSearch() { this.searchOpen = true; }, closeSearch() { this.searchOpen = false; }, setDialogWidth(e) { const t = normalizeDialogWidth(e); this.app.dialogWidth = t, Cache.set("app", this.app); }, addLog(e) { this.logs.length > 100 && this.logs.shift(), this.logs.push(e); } } }); function getCachedNoticeResult(e, t = Date.now(), n = {}) { return function(e, t = Date.now(), n = {}) { if (n.force) return true; if (!e.noticeLoaded) return true; const a = n.cacheTtl ?? 3e5; return t - e.noticeFetchedAt >= a; }(e, t, n) ? null : { success: true, notice: e.notice }; } const Qn = Cache.get("user", {}), Jn = pinia.defineStore("user", { state: () => ({ user: Qn.user || null, notice: "", noticeLoaded: false, noticeFetchedAt: 0, apiKey: Qn.api_key || "", isLoggedIn: !!Qn.user, loginTime: Qn.login_time || 0 }), getters: { username: e => { var t; return (null == (t = e.user) ? void 0 : t.username) || "\u672a\u767b\u5f55"; }, nickname: e => { var t; return (null == (t = e.user) ? void 0 : t.nickname) || "\u6e38\u5ba2"; }, avatar: () => "", score: e => { var t; return (null == (t = e.user) ? void 0 : t.score) || 0; } }, actions: { async loginByPassword(e, t) { try { const n = apiUrl("sessions"), [a] = await requestApi(n, "POST", { username: e, password: t, login_type: "password" }), r = JSON.parse(a.responseText); return 200 === r.code ? (this.user = r.data.user, this.apiKey = r.data.api_key, this.isLoggedIn = !0, this.loginTime = Date.now(), this.saveToCache(), await this.fetchUserInfo(), r.data, { success: !0, message: "\u767b\u5f55\u6210\u529f" }) : { success: !1, message: r.message || "\u767b\u5f55\u5931\u8d25" }; } catch (n) { return { success: false, message: n.message || "\u767b\u5f55\u5931\u8d25\uff0c\u8bf7\u68c0\u67e5\u7f51\u7edc\u8fde\u63a5" }; } }, async loginByApiKey(e) { try { const t = apiUrl("sessions"), [n] = await requestApi(t, "POST", { api_key: e, login_type: "apikey" }), a = JSON.parse(n.responseText); return 200 === a.code ? (this.user = a.data.user, this.apiKey = a.data.api_key, this.isLoggedIn = !0, this.loginTime = Date.now(), this.saveToCache(), await this.fetchUserInfo(), a.data, { success: !0, message: "\u767b\u5f55\u6210\u529f" }) : { success: !1, message: a.message || "API Key \u767b\u5f55\u5931\u8d25" }; } catch (t) { return { success: false, message: t.message || "API Key \u767b\u5f55\u5931\u8d25\uff0c\u8bf7\u68c0\u67e5\u7f51\u7edc\u8fde\u63a5" }; } }, async fetchUserInfo() { if (this.isLoggedIn) try { const e = apiUrl("profile"), [t] = await requestApi(e, "GET", void 0, { Authorization: `Bearer ${this.apiKey}` }), n = JSON.parse(t.responseText); 200 === n.code && (this.user = n.data.user, this.saveToCache(), n.data); } catch (e) {} }, async logout() { try { if (this.apiKey) { const e = apiUrl("session"); await requestApi(e, "POST", void 0, { Authorization: `Bearer ${this.apiKey}` }); } } catch (e) {} finally { this.user = null, this.apiKey = "", this.isLoggedIn = false, this.loginTime = 0, Cache.remove("user"); } }, async refreshApiKey() { try { const e = apiUrl("credentials/renew"), [t] = await requestApi(e, "POST", void 0, { Authorization: `Bearer ${this.apiKey}` }), n = JSON.parse(t.responseText); return 200 === n.code ? (this.apiKey = n.data.api_key, this.saveToCache(), n.data.api_key, { success: !0, message: "API Key \u5237\u65b0\u6210\u529f", api_key: n.data.api_key }) : { success: !1, message: n.message || "API Key \u5237\u65b0\u5931\u8d25" }; } catch (e) { return { success: false, message: e.message || "API Key \u5237\u65b0\u5931\u8d25" }; } }, async fuzzySearchQuestion(e) { var t; try { const t = apiUrl("catalog/search"), n = { question: e.question, type: e.type ?? 8, options: e.options ?? [] }, [a] = await requestApi(t, "POST", n), r = JSON.parse(a.responseText), i = 401 === r.code || 401 === a.status; return 200 === r.code ? { success: !0, message: r.message || "success", data: r.data || [] } : i ? { success: !1, message: r.message || "\u767b\u5f55\u540e\u624d\u53ef\u4ee5\u4f7f\u7528\u5b98\u65b9\u9898\u5e93\uff0c\u8bf7\u5148\u767b\u5f55", data: [], needLogin: !0 } : { success: !1, message: r.message || "\u5b98\u65b9\u9898\u5e93\u641c\u7d22\u5931\u8d25", data: [] }; } catch (n) { const e = 401 === (null == n ? void 0 : n.status) || 401 === (null == (t = null == n ? void 0 : n.response) ? void 0 : t.status); return { success: false, message: e ? "\u767b\u5f55\u540e\u624d\u53ef\u4ee5\u4f7f\u7528\u5b98\u65b9\u9898\u5e93\uff0c\u8bf7\u5148\u767b\u5f55" : (null == n ? void 0 : n.message) || "\u5b98\u65b9\u9898\u5e93\u641c\u7d22\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5", data: [], needLogin: e }; } }, async fetchNotice(e = {}) { var t; const n = getCachedNoticeResult(this, Date.now(), e); if (n) return n; try { const [e] = await requestApi(apiUrl("bulletin"), "GET"), n = JSON.parse(e.responseText), a = (null == (t = null == n ? void 0 : n.data) ? void 0 : t.notice) ?? (null == n ? void 0 : n.data); return 200 === n.code ? (this.notice = a || "", { success: !0, notice: this.notice, message: n.message }) : { success: !1, message: n.message || "\u516c\u544a\u83b7\u53d6\u5931\u8d25" }; } catch (a) { return this.notice ? { success: true, notice: this.notice } : { success: false, message: (null == a ? void 0 : a.message) || "\u516c\u544a\u83b7\u53d6\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5" }; } finally { this.noticeLoaded = true, this.noticeFetchedAt = Date.now(); } }, saveToCache() { const e = { user: this.user || void 0, api_key: this.apiKey || void 0, login_time: this.loginTime || void 0 }; Cache.set("user", e); }, loadFromCache() { const e = Cache.get("user", {}); e.user && (this.user = e.user, this.apiKey = e.api_key || "", this.loginTime = e.login_time || 0, this.isLoggedIn = true); } } }), Zn = { get: e => Cache.get(e), set: (e, t) => Cache.set(e, t) }; const Yn = pinia.defineStore("ai", { state: () => ({ aiMsg: "", aiLoading: false, settings: loadAiSettingsFrom(Zn, He, getApp), catalog: { seq: 0, fetchedAt: 0, channels: He }, catalogLoading: false, connectionTestingId: "", connectionMessage: "", connectionTestingIds: {}, connectionMessages: {}, connectionRequestTokens: {}, latestConnectionRequestToken: "" }), actions: { selectTargetById(e) { if (this.settings.instances.find((t => t.channelId === e))) return resolveAiTarget({ ...this.settings, defaultChannelId: e, sceneOverrides: { enabled: false } }, this.catalog, "search", "text"); }, currentAiMd() { return createSafeMarkdownHtml(this.aiMsg); }, resetAi() { this.aiMsg = "", this.aiLoading = false; }, saveSettings() { this.settings = ((e, t) => { const n = normalizeAiSettingsV2(t) ?? t; return e.set(Fe, n), n; })(Zn, this.settings); }, async loadCatalog() { this.catalog = {seq: 2, fetchedAt: Date.now(), channels: He}; }, selectTarget(e, t = "text") { return resolveAiTarget(this.settings, this.catalog, e, t); }, routeContextFor(e) { return undefined; // AI uses the selected provider directly; no private-key proxy. }, catalogForDisplay() { return this.catalog.channels.filter((e => "active" === e.status)).sort(((e, t) => e.recommended !== t.recommended ? e.recommended ? -1 : 1 : e.order - t.order)); }, updateCredential(e, t) { const n = this.settings.instances.find((t => t.channelId === e)); n ? n.credential = { ...t, updatedAt: Date.now() } : this.settings.instances.push({ channelId: e, credential: { ...t, updatedAt: Date.now() }, enabled: true }), this.saveSettings(); }, addChannel(e) { this.settings.instances.some((t => t.channelId === e)) || (this.settings.instances.push({ channelId: e, enabled: true }), this.settings.defaultChannelId || (this.settings.defaultChannelId = e), this.saveSettings()); }, removeInstance(e) { var t; this.settings.instances = this.settings.instances.filter((t => t.channelId !== e)), this.settings.customChannels = this.settings.customChannels.filter((t => t.id !== e)), this.settings.defaultChannelId === e && (this.settings.defaultChannelId = (null == (t = this.settings.instances[0]) ? void 0 : t.channelId) || ""), this.settings.defaultVisionChannelId === e && (this.settings.defaultVisionChannelId = ""), delete this.connectionTestingIds[e], delete this.connectionMessages[e], delete this.connectionRequestTokens[e], this.connectionTestingId === e && (this.connectionTestingId = ""), this.saveSettings(); }, async testConfig(e) { var t; const n = null == (t = this.selectTargetById(e)) ? void 0 : t.config, a = `${Date.now()}-${Math.random()}`; this.connectionTestingId = e, this.connectionMessage = "", this.connectionTestingIds[e] = true, this.connectionMessages[e] = "", this.connectionRequestTokens[e] = a, this.latestConnectionRequestToken = a; const updateConnectionMessage = t => { const n = t.success ? `\u8fde\u63a5\u6210\u529f\uff0c\u8017\u65f6 ${t.duration}ms` : t.displayMessage || "\u8fde\u63a5\u5931\u8d25\uff0c\u8bf7\u68c0\u67e5\u914d\u7f6e"; this.connectionRequestTokens[e] === a && (this.connectionMessages[e] = n), this.latestConnectionRequestToken === a && (this.connectionMessage = n); }; try { const e = await (async e => runAiScene("search", e, "\u8bf7\u53ea\u56de\u590d\u201c\u8fde\u63a5\u6210\u529f\u201d", { stream: !1 }))(n); return updateConnectionMessage(e), e; } catch (r) { const e = { success: false, text: "", duration: 0, displayMessage: "\u8fde\u63a5\u6d4b\u8bd5\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5" }; return updateConnectionMessage(e), e; } finally { this.connectionRequestTokens[e] === a && (delete this.connectionTestingIds[e], delete this.connectionRequestTokens[e]), this.latestConnectionRequestToken === a && (this.connectionTestingId = "", this.latestConnectionRequestToken = ""); } } } }), waitForAnswerRender = async () => { await vue.nextTick(), await function(e = {}, t = 120) { var n; const a = e.requestAnimationFrame ?? (null == (n = globalThis.requestAnimationFrame) ? void 0 : n.bind(globalThis)), r = e.setTimeout ?? globalThis.setTimeout.bind(globalThis), i = e.clearTimeout ?? globalThis.clearTimeout.bind(globalThis); return new Promise((e => { let n, s = false; const finish = () => { s || (s = true, e()); }; n = r(finish, t), a && a((() => { void 0 !== n && i(n), finish(); })); })); }(); }, Xn = pinia.defineStore("ask", { state: () => ({ questionList: [], questionInx: 0, inx: 0, Interval: 0, start: false, skipFinish: Cache.get("skipFinish", false), autoNext: Cache.get("autoNext", false), autoAnswer: Cache.get("autoAnswer", true), freeFirst: true, randomAnswer: Cache.get("randomAnswer", false), lock: false, runToken: 0, formMap: {}, type: "cx", loading: false, scanning: false, scanText: "", loadingText: "\u52a0\u8f7d\u4e2d....", loadingRunToken: 0, aiLoadingIndex: -1, aiPreview: null, aiFailureMap: {}, restartPending: false, tips: "\u672c\u811a\u672c\u4ec5\u4f9b\u5b66\u4e60\u7814\u7a76\uff0c\u8bf7\u52ff\u7528\u4e8e\u975e\u6cd5\u7528\u9014", delay: Cache.get("delay", 1e3), minDelay: Cache.get("minDelay", 0), optionDelay: Cache.get("optionDelay", 0), optionMinDelay: 0, saveQuestionData: [] }), actions: { addQuestion(e) { this.questionList.push({ ...e, answer: [], status: 0, phase: "idle", error: "", taskId: "", aiMsg: "" }); }, clearQuestion() { this.questionList = []; }, getQuestion() { return this.questionList[this.questionInx]; }, nextQuestion() { if (this.questionInx === this.questionList.length - 1) return clearInterval(this.Interval), void (this.start = false); this.questionInx++; }, prevQuestion() { 0 !== this.questionInx && this.questionInx--; }, toQuestion(e) { this.questionInx = e; let t = this.questionList[e]; this.rule.toquestion && this.rule.toquestion(e); try { if (t.html.scrollIntoView({ block: "center" }), ie.self !== ie.top) { let n = document.querySelector(".el-dialog"); if (n) { n.style.transform = "none"; let a = t.html.getBoundingClientRect(); n.style.top = a.top - 700 + "px", 0 === e && (n.style.top = "0px"), e === this.questionList.length - 1 && document.documentElement.scrollHeight > 2e3 && (n.style.top = a.top - 900 + "px"); } } t.html.style.boxShadow = "0 0 10px rgba(0, 0, 0, 0.15)", setTimeout((() => { t.html.style.boxShadow = ""; }), 500); } catch (n) {} }, setQuestionStatus(e, t) { this.questionList[e] && null != this.questionList[e].status && (this.questionList[e].status = t); }, async toggleStart() { const e = getAppStore(); let t = 0; try { const n = await async function(e, t) { const n = function(e) { return e.lock ? "noop" : e.start ? "stop" : "start"; }(e); if ("noop" === n) return n; if ("stop" === n) return e.start = !1, n; e.start = !0, e.lock = !0; try { return await t(), e.start ? n : "stop"; } finally { e.start = !1, e.lock = !1; } }(this, (async () => { var n; const a = createNextRunToken(this); t = a; for (let t = this.questionInx; t < this.questionList.length && this.start; t++) { if (this.skipFinish && 1 === this.questionList[t].status) continue; this.questionInx = t; let r = this.questionList[t]; if ("8" !== r.type || isTextAnswerUnknownQuestion(r)) { if ((null == (n = this.rule) ? void 0 : n.answerDelay) && (await sleep(this.rule.answerDelay), !isRunTokenCurrent(this, a))) { this.start = !1; break; } if (await this.reAnswer(t, a), !isRunTokenCurrent(this, a)) { this.start = !1; break; } if (!this.start) break; if (e.app.alert = `\u5f53\u524d\u8fdb\u5ea6:${t + 1}/${this.questionList.length}`, await sleep(this.delay + 1e3 * Math.random()), !isRunTokenCurrent(this, a)) { this.start = !1; break; } this.rule.toquestion && this.rule.toquestion(this.questionInx + 1), this.autoNext && this.rule.next && this.rule.next(); } else this.setQuestionStatus(t, 2); } })); if (this.restartPending && "noop" !== n) return this.restartPending = !1, this.loadingRunToken === t && (this.loading = !1), void (await this.toggleStart()); if ("start" !== n) return; this.finishRun(e); } catch (n) { e.app.alert = "\u7b54\u9898\u4e2d\u65ad\uff0c\u8bf7\u91cd\u8bd5"; } finally { if (this.restartPending && !this.lock) return this.restartPending = false, this.loadingRunToken === t && (this.loading = false), void (await this.toggleStart()); this.lock || this.start || this.loadingRunToken !== t || (this.loading = false); } }, finishRun(e = getAppStore()) { this.formMap = {}, this.questionList.forEach((t => { var n; if (null == (n = t.form) ? void 0 : n.form) { let e = t.form.form; e && (this.formMap[e] = this.formMap[e] ? this.formMap[e] + 1 : 1); } else this.formMap["\u65e0\u7b54\u6848"] = this.formMap["\u65e0\u7b54\u6848"] ? this.formMap["\u65e0\u7b54\u6848"] + 1 : 1; })); this.start = false; const parts = Object.entries(this.formMap || {}).filter(([, count]) => Number(count) > 0).map(([name, count]) => `${count} 题来自${name}`); const tip = parts.length ? `已完成自动答题:${parts.join(',')}` : '已完成自动答题,请手动检查提交'; e.app.alert = tip; try { msg(tip, "success"); } catch (_) {} }, setQuestionPhase(e, t, n, a = "") { const r = this.questionList[e]; r && (r.phase = t, r.status = phaseToLegacyStatus(t), r.error = a, n && (r.taskId = n.id), a ? this.aiFailureMap[e] = a : "failed" !== t && "no-answer" !== t && delete this.aiFailureMap[e]); }, publishQuestionTaskResult(e, t) { const n = this.questionList[e]; n && (t.answer && (n.answer = t.answer), "form" in t && (n.form = t.form), t.phase && (n.phase = t.phase), void 0 !== t.status && (n.status = t.status), t.taskId && (n.taskId = t.taskId), n.error = t.error || "", t.error && (this.aiFailureMap[e] = t.error)); }, publishQuestionTaskPreview(e, t) { this.aiPreview = t ? { index: e, answer: t.answer, rawText: t.rawText, reason: t.reason } : null; }, createQuestionRunnerDeps(e) { return getAppStore(), { getQuestion: e => this.questionList[e], isCurrentRun: e => isRunTokenCurrent(this, e), runPipeline: (t, n) => runQuestionPipelineFromSources({ task: t, question: n, runToken: e, isCurrentRun: e => isRunTokenCurrent(this, e), askAiEnabled: Wn().app.zkAiEnabled !== false && (Yn().settings.enabledForAsk || !!Jn().user?.sources?.sharedAi), randomAnswerEnabled: this.randomAnswer, sources: { getCacheAnswer: e => Answer.getCacheAnswer(e), getRemoteAnswers: e => (this.loadingText = "\u6b63\u5728\u4ece\u63a5\u53e3\u4e2d\u83b7\u53d6\u7b54\u6848", Answer.getAnswersFree(e)), getAiAnswer: async e => { this.loadingText = "\u6b63\u5728\u4eceAI\u4e2d\u83b7\u53d6\u7b54\u6848"; const t = this.buildAIQuestionText(e); return this.fetchAIAnswer(t, n); }, getRandomFillPlan: e => ((e, t = Math.random) => { switch (e.type) { case "0": case "1": if (!Array.isArray(e.options) || 0 === e.options.length) return; return { kind: "choice", indexes: [ randomIndex(e.options.length, t) ] }; case "3": return { kind: "judge", value: t() > .5 ? "\u6b63\u786e" : "\u9519\u8bef" }; case "15": if (!Array.isArray(e.options) || 0 === e.options.length) return; const n = e.options.map((e => Array.isArray(null == e ? void 0 : e.options) && 0 !== e.options.length ? { kind: "choice", indexes: [ randomIndex(e.options.length, t) ] } : { kind: "unsupported", reason: "\u5b50\u9898\u9009\u9879\u4e3a\u7a7a\uff0c\u65e0\u6cd5\u968f\u673a\u7b54\u9898" })); return n.some((e => "choice" === e.kind)) ? { kind: "reading", subPlans: n } : void 0; default: return; } })(e) } }), fillAnswer: (t, n) => (async (e, t, n, a) => { try { return assertFillShouldContinue(a), (a.resolveOptions || defaultResolveOptions)(t), assertFillShouldContinue(a), await applyFillPlan(e, t, n, a.applyLegacyAnswer, { shouldContinue: a.shouldContinue }); } catch (r) { if (r instanceof Error && "\u7b54\u9898\u5df2\u53d6\u6d88" === r.message) return { success: false, reason: "\u7b54\u9898\u5df2\u53d6\u6d88" }; throw r; } })(t, n, this.rule, { applyLegacyAnswer: applyAnswerResult, shouldContinue: () => isRunTokenCurrent(this, e) }), publishQuestion: (e, t) => this.publishQuestionTaskResult(e, t), publishPreview: (e, t) => this.publishQuestionTaskPreview(e, t), setPhase: (e, t, n, a) => this.setQuestionPhase(e, t, n, a), setLoadingText: e => { this.loadingText = e; }, stopAutoRun: () => { this.start = false; }, waitForRender: waitForAnswerRender, log: log$1 }; }, async reAnswer(e, t) { var n; const a = t ?? createNextRunToken(this), r = createQuestionTask({ kind: void 0 === t ? "retry" : "auto", index: e, runToken: a }), i = this.questionList[e]; if (i) { delete this.aiFailureMap[e], (null == (n = this.aiPreview) ? void 0 : n.index) === e && (this.aiPreview = null), this.loading = true, this.loadingRunToken = a; try { await runQuestionTask(r, this.createQuestionRunnerDeps(a)); } finally { this.loadingRunToken === a && (this.loading = false); } } }, buildAIQuestionText: e => (e => { var t; let n = `[${typeConvert(e.type, false)}]${e.question}\n`; if ("15" === e.type && Array.isArray(e.options)) return e.options.forEach(((e, t) => { e && "object" == typeof e && (n += `\n\u5b50\u9898${t + 1}[${typeConvert(e.type, false)}]${e.question || ""}\n`, Array.isArray(e.options) && e.options.length > 0 ? n += `${appendOptionLines(e.options)}\n` : "3" === e.type && (n += "\u8bf7\u56de\u7b54\uff1a\u6b63\u786e \u6216 \u9519\u8bef\n")); })), n; if (Array.isArray(e.options)) { const t = e.options.filter((e => "object" != typeof e)); t.length > 0 && (n += `${appendOptionLines(t)}\n`); } return "24" === e.type && (e.match.forEach((e => { n += `\u7b2c\u4e00\u5217${e}\n`; })), null == (t = e.selects[0]) || t.forEach((e => { n += `\u7b2c\u4e8c\u5217${e.text}\n`; }))), n; })(e), async fetchAIAnswer(e, t) { const n = Yn(), a = hasQuestionImages(t, e) ? "image" : "text", r = n.selectTarget("ask", a), i = await runAskAiFallback({ text: e, type: t.type, question: t, config: null == r ? void 0 : r.config, route: r ? n.routeContextFor(r) : void 0, adoptionStrategy: n.settings.adoptionStrategy, usePureMatcher: true }); return i; }, async confirmAiPreview() { if (!this.aiPreview) return; const e = this.aiPreview; if (!this.questionList[e.index]) return void (this.aiPreview = null); const t = createNextRunToken(this), n = createQuestionTask({ kind: "confirm-ai-preview", index: e.index, runToken: t, preview: { answer: e.answer, rawText: e.rawText, reason: e.reason } }); this.loading = true, this.loadingRunToken = t, this.aiPreview = null; try { await runQuestionTask(n, this.createQuestionRunnerDeps(t)); } finally { this.loadingRunToken === t && (this.loading = false); } const a = getPreviewResumeAction(e.index, this.questionList.length); this.questionInx = a.nextIndex, a.shouldFinish ? this.finishRun() : this.toggleStart(); }, skipAiPreview() { if (!this.aiPreview) return; const e = this.aiPreview, t = this.questionList[e.index]; t && (t.phase = "no-answer", t.status = phaseToLegacyStatus("no-answer"), t.error = "\u7528\u6237\u8df3\u8fc7 AI \u5efa\u8bae", this.aiFailureMap[e.index] = "\u7528\u6237\u8df3\u8fc7 AI \u5efa\u8bae"), this.aiPreview = null; const n = getPreviewResumeAction(e.index, this.questionList.length); this.questionInx = n.nextIndex, n.shouldFinish ? this.finishRun() : this.toggleStart(); }, async aiAnswer(e) { var t, n; const a = createNextRunToken(this), r = createQuestionTask({ kind: "manual-ai", index: e, runToken: a }), i = this.questionList[e]; if (i) { this.loadingText = "AI\u601d\u8003\u4e2d.....", this.loading = true, this.loadingRunToken = a, this.aiLoadingIndex = e, i.aiMsg = ""; try { const s = await runQuestionTask(r, this.createQuestionRunnerDeps(a)); if ("preview" === s.phase && (null == (t = this.aiPreview) ? void 0 : t.index) === e) return void (i.aiMsg = this.aiPreview.rawText || s.reason || ""); if (s.reason) i.aiMsg = createManualAiDisplayMessage(!1, "", s.reason); else if (null == (n = i.answer) ? void 0 : n.length) { const e = i.answer[i.answer.length - 1], t = (null == e ? void 0 : e.rawText) || (Array.isArray(null == e ? void 0 : e.answer) ? e.answer.join("\u3001") : ""); i.aiMsg = createManualAiDisplayMessage("done" === s.phase, t, "AI \u672a\u91c7\u7eb3\u8be5\u7b54\u6848"); } } catch { const t = "AI\u54cd\u5e94\u5f02\u5e38\uff0c\u8bf7\u5148\u5728 AI \u8bbe\u7f6e\u4e2d\u586b\u5199 API Key\u3001\u6a21\u578b\u548c Base URL"; i.aiMsg = t, this.aiFailureMap[e] = t, this.setQuestionPhase(e, "failed", r, t); } finally { this.loadingRunToken === a && (this.loading = false), this.aiLoadingIndex = -1; } } }, pause() { this.start = false, createNextRunToken(this); }, restart() { const e = { questionInx: 0, start: false }; this.questionInx = e.questionInx, this.start = e.start, this.aiPreview = null, createNextRunToken(this), this.lock ? this.restartPending = true : this.toggleStart(); } }, getters: { current() { return this.questionList[this.questionInx]; }, currentAiMd() { return createSafeMarkdownHtml(this.questionList[this.questionInx].aiMsg); }, tipsMd() { const e = this.rule; if (!e) return '\u8be5\u9875\u9762\u6682\u65e0\u89c4\u5219'; const t = []; return t.push(`${e.name}${e.tips || "\u6709\u95ee\u9898\u53ef\u4ee5\u53cd\u9988\u7ed9\u4f5c\u8005"}`), t.join("
    "); }, typesMd() { const e = this.rule; if (!e || !e.types) return '\u8be5\u9875\u9762\u6682\u65e0\u89c4\u5219'; const t = e.types, n = []; for (const a in t) { const e = t[a]; n.push(`${typeConvert(e, false)} \u2705`); } return n.push('\u4e0d\u652f\u6301\u7684\u9898\u578b\u53ef\u4ee5\u53cd\u9988\u7ed9\u4f5c\u8005\u517c\u5bb9'), n.join("
    "); } } }); // One local repository for reusable answers and private imports; publication is separate. function createWorkspaceLibrary({cache, hash, cleanHtml, nonAnswer = () => false, now = () => Math.floor(Date.now() / 1000)}) { const prefix = 'ques1_', initialized = 'zkLibraryCategoriesV2'; const originLabels = {platform: '平台标准答案', cloud: '知库题库', yizhi: '一之题库', personal: '自选答案', imported: '本地导入', ai: 'AI 答案'}; const sourceLabels = {local: '本地缓存', query: '查询缓存', personal: '自选答案', imported: '本地导入'}; const inferOrigin = source => /平台标准|平台采集/.test(source || '') ? 'platform' : /知库官方|知库题库/.test(source || '') ? 'cloud' : /一之/.test(source || '') ? 'yizhi' : /AI/i.test(source || '') ? 'ai' : /个人导入|本地导入|个人文件导入/.test(source || '') ? 'imported' : /自选|手动/.test(source || '') ? 'personal' : null; const sourceGroup = row => { const origin = originLabels[row.activeOrigin] ? row.activeOrigin : inferOrigin(row.source) || row.origins?.find(x => originLabels[x]); return origin === 'platform' ? 'local' : ['cloud', 'yizhi', 'ai'].includes(origin) ? 'query' : origin === 'imported' ? 'imported' : 'personal'; }; const verification = row => sourceGroup(row) === 'local' ? '平台公布答案' : '未核验'; const describe = row => `本地缓存库 · ${sourceLabels[sourceGroup(row)]}${sourceGroup(row) === 'query' ? ' · ' + row.source : ''} · 免费,${verification(row)}`; const visible = value => String(cleanHtml(String(value ?? ''))).replace(/]*\bsrc\s*=\s*["']([^"']+)["'][^>]*>/gi, '$1').replace(/<[^>]*>/g, '').replace(/[\s\u200b-\u200d\ufeff]/g, ''); const meaningful = value => { if (typeof value === 'string') return !!visible(value) && !/^(?:null|undefined|\[\]|\{\}|暂无答案|暂无答案信息|未找到答案|无答案)$/i.test(visible(value)) && !nonAnswer(value); if (typeof value === 'number') return Number.isFinite(value); if (typeof value === 'boolean') return true; if (Array.isArray(value)) return value.length > 0 && value.every(meaningful); return !!value && typeof value === 'object' && Object.keys(value).length > 0 && Object.values(value).every(meaningful); }; const cleanTree = value => { if (typeof value === 'string') return cleanHtml(value).trim(); if (Array.isArray(value)) return value.map(cleanTree); if (value && typeof value === 'object') return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cleanTree(item)])); return value; }; const cleanOptions = options => options.map(item => item && !Array.isArray(item) && typeof item === 'object' && 'question' in item ? {type: String(item.type ?? '0'), question: cleanHtml(String(item.question ?? '')), options: cleanOptions(Array.isArray(item.options) ? item.options : [])} : cleanTree(item)); function normalize(raw, origin) { if (!raw || typeof raw !== 'object' || typeof raw.question !== 'string' || !visible(raw.question) || !Array.isArray(raw.options)) return null; const type = String(raw.type ?? '8'), question = cleanHtml(raw.question).trim(); const options = cleanOptions(raw.options); let answer = cleanTree(raw.answer); if (!meaningful(answer)) return null; if (type === '0' || type === '1') { if (options.length < 2 || !options.every(meaningful)) return null; answer = (Array.isArray(answer) ? answer : [answer]).map(item => { if (typeof item !== 'string' || options.includes(item)) return item; return /^[A-Z]$/.test(item) ? options[item.charCodeAt(0) - 65] : item; }); if (!answer.every(item => typeof item === 'string' && options.includes(item)) || type === '0' && answer.length !== 1) return null; } if (type === '3') { const parts = (Array.isArray(answer) ? answer.flat(Infinity) : [answer]).flatMap(item => { if (typeof item === 'boolean') return [item ? '正确' : '错误']; if (typeof item !== 'string') return [item]; const text = item.trim(); if ((text.startsWith('[') && text.endsWith(']')) || (text.startsWith('{') && text.endsWith('}'))) { try { const parsed = JSON.parse(text); return Array.isArray(parsed) || (parsed && typeof parsed === 'object') ? [parsed].flat(Infinity) : [text]; } catch {} } return [item]; }); answer = parts.map(item => typeof item === 'boolean' ? (item ? '正确' : '错误') : item); } if (!meaningful(answer)) return null; const knownOrigins = Array.isArray(raw.origins) ? raw.origins.filter(x => originLabels[x]) : []; const category = originLabels[origin] ? origin : originLabels[raw.activeOrigin] ? raw.activeOrigin : inferOrigin(raw.source) || knownOrigins[0] || 'personal'; const origins = [...new Set([...knownOrigins, category])]; const stamp = Number.isFinite(raw.createTime) ? raw.createTime : now(); return {type, question, options, answer, analysis: typeof raw.analysis === 'string' ? cleanHtml(raw.analysis).trim() : '', source: inferOrigin(raw.source) === category ? raw.source : originLabels[category], origins, activeOrigin: category, createTime: stamp, updatedTime: Number.isFinite(raw.updatedTime) ? raw.updatedTime : stamp}; } const keyFor = row => prefix + hash(String(row.type ?? '8'), cleanHtml(String(row.question ?? '')).trim(), cleanOptions(Array.isArray(row.options) ? row.options : [])); const answerSignature = answer => JSON.stringify(answer); function save(raw, origin, oldKey) { let row = normalize(raw, origin); if (!row) return false; const key = keyFor(row), existingRaw = cache.get(key), existing = normalize(existingRaw); const versions = [...(Array.isArray(raw.alternatives) ? raw.alternatives : []), ...(Array.isArray(existingRaw?.alternatives) ? existingRaw.alternatives : [])]; if (existing) { row.origins = [...new Set([...existing.origins, ...row.origins])]; row.createTime = Math.min(existing.createTime, row.createTime); const differs = answerSignature(existing.answer) !== answerSignature(row.answer); if (existing.activeOrigin === 'platform' && row.activeOrigin !== 'platform') { if (differs) versions.push({answer: row.answer, source: row.source, activeOrigin: row.activeOrigin, updatedTime: row.updatedTime}); row = {...existing, origins: row.origins, createTime: row.createTime}; } else if (differs) versions.push({answer: existing.answer, source: existing.source, activeOrigin: existing.activeOrigin, updatedTime: existing.updatedTime}); } const signatures = new Set([answerSignature(row.answer)]); row.alternatives = versions.filter(item => { if (!item) return false; const candidate = normalize({...row, answer: item.answer}); if (!candidate) return false; item.answer = candidate.answer; const signature = answerSignature(item.answer); if (signatures.has(signature)) return false; signatures.add(signature); return true; }); cache.set(key, row); if (typeof oldKey === 'string' && oldKey.startsWith(prefix) && oldKey !== key) cache.remove(oldKey); return true; } function list() { const entries = new Map(); for (const raw of cache.matchGet(prefix) || []) { const row = normalize(raw); if (!row) continue; const key = keyFor(row); const candidate = {...row, key: raw.key, alternatives: (Array.isArray(raw.alternatives) ? raw.alternatives : []).filter(item => item && normalize({...row, answer: item.answer}))}; const existing = entries.get(key); if (!existing || row.updatedTime > existing.updatedTime) entries.set(key, candidate); } return [...entries.values()].sort((a, b) => b.updatedTime - a.updatedTime); } function initialize() { // Preserve old local answers and upload queues; migrate once without erasing backups. if (cache.get(initialized)) return; const rows = [...(cache.matchGet('examCache_') || []), ...(cache.matchGet(prefix) || [])] .filter(row => normalize(row)).sort((a, b) => (a.updatedTime || a.createTime || 0) - (b.updatedTime || b.createTime || 0)); for (const row of rows) save(row, undefined, row.key); cache.set(initialized, {initializedAt: now()}); } function get(question) { const raw = cache.get(keyFor(question)), row = normalize(raw); return row ? {...row, key: keyFor(question)} : null; } function importPrivate(rows) { const valid = new Map(); let invalid = 0; for (const raw of rows) { const row = normalize({...raw, source: '本地导入', origins: ['imported'], activeOrigin: 'imported'}, 'imported'); if (!row) { invalid++; continue; } row.alternatives = Array.isArray(raw?.alternatives) ? raw.alternatives : []; valid.set(keyFor(row), row); } for (const row of valid.values()) save(row, 'imported'); return {rows: [...valid.values()], invalid, duplicates: rows.length - invalid - valid.size}; } return {normalize, meaningful, save, list, get, initialize, keyFor, originLabels, sourceLabels, sourceGroup, verification, describe, importPrivate, hiddenCount: () => (cache.matchGet(prefix) || []).filter(row => !normalize(row)).length, remove: row => { cache.remove(row.key); cache.remove(keyFor(row)); }, clear: () => cache.matchRemove(prefix)}; } // Selected-answer reader adapted from user-supplied aiask.js; attribution in THIRD_PARTY.md. class WorkspaceManualReader { static normalizeJudgmentAnswer(e) { if (null == e || "" === String(e).trim()) return ""; const t = removeHtml(String(e)).trim(); return isTrue(t) ? "\u6b63\u786e" : isFalse(t) ? "\u9519\u8bef" : ""; } static readJudgmentFromElement(e, t, n) { const a = O(e), d = a.attr("data") || a.find(".num_option,.saveSingleSelect").attr("data"); if ("true" === String(d || "").toLowerCase()) return "\u6b63\u786e"; if ("false" === String(d || "").toLowerCase()) return "\u9519\u8bef"; const i = [ a.val(), a.attr("value"), a.find(".answer_p").text(), a.text() ]; a.closest("label").length && i.push(a.closest("label").text()), a.parent().length && i.push(a.parent().text()); const o = null == n ? -1 : n; o >= 0 && Array.isArray(t) && t[o] && i.push(t[o]); for (const e of i) { const t = this.normalizeJudgmentAnswer(e); if (t) return t; } return ""; } static isJudgmentOptionSelected(e, t) { const n = O(e); return !!n.is("input:radio,input:checkbox") && n.prop("checked") || !!(t && t.ischecked && t.ischecked(n)) || !!(n.hasClass("cur") || n.parent().hasClass("cur") || n.closest("dd,li,label").hasClass("cur")); } static readManualAnswerFromPage(e, t) { if (!e || !t) return null; try { e.$options && "function" == typeof e.$options && (e.$options = e.$options()); const n = e.type, a = e.options || [], i = t.ischecked, readInputText = e => { let t = e.val(); if (null == t || "" === String(t).trim()) { const n = e.attr("name"); if (n) try { const e = ie.UE && ie.UE.getEditor(n); e && e.ready && (t = e.getContent()); } catch (a) {} } return this.sanitizeExamAnswer(t || ""); }; switch (n) { case "0": case "1": { const o = this.detectSelectedOptionIndices(e, t); if (!o.length) return null; const s = ("1" === n ? o : [ o[0] ]).map((e => this.getOptionAnswerForCache(a[e]))).filter((e => "" !== e)); return s.length ? { answer: "1" === n ? s : [ s[0] ] } : null; } case "3": { if (e.html) { const n = O(e.html).find("input[type=radio]:checked, input[type=checkbox]:checked").first(); if (n.length) { const o = e.$options && e.$options.length ? e.$options.index(n[0]) : 0, s = this.readJudgmentFromElement(n[0], e.options, o >= 0 ? o : 0); if (s) return { answer: [ s ] }; const r = this.sanitizeExamAnswer(n.closest("label").text() || n.parent().text() || n.val() || ""); if (r && !isTrue(r) && !isFalse(r)) return { answer: [ r ] }; } } if (a.length && !isJudgmentStyleOptions(a)) { const n = this.detectSelectedOptionIndices(e, t); if (n.length) { const t = this.getOptionAnswerForCache(a[n[0]]); if (t) return { answer: [ t ] }; } } if (!e.$options || !e.$options.length) return null; let n = ""; return e.$options.each((function(a) { WorkspaceManualReader.isJudgmentOptionSelected(this, t) && (n = WorkspaceManualReader.readJudgmentFromElement(this, e.options, a) || n); })), n ? { answer: [ n ] } : null; } case "2": case "9": case "4": case "5": case "6": case "7": if (!e.html) return null; { const t = O(e.html).find("textarea").map(((e, t) => readInputText(O(t)))).get(); if (t.length) return t.every(x => String(x).trim()) ? { answer: t } : null; const n = O(e.html).find('input[type="text"], input:not([type])').map(((e, t) => readInputText(O(t)))).get(); return n.length && n.every(x => String(x).trim()) ? { answer: n } : null; } case "14": if (!e.html) return null; { const t = []; return O(e.html).find('input[type="text"], input:not([type])').each(((e, n) => { const a = readInputText(O(n)); a && t.push(a); })), t.length || O(e.html).find("select").each(((e, n) => { const a = this.sanitizeExamAnswer(O(n).find("option:selected").text()); a && t.push(a); })), t.length ? { answer: t } : null; } case "15": if (!e.options || !Array.isArray(e.options)) return null; { const t = []; for (let o = 0; o < e.options.length; o++) { const s = e.options[o]; let r = s.$options; if ((!r || !r.length) && e.html) { const t = O(e.html).find(".readCompreHensionItem, .sub-subject, .subject").eq(o); r = t.length ? t.find("ul.Zy_ulTop>li, .subject-options li, li.option, li") : null; } if (r && r.length) { const e = []; r.each((function(t) { (i ? i(O(this)) : O(this).is(":checked") || O(this).find("input:checked").length || O(this).hasClass("cur") || O(this).hasClass("is-checked")) && e.push(t); })); const n = s.options || []; t.push(e.map((e => this.sanitizeExamAnswer(n[e]))).filter(Boolean)); } else t.push([]); } return t.some((e => Array.isArray(e) && e.length)) ? { answer: t } : null; } default: return null; } } catch (o) { return null; } } static getOptionAnswerForCache(e) { if ("string" != typeof e || !e) return ""; const t = this.stripExamAnswerText(e, !0); return t || (/ { "number" == typeof e && e >= 0 && !n.includes(e) && n.push(e); }, isOptionSelected = e => !!(e.is("input:checked") || e.find("input:checked").length || e.closest("label").find("input").length === 1 && e.closest("label").find("input:checked").length || e.hasClass("cur") || e.parent().hasClass("cur") || e.closest("dd").hasClass("cur") || e.find(".check_answer, .check_answer_dx").length || e.hasClass("check_answer") || e.hasClass("check_answer_dx") || e.hasClass("checked") || e.hasClass("active") || e.hasClass("cho-this") || e.hasClass("is-checked") || e.parent().hasClass("is-checked") || e.parent().hasClass("checked")); if (e.$options && e.$options.length) { if (a) e.$options.each((function(e) { a(O(this)) && pushIdx(e); })); n.length || e.$options.each((function(e) { isOptionSelected(O(this)) && pushIdx(e); })); } if (!n.length && i) { i.find(".answerBg").each((function(e) { isOptionSelected(O(this)) && pushIdx(e); })); n.length || i.find("dd > div").each((function(e) { isOptionSelected(O(this)) && pushIdx(e); })); n.length || i.find("ul:eq(0) li").each((function(e) { const t = O(this); (isOptionSelected(t) || t.find("input:checked").length) && pushIdx(e); })); } if (!n.length && i) { const t = i.find(":radio:checked, :checkbox:checked"); t.length && t.each((function() { const t = O(this), a = t.closest("li"), o = t.closest("dd"); if (a.length) { const e = a.parent().children("li").index(a); e >= 0 && pushIdx(e); } else if (o.length) { const e = o.parent().children("dd").index(o); e >= 0 && pushIdx(e); } })); } if (!n.length && i && e.$options && e.$options.length) { const t = i.find(":radio:checked, :checkbox:checked"); t.length && t.each((function() { const t = this; e.$options.each((function(e) { (this === t || O(this).find(t).length || O(this).is(t)) && pushIdx(e); })); })); } return n.sort(((e, t) => e - t)); } static stripExamAnswerText(e, t = !1) { if ("string" != typeof e || !e) return ""; let n = e.trim(); try { const e = document.createElement("textarea"); e.innerHTML = n, n = e.value; } catch (a) {} if (n = removeHtml(n), n.includes("<") && !t) { for (let e = 0; e < 3 && n.includes("<"); e++) n = n.replace(/<\/?[a-zA-Z][^>]*>/g, ""); n = removeHtml(n); } const i = n.replace(/\s+/g, " ").trim(); return i || t && / this.sanitizeExamAnswer(e))) : "string" == typeof e ? this.getOptionAnswerForCache(e) : e; } } // Reuse the platform engine's authenticated image loaders; never send page cookies to the cloud. function hasWorkspaceQuestionImages(question, text = '', dependencies = {}) { const detect = dependencies.detect || hasQuestionImages; const collect = dependencies.collect || collectRefs; if (detect(question, text)) return true; function walk(node, depth = 0) { if (!node || depth > 12) return false; if (collect(node.question).length) return true; return (node.options || []).some(option => typeof option === 'string' ? collect(option).length > 0 : option && typeof option === 'object' && walk(option, depth + 1)); } return walk(question); } async function prepareWorkspaceImages(question, dependencies = {}) { const collect = dependencies.collect || collectRefs; const extract = dependencies.extract || extractQuestionImageRefs; const load = dependencies.load || loadQuestionImagePart; const bytes = dependencies.bytes || base64Bytes; const refs = new Map(); function add(ref, location, index = null) { if (!ref?.src) return; const entry = refs.get(ref.src) || {...ref, locations: [], positions: {}}; if (!entry.el && ref.el) entry.el = ref.el; if (!entry.locations.includes(location)) entry.locations.push(location); if (index !== null) { entry.positions[location] ||= []; if (!entry.positions[location].includes(index)) entry.positions[location].push(index); } refs.set(ref.src, entry); } function addField(value, location) { if (typeof value === 'string') { [...value.matchAll(/]*>/gi)].forEach((match, index) => { for (const ref of collect(match[0])) add(ref, location, index); }); } else collect(value).forEach((ref, index) => add(ref, location, index)); } function walk(node, path = '', depth = 0) { if (!node || depth > 12) return; addField(node.question, path + '/question'); (node.options || []).forEach((option, index) => { if (typeof option === 'string') addField(option, `${path}/options/${index}`); else if (option && typeof option === 'object') walk(option, `${path}/options/${index}`, depth + 1); }); } walk(question); for (const ref of extract(question)) { const existing = refs.get(ref.src); if (existing) { if (ref.el) existing.el = ref.el; } else add(ref, '/supplementary'); } if (refs.size > 12) throw new Error('单题最多支持 12 张图片,请减少图片后再试;未调用公共 AI'); const entries = [...refs.values()]; const result = new Array(entries.length); let total = 0; // Limit concurrent downloads so a paper with several image choices stays responsive. for (let start = 0; start < entries.length; start += 2) { const settled = await Promise.allSettled(entries.slice(start, start + 2).map(ref => load(ref))); for (let i = 0; i < settled.length; i++) { const outcome = settled[i], ref = entries[start + i]; if (outcome.status !== 'fulfilled') throw new Error(`题目图片读取失败(${ref.locations.join('、')}):${outcome.reason?.message || '无法读取'};未调用公共 AI`); const part = outcome.value; const mimeType = String(part.mimeType || '').toLowerCase().replace('image/jpg', 'image/jpeg'); if (!['image/png', 'image/jpeg', 'image/webp', 'image/gif'].includes(mimeType)) throw new Error('图片须为 PNG、JPEG、WebP 或 GIF;未调用公共 AI'); const size = bytes(part.data); total += size; if (!size || size > 2 * 1024 * 1024 || total > 3 * 1024 * 1024) throw new Error('题目图片过大:单张最多 2MB、单题合计最多 3MB;请缩小图片后再试'); result[start + i] = {id: `image-${start + i + 1}`, locations: ref.locations, positions: ref.positions, mimeType, data: part.data}; } } return result; } // Source order is explicit. Unverified local answers never enter platform capture. function installWorkspaceWorkflow({task, account, models, app, repository}) { if (task._workspaceWorkflow) return task._workspaceWorkflow; const labels = {official: '知库题库', yizhi: '一之题库', ai: 'AI(知库公共服务)'}; const scrubChargeHint = text => String(text || '') .replace(/[;;,,]?\s*未扣积分/g, '') .replace(/[;;,,]?\s*积分已退回(?:,请重新查询)?/g, '') .replace(/[;;,,]?\s*未调用公共 AI/g, '') .replace(/返还积分/g, '') .replace(/^[;;,,\s]+|[;;,,\s]+$/g, '') .trim(); const requestId = () => globalThis.crypto?.randomUUID?.() || `${Date.now()}-${Math.random().toString(36).slice(2)}`; async function query(provider, question) { question._zkRequests ||= {}; // Keep the ID on the task until a response arrives, allowing transport retry without double charging. const id = question._zkRequests[provider] ||= requestId(); const started = Date.now(); const payload = {...toWorkspaceEntry(question), solutions: [], requestId: id}; if (provider === 'ai' && hasWorkspaceQuestionImages(question)) { if (!account.user?.sources?.sharedAiVision) throw new Error('后台公共 AI 尚未启用图片输入,请管理员配置视觉模型并开启图片题支持'); task.loadingText = '正在读取题干与选项图片…'; payload.images = await prepareWorkspaceImages(question); if (!payload.images.length) throw new Error('未能读取题目图片,请等待页面图片加载完成后重试'); if (new Blob([JSON.stringify(payload)]).size > 5.5 * 1024 * 1024) throw new Error('题目与图片总数据超过 5.5MB,请缩小图片后再试'); task.loadingText = '公共 AI 正在识别图片并解答…'; } const wire = await workspaceRequest(`answers/${provider === 'official' ? 'resolve' : provider}`, payload); delete question._zkRequests[provider]; if (wire.balance !== undefined) { account.user.score = wire.balance; account.user.points = wire.balance; } const raw = Array.isArray(wire.solutions) ? wire.solutions : []; const row = repository.normalize({...question, answer: raw}); // Keep upstream text for the source panel even when it cannot fill the current options. const answer = row?.answer || raw; const matched = !!row; return { form: labels[provider], answer, duration: Math.max(1, Date.now() - started), msg: scrubChargeHint(wire.message || (matched ? '' : raw.length ? '已返回内容,但无法匹配当前题目选项' : '未命中')), outcome: wire.outcome, charged: wire.charged || 0, matched }; } Answer.getAnswersFree = async question => { const answers = []; for (const provider of ['official', 'yizhi']) { if (provider === 'yizhi' && !account.user?.sources?.yizhi) continue; const started = Date.now(); try { const answer = await query(provider, question); if (answer.matched || repository.normalize({...question, answer: answer.answer})) return [answer]; answers.push(answer); } catch (e) { answers.push({form: labels[provider], answer: [], duration: Math.max(1, Date.now()-started), msg: scrubChargeHint(e.message), matched: false}); } } return answers; }; const originalAi = task.fetchAIAnswer.bind(task); task.fetchAIAnswer = async (text, question) => { const selected = models.selectTarget('ask', hasWorkspaceQuestionImages(question, text) ? 'image' : 'text'); if (selected?.config) { try { const personal = await originalAi(text, question); if (personal?.action?.action === 'preview' || repository.normalize({...question, answer: personal?.res?.answer || personal?.answer})) return personal; } catch (e) { addLog(`个人 AI 未返回可用答案:${e.message}`, 'warning'); } } if (!account.user?.sources?.sharedAi) return {form: 'AI', answer: [], duration: 0, msg: '个人 AI 未返回答案,后台公共 AI 未启用'}; return query('ai', question); }; function saveManual(question, force = false) { if (!question || task.start || task.loading || app.app.examCacheEnabled === false) return false; if (!force && ((question._randomFilled || /随机/.test(question.form?.form || '')) && !question._zkManualEdited || repository.normalize({...question, answer: question.form?.answer}))) return false; const stored = repository.get(question); if (!force && stored && repository.sourceGroup(stored) !== 'personal') return false; if (!question.$options?.length && question.html && ['0', '1'].includes(question.type)) { const candidates = O(question.html).find('li, dd, label'); if (candidates.length === question.options.length) question.$options = candidates; } const manual = WorkspaceManualReader.readManualAnswerFromPage(question, task.rule); if (!manual || !repository.save({...question, answer: manual.answer, source: '自选答案'}, 'personal')) return false; repository.onChange?.(); return true; } function flushManual() { for (const question of task.questionList) saveManual(question); } const wrap = (name, before) => { const original = task[name]?.bind(task); if (original) task[name] = (...args) => { before(); return original(...args); }; }; wrap('toQuestion', flushManual); wrap('clearQuestion', flushManual); let timer; const onInput = event => { if (event.composedPath?.().some(node => node?.id === 'ZhikuWorkspace' || node?.id === 'ZhikuWorkspaceTop')) return; if (task.start || task.loading) return; if (event.isTrusted) { for (const question of task.questionList) { if (question.html?.contains?.(event.target)) question._zkManualEdited = true; } } clearTimeout(timer); timer = setTimeout(flushManual, 250); }; document.addEventListener('change', onInput, true); document.addEventListener('input', onInput, true); document.addEventListener('click', onInput, true); window.addEventListener('pagehide', flushManual); vue.watch(() => task.start, (running, previous) => { if (previous && !running) vue.nextTick(flushManual); }); vue.watch(() => task.questionList.map(row => `${row.phase}:${JSON.stringify(row.form?.answer || [])}`), () => { if (app.app.examCacheEnabled === false) return; for (const row of task.questionList) { if (row.phase !== 'done' || !row.form?.answer) continue; const source = row.form.form || ''; if (['考试缓存库', '本地缓存题库', '本地缓存库', '本地缓存'].includes(source)) continue; const origin = /一之/.test(source) ? 'yizhi' : /AI/i.test(source) ? 'ai' : 'cloud'; repository.save({...row, answer: row.form.answer, source}, origin); } repository.onChange?.(); }); const workflow = {query, saveManual, flushManual}; task._workspaceWorkflow = workflow; return workflow; } function cacheUnresolvedReview(rule, standardRows) { const repo = Answer.workspaceLibrary; if (!repo || Wn().app.examCacheEnabled === false) return; const known = new Set(standardRows.map(row => repo.keyFor(row))); try { const questions = questionParser(rule.question, rule.questionHook || null).filter(Boolean); for (const row of questions) { row.question = titleClean(row.question); if (known.has(repo.keyFor(row))) continue; if (!row.$options?.length && row.html) { const controls = O(row.html).find('li,dd,label'); if (controls.length === row.options.length) row.$options = controls; } const selected = WorkspaceManualReader.readManualAnswerFromPage(row, rule); if (selected) repo.save({...row, answer: selected.answer, source: '自选答案'}, 'personal'); } repo.onChange?.(); } catch (e) { addLog('本页无标准答案的缓存读取:' + e.message, 'warning'); } } // The update service is public and never reads or sends the account credential. function compareWorkspaceVersions(left, right) { const parts = value => { if (typeof value !== 'string' || !/^\d+(?:\.\d+){0,3}$/.test(value)) throw new Error('版本号格式无效'); const values = value.split('.').map(Number); if (values.some(x => !Number.isSafeInteger(x))) throw new Error('版本号格式无效'); return values; }; const a = parts(left), b = parts(right); for (let i = 0; i < Math.max(a.length, b.length); i++) { if ((a[i] || 0) !== (b[i] || 0)) return (a[i] || 0) > (b[i] || 0) ? 1 : -1; } return 0; } function requestWorkspaceRelease(baseUrl) { return new Promise((resolve, reject) => re({ url: `${baseUrl}/api/client/v2/releases/latest`, method: 'GET', anonymous: true, timeout: 12000, headers: {Accept: 'application/json'}, onload: response => { try { const wire = JSON.parse(response.responseText); if (response.status !== 200 || !wire.ok) throw new Error(wire.error?.message || '无法获取云端版本'); resolve(wire.result); } catch (error) { reject(error); } }, ontimeout: () => reject(new Error('检查更新超时,请稍后重试')), onerror: () => reject(new Error('暂时无法检查更新,请稍后重试')) })); } function createWorkspaceUpdates({baseUrl, currentVersion, cache, request = requestWorkspaceRelease, now = Date.now, onChange = () => {}, onAvailable = () => {}}) { const origin = new URL(baseUrl).origin, key = 'zkScriptUpdateV1'; const day = value => { const d = new Date(value); return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`; }; const normalize = release => { if (!release || typeof release !== 'object') throw new Error('云端版本信息无效'); compareWorkspaceVersions(release.version, currentVersion); return {version: release.version, publishedAt: String(release.publishedAt || '').slice(0, 40), notes: Array.isArray(release.notes) ? release.notes.slice(0, 20).map(x => String(x).slice(0, 500)) : []}; }; let saved = cache.get(key, {}); if (!saved || saved.origin !== origin) saved = {origin}; let release = null; try { if (saved.release) release = normalize(saved.release); } catch {} const state = {release, currentVersion, checking: false, error: '', lastChecked: Number(saved.lastChecked) || 0, hasNew: false, showBanner: false, downloadUrl: `${origin}/downloads/study-helper.user.js?base_url=${encodeURIComponent(origin)}`}; function emit() { state.hasNew = !!state.release && compareWorkspaceVersions(state.release.version, currentVersion) > 0; state.showBanner = state.hasNew && !(saved.dismissedVersion === state.release.version && saved.dismissedDay === day(now())); onChange({...state}); } function persist() { cache.set(key, saved); } let pending = null; function check(manual = false) { if (pending) return pending; const clock = now(), stored = cache.get(key, {}); if (!manual && stored?.origin === origin) { saved = {...stored}; try { if (stored.release) state.release = normalize(stored.release); } catch {} state.lastChecked = Number(stored.lastChecked) || 0; const checked = Number(stored.lastChecked) || 0, attempt = Number(stored.lastAttempt) || 0; if (checked > 0 && checked <= clock && day(checked) === day(clock)) { emit(); return Promise.resolve({...state, skipped: true}); } if (attempt > checked && attempt <= clock && clock - attempt < 3600000) return Promise.resolve({...state, skipped: true}); } state.checking = true; state.error = ''; saved.lastAttempt = clock; persist(); emit(); pending = (async () => { // Defer so pending is assigned even when a custom transport throws synchronously. await Promise.resolve(); try { state.release = normalize(await request(origin)); state.lastChecked = now(); saved.release = state.release; saved.lastChecked = state.lastChecked; if (manual) { delete saved.dismissedVersion; delete saved.dismissedDay; } const notify = compareWorkspaceVersions(state.release.version, currentVersion) > 0 && (saved.notifiedVersion !== state.release.version || saved.notifiedDay !== day(now())); if (notify) { saved.notifiedVersion = state.release.version; saved.notifiedDay = day(now()); } persist(); emit(); if (notify) onAvailable(state.release); return {...state}; } catch (error) { state.error = error.message || '检查更新失败'; return {...state}; } finally { state.checking = false; pending = null; emit(); } })(); return pending; } function dismiss() { if (state.release) { saved.dismissedVersion = state.release.version; saved.dismissedDay = day(now()); persist(); emit(); } } emit(); return {state, check, dismiss}; } // Only platform save rules may feed this queue; local/manual/AI answers never do. function createWorkspaceCaptureQueue({cache, owner, normalize, keyFor, send, now = Date.now}) { let busy = false; const pending = new Map(); async function enqueue(items, platform) { const user = owner(); if (!user?.id || !user.token) return {published: 0}; const scope = String(user.id); const saved = cache.get('zkPlatformUploadedV1', {}); const seen = saved[scope] || {}; for (const raw of items) { const item = normalize(raw); if (!item) continue; const key = keyFor(item); if (!seen[key]) { const id = scope + ':' + key; if (!pending.has(id)) pending.set(id, {key, scope, item, platform, attempt: 0, next: 0}); } } if (busy) return {published: 0}; busy = true; let published = 0; try { const batch = [...pending.values()].filter(row => row.scope === scope && row.next <= now()).slice(0, 100); if (!batch.length) return {published}; try { const result = await send(batch.map(row => row.item), platform); // A partial validation failure is retried without falsely marking every item accepted. if (result.issues?.length) throw new Error('部分标准答案未通过校验'); if (owner()?.token !== user.token) return {published: 0}; const latest = cache.get('zkPlatformUploadedV1', {}); latest[scope] ||= {}; for (const row of batch) { latest[scope][row.key] = now(); pending.delete(scope + ':' + row.key); } latest[scope] = Object.fromEntries(Object.entries(latest[scope]).sort((a,b)=>b[1]-a[1]).slice(0, 3000)); cache.set('zkPlatformUploadedV1', latest); published = result.published || 0; } catch (error) { for (const row of batch) { row.attempt++; row.next = now() + Math.min(120000, 3000 * 2 ** Math.min(row.attempt, 5)); } return {published: 0, retry: true}; } return {published}; } finally { busy = false; } } return {enqueue}; } let workspaceCaptureQueue; function cacheWorkspacePlatformAnswers(items) { const repo = Answer.workspaceLibrary; let changed = false; for (const raw of items) { const row = repo.normalize({...raw, source: '平台标准答案'}, 'platform'); if (!row) continue; const previous = repo.get(row); if (previous?.activeOrigin === 'platform' && JSON.stringify(previous.answer) === JSON.stringify(row.answer) && previous.analysis === row.analysis) continue; changed = repo.save(row, 'platform') || changed; } if (changed) repo.onChange?.(); } function uploadWorkspacePlatformAnswers(items, platform) { // The contributor keeps a free local copy even when logged out or upload fails. cacheWorkspacePlatformAnswers(items); workspaceCaptureQueue ||= createWorkspaceCaptureQueue({ cache: Cache, owner: () => {const user = Cache.get('user', {}) || {}; return {id: user.user?.id, token: user.api_key};}, normalize: row => {const item = Answer.workspaceLibrary.normalize(row); return item ? {...item, analysis: row.analysis || '', source: '平台标准答案'} : null;}, keyFor: row => md5(JSON.stringify([row.type, row.question, row.options, row.answer])), send: (rows, name) => workspaceRequest('captures/platform', {entries: rows.map(toWorkspaceEntry), context: {platform: name || ''}}) }); return workspaceCaptureQueue.enqueue(items, platform); } function createWorkspaceCaptureScanner({rules, matches, read, upload, claimed, route, locked, onRead = () => {}}) { let busy = false; return async () => { if (busy || claimed() || locked()) return; busy = true; const startRoute = route(); try { for (const rule of rules()) { try { if (rule.type !== 'save' || !matches(rule)) continue; if (rule.init && await rule.init() === false) continue; const rows = await read(rule); if (route() !== startRoute || !matches(rule) || claimed()) return; onRead(rule, rows); await upload(rows, rule.name); } catch { /* Other platform rules can still collect on this page. */ } } } finally { busy = false; } }; } function installWorkspaceCaptureWatch() { if (ie.__zkCaptureWatch) return; ie.__zkCaptureWatch = true; const scan = createWorkspaceCaptureScanner({ rules: () => $n, matches: isRuleMatched, claimed: () => isPageClaimedByNewLine(document), route: () => location.href, locked: () => ie.vuePageChangeLock || getAskStore().start, read: async rule => (rule.collect ? await rule.collect() : questionSaveParser(rule.question, rule.answerHook || null)) .filter(row => row && String(row.type) !== '8') .map(row => ({...row, question: titleClean(row.question)})) .filter(row => Answer.workspaceLibrary.normalize(row)), upload: uploadWorkspacePlatformAnswers, onRead: (rule, rows) => {if (rows.length) getAskStore().saveQuestionData = rows;} }); let timer, firstPending = 0; const schedule = () => { firstPending ||= Date.now(); clearTimeout(timer); timer = setTimeout(() => {firstPending = 0; scan();}, Date.now() - firstPending > 3000 ? 0 : 800); }; const owned = node => { const el = node.nodeType === 1 ? node : node.parentElement; return !!el?.closest?.('#ZhikuWorkspace,#ZhikuWorkspaceTop,[data-zk-owned]'); }; new MutationObserver(records => { if (records.some(record => !owned(record.target))) schedule(); }).observe(document.documentElement, {subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: ['class', 'style', 'hidden', 'data-answer', 'data-correct']}); setInterval(scan, 15000); window.addEventListener('popstate', schedule); window.addEventListener('hashchange', schedule); window.addEventListener('zk-account-changed', schedule); schedule(); } const WORKSPACE_BRAND_LOGO = "data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2264%22%20height%3D%2264%22%20viewBox%3D%220%200%2064%2064%22%20fill%3D%22none%22%3E%0A%20%20%3Cdefs%3E%0A%20%20%20%20%3ClinearGradient%20id%3D%22ink%22%20x1%3D%225%22%20y1%3D%222%22%20x2%3D%2260%22%20y2%3D%2265%22%20gradientUnits%3D%22userSpaceOnUse%22%3E%3Cstop%20stop-color%3D%22%237165EA%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%23393184%22%2F%3E%3C%2FlinearGradient%3E%0A%20%20%20%20%3ClinearGradient%20id%3D%22leaf%22%20x1%3D%2239%22%20y1%3D%2230%22%20x2%3D%2247%22%20y2%3D%2253%22%20gradientUnits%3D%22userSpaceOnUse%22%3E%3Cstop%20stop-color%3D%22%23A1F7DE%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%2347CBB5%22%2F%3E%3C%2FlinearGradient%3E%0A%20%20%3C%2Fdefs%3E%0A%20%20%3Crect%20x%3D%221%22%20y%3D%221%22%20width%3D%2262%22%20height%3D%2262%22%20rx%3D%2219%22%20fill%3D%22url%28%23ink%29%22%2F%3E%0A%20%20%3Crect%20x%3D%221.5%22%20y%3D%221.5%22%20width%3D%2261%22%20height%3D%2261%22%20rx%3D%2218.5%22%20stroke%3D%22white%22%20stroke-opacity%3D%22.18%22%2F%3E%0A%20%20%3Cpath%20d%3D%22M16%2018H41C43.2%2018%2045%2019.8%2045%2022V24L23%2043H45V48H20C17.8%2048%2016%2046.2%2016%2044V42L38%2023H16V18Z%22%20fill%3D%22white%22%2F%3E%0A%20%20%3Cpath%20d%3D%22M34%2037L49%2029V47L34%2055V37Z%22%20fill%3D%22url%28%23leaf%29%22%2F%3E%0A%20%20%3Cpath%20d%3D%22M39%2039L44%2036M39%2044L44%2041%22%20stroke%3D%22%23245A65%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20opacity%3D%22.6%22%2F%3E%0A%20%20%3Cpath%20d%3D%22M48%2010L49.8%2014.2L54%2016L49.8%2017.8L48%2022L46.2%2017.8L42%2016L46.2%2014.2L48%2010Z%22%20fill%3D%22%23A1F7DE%22%2F%3E%0A%3C%2Fsvg%3E%0A"; // Independently authored presentation layer. Platform adapters and task runner are injected below. const WorkspacePanel = vue.defineComponent({ name: 'WorkspacePanel', setup() { const app = Wn(), task = Xn(), account = Jn(), models = Yn(); ie[Ve + 'app'] = app; ie[Ve + 'ask'] = task; ie[Ve + 'user'] = account; ie[Ve + 'ai'] = models; const view = vue.ref('ask'), snackbar = vue.ref(null), busy = vue.ref(false), error = vue.ref(''); const loginMode = vue.ref('account'), username = vue.ref(''), password = vue.ref(''), email = vue.ref(''), agreeTerms = vue.ref(false); const spaceOpening = vue.ref(false); const connection = vue.reactive({status: 'unknown', error: ''}); const importsError = vue.ref(''); const officialQuery = vue.ref(''), officialRows = vue.ref([]), importStatus = vue.ref([]), importTotal = vue.ref(0), importPage = vue.ref(1); const query = vue.ref(''), results = vue.ref([]), searched = vue.ref(false), searchMode = vue.ref('bank'), aiResult = vue.ref(''); const localFilter = vue.ref(''), localType = vue.ref(''), localScope = vue.ref('all'), localOrigin = vue.ref(''), vaultFocus = vue.ref(null); const library = vue.shallowRef([]), importInput = vue.ref(null), hiddenRecords = vue.ref(0); const libraryLimit = vue.ref(40), captureBusy = vue.ref(false), libraryTab = vue.ref('list'); const logFilter = vue.ref('all'); const confirmBox = vue.ref(null), settingsOpen = vue.ref(false); const configTab = vue.ref('display'); const importPaste = vue.ref(''), importPreview = vue.ref(null); const importQueueVersion = vue.ref(0); const shellRef = vue.ref(null), ballRef = vue.ref(null); const markFilter = vue.ref('all'), focusMode = vue.ref(false); const appearance = vue.ref(Cache.get('zkAppearance', 'light')); const density = vue.ref(Cache.get('zkDensity', 'comfortable')); const viewTitles = { home: '概览', ask: '答题工作台', config: '偏好设置', account: '连接与账户', vault: '本地缓存库', official: '知库题库', imports: '导入本地题库', logs: '运行日志', search: '知识检索' }; const navigation = [ {label: '学习', items: [['home', '概览', 'grid'], ['ask', '答题工作台', 'edit'], ['search', '知识检索', 'search']]}, {label: '题库', items: [['official', '知库题库', 'book'], ['vault', '本地缓存库', 'library'], ['imports', '导入本地题库', 'upload']]}, {label: '设置', items: [['config', '偏好设置', 'settings'], ['logs', '运行日志', 'log']]} ]; if (!Cache.get('zkAutoRunOn')) { Cache.set('autoAnswer', true); Cache.set('zkAutoRunOn', 1); task.autoAnswer = true; } const uiNotice = vue.ref(''); const preferences = vue.reactive({ delay: task.delay, optionDelay: task.optionDelay || 0, autoStart: task.autoAnswer, skipDone: task.skipFinish, autoNext: task.autoNext, randomAnswer: task.randomAnswer }); const repository = Answer.workspaceLibrary || (Answer.workspaceLibrary = createWorkspaceLibrary({ cache: Cache, hash: questionHash, cleanHtml: removeHtml, nonAnswer: findNonAnswerText })); repository.initialize(); const defaultShell = () => ({x: Math.max(8, window.innerWidth - 900 - 24), y: window.innerWidth <= 560 ? 8 : 24}); const defaultBall = () => ({x: Math.max(12, window.innerWidth - 150), y: Math.max(12, window.innerHeight - 72)}); const shellPos = vue.reactive(Cache.get('zkShellPos', null) || defaultShell()); const ballPos = vue.reactive(Cache.get('zkBallPos', null) || defaultBall()); let dragMoved = false; let releaseDrag = null; function clampPosition(pos, element) { const rect = element?.getBoundingClientRect(); const width = rect?.width || Math.min(900, window.innerWidth - 16); const height = rect?.height || Math.min(780, window.innerHeight - 48); pos.x = Math.min(Math.max(8, window.innerWidth - width - 8), Math.max(8, pos.x)); pos.y = Math.min(Math.max(8, window.innerHeight - height - 8), Math.max(8, pos.y)); } const keepInView = () => { clampPosition(shellPos, shellRef.value); if (ballRef.value) clampPosition(ballPos, ballRef.value); }; function bindDrag(getPos, saveKey, canStart) { return event => { if (event.button !== 0) return; if (canStart && !canStart(event)) return; event.preventDefault(); const pos = getPos(); const sx = event.clientX, sy = event.clientY, ox = pos.x, oy = pos.y; dragMoved = false; const move = ev => { const dx = ev.clientX - sx, dy = ev.clientY - sy; if (Math.abs(dx) + Math.abs(dy) > 3) dragMoved = true; pos.x = ox + dx; pos.y = oy + dy; clampPosition(pos, saveKey === 'zkShellPos' ? shellRef.value : ballRef.value); }; const up = () => { window.removeEventListener('pointermove', move); window.removeEventListener('pointerup', up); window.removeEventListener('pointercancel', up); releaseDrag = null; if (dragMoved) Cache.set(saveKey, {x: pos.x, y: pos.y}); }; window.addEventListener('pointermove', move); window.addEventListener('pointerup', up); window.addEventListener('pointercancel', up); releaseDrag = up; }; } const onShellDrag = bindDrag(() => shellPos, 'zkShellPos', e => !!e.target.closest('[data-zk-drag]') && !e.target.closest('button,a,input,select')); const onBallDrag = bindDrag(() => ballPos, 'zkBallPos'); const h = vue.h; const iconPaths = { grid: ['M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z'], book: ['M12 6v14M4 4h4a4 4 0 0 1 4 3 4 4 0 0 1 4-3h4v14h-4a5 5 0 0 0-4 2 5 5 0 0 0-4-2H4V4Z', 'M7 8h1M16 8h1'], edit: ['M12 4H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-6', 'm13 11 6-7a2 2 0 0 1 3 3l-7 6-3 1 1-3Z', 'm18 5 3 3M8 16h3'], search: ['M17 10a6.5 6.5 0 1 1-13 0 6.5 6.5 0 0 1 13 0', 'm15 15 5 5M7 10h6M10 7v6'], library: ['M4 5v14M8 5v14M13 5v14M17 5l4 13M3 20h18', 'M4 8h4M13 8h2'], archive: ['M4 4h16v4H4zM6 8v12h12V8M10 12h4'], upload: ['M5 14v5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-5', 'M12 15V4m-4 4 4-4 4 4M8 17h8'], download: ['M12 4v11m-4-4 4 4 4-4M5 16v3a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-3'], settings: ['M4 6h5m5 0h6M4 12h10m5 0h1M4 18h2m5 0h9', 'M14 6a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0M19 12a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0M11 18a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0'], user: ['M16 8a4 4 0 1 1-8 0 4 4 0 0 1 8 0M5 20v-1a6 6 0 0 1 6-5h2a6 6 0 0 1 6 5v1'], log: ['M8 4h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2Z', 'M3 8h5M3 12h5M3 16h5M11 8h5M11 12h5M11 16h3'], check: ['m6 12 4 4 8-8'], chevron: ['m10 6 6 6-6 6'], arrow: ['M5 12h14m-5-4 4 4-4 4'], refresh: ['M19 8a8 8 0 0 0-13-2L4 8m0-4v4h4M5 16a8 8 0 0 0 13 2l2-2m0 4v-4h-4'], play: ['M8 5.8c0-.8.9-1.2 1.6-.8l9 6.2a1 1 0 0 1 0 1.6l-9 6.2c-.7.4-1.6 0-1.6-.8V5.8Z'], pause: ['M7 5h3v14H7zM15 5h3v14h-3z'], sparkles: ['m11 4 2.1 5.9L19 12l-5.9 2.1L11 20l-2.1-5.9L3 12l5.9-2.1L11 4ZM19 3v4m-2-2h4'], copy: ['M9 8h10a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1ZM15 4H5a1 1 0 0 0-1 1v10'], close: ['m7 7 10 10M17 7 7 17'], minus: ['M6 12h12'], moon: ['M20 14a8 8 0 0 1-10-10 8.5 8.5 0 1 0 10 10Z'], sun: ['M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0M12 3v1m0 16v1M3 12h1m16 0h1M5.6 5.6l.8.8m11.2 11.2.8.8M5.6 18.4l.8-.8M17.6 6.4l.8-.8'], focus: ['M4 9V5a1 1 0 0 1 1-1h4M15 4h4a1 1 0 0 1 1 1v4M20 15v4a1 1 0 0 1-1 1h-4M9 20H5a1 1 0 0 1-1-1v-4'], link: ['m9 15 6-6M8 16l-1 1a4 4 0 0 1-6-6l4-4a4 4 0 0 1 6 0M16 8l1-1a4 4 0 0 1 6 6l-4 4a4 4 0 0 1-6 0'], info: ['M12 11v5m0-9v.1', 'M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0'], megaphone: ['M11 6a13 13 0 0 0 8.4-2.8A1 1 0 0 1 21 4v12a1 1 0 0 1-1.6.8A13 13 0 0 0 11 14H7a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1Z', 'M6 14a3 3 0 0 0 3 3v3a2 2 0 0 1-4 0v-3a3 3 0 0 0 1-3'], trash: ['M4 7h16M9 7V4h6v3M6 7l1 12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1l1-12M10 10v7M14 10v7'], key: ['m10 14-6 6m2-2 2 2m0-6 2 2M20 8a5 5 0 1 1-10 0 5 5 0 0 1 10 0M17 7v.1'], folder: ['M4 6a1 1 0 0 1 1-1h5l2 3h7a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V6Z'], logout: ['M10 4H5a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h5M11 12h9m-4-4 4 4-4 4'] }; const brand = (size = 32) => h('img', {class: 'zk-brand-logo', src: WORKSPACE_BRAND_LOGO, width: size, height: size, alt: ''}); const icon = (name, size = 18) => h('svg', {class: 'zk-icon', width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', 'stroke-width': 1.75, 'stroke-linecap': 'round', 'stroke-linejoin': 'round', 'aria-hidden': 'true'}, (iconPaths[name] || iconPaths.book).map(d => h('path', {d}))); let notificationTimer; const tell = (text, type = 'info') => { snackbar.value = {text: String(text), type}; clearTimeout(notificationTimer); notificationTimer = setTimeout(() => snackbar.value = null, 3800); }; const askConfirm = (title, body, options = {}) => new Promise(resolve => { confirmBox.value = {title, body, danger: !!options.danger, ok: options.ok || '确定', cancel: options.cancel || '取消', resolve}; }); const closeConfirm = ok => { const box = confirmBox.value; confirmBox.value = null; box?.resolve(!!ok); }; const run = async fn => { if (busy.value) return; busy.value = true; error.value = ''; try { return await fn(); } catch (e) { error.value = e.message || String(e); } finally { busy.value = false; } }; function refreshLocal() { library.value = repository.list(); hiddenRecords.value = repository.hiddenCount(); } function navigate(next) { if (next === 'import') next = 'imports'; if (['bank', 'exam'].includes(next)) { libraryTab.value = next === 'import' ? 'import' : 'list'; if (next === 'exam') localOrigin.value = ''; next = 'vault'; } view.value = next; error.value = ''; settingsOpen.value = false; if (next === 'vault' || next === 'home') refreshLocal(); if (next === 'imports' && account.isLoggedIn) loadImportStatus(); if (next === 'account' && account.isLoggedIn) refreshAccount(); } function persistApp(patch) { app.setConfig(patch); } const selectedChannel = models.settings.defaultChannelId; const selectedInstance = models.settings.instances.find(x => x.channelId === selectedChannel); const customSaved = models.settings.customChannels.find(x => x.id === selectedChannel); const presetSaved = models.catalog.channels.find(x => x.id === selectedChannel); const aiForm = vue.reactive({ provider: customSaved ? 'custom' : selectedChannel || models.catalog.channels[0]?.id || '', baseUrl: customSaved?.baseUrl || presetSaved?.baseUrl || '', model: selectedInstance?.modelId || customSaved?.model || presetSaved?.defaultModelId || '', credential: selectedInstance?.credential?.value || '', enabled: app.app.zkAiEnabled !== false, adoption: selectedChannel && ['preview', 'conservative', 'direct'].includes(models.settings.adoptionStrategy) ? models.settings.adoptionStrategy : 'preview' }); const marks = vue.computed(() => task.questionList.map((q, index) => task.aiPreview?.index === index ? 'wait' : q.phase === 'done' || q.status === 1 ? 'done' : q.phase === 'failed' || q.phase === 'no-answer' || q.status === 2 ? 'none' : q.phase && z.has(q.phase) ? 'run' : 'todo')); const complete = vue.computed(() => marks.value.filter(x => x === 'done').length); const missing = vue.computed(() => marks.value.filter(x => x === 'none').length); const processed = vue.computed(() => complete.value + missing.value); const waiting = vue.computed(() => marks.value.filter(x => x === 'wait').length); const current = vue.computed(() => task.questionList[task.questionInx] || null); const currentMark = vue.computed(() => marks.value[task.questionInx] || 'todo'); const questionIndexes = vue.computed(() => task.questionList.map((_, i) => i).filter(i => markFilter.value === 'all' || marks.value[i] === markFilter.value)); const runLabel = vue.computed(() => task.scanning ? '识别中' : task.start ? '答题中' : processed.value && processed.value === task.questionList.length && task.questionList.length ? '已完成' : task.questionList.length ? '待开始' : '未识别'); const sourceSummary = vue.computed(() => Object.entries(task.formMap || {}).filter(([, count]) => Number(count) > 0).map(([name, count]) => [name, Number(count)])); const sourceSummaryText = vue.computed(() => sourceSummary.value.map(([name, count]) => `${count} 题来自${name}`).join(',')); const pageHashes = vue.computed(() => new Set([...(task.saveQuestionData || []), ...task.questionList].filter(item => item && Array.isArray(item.options)).map(item => repository.keyFor(item)))); const capturedHashes = vue.computed(() => new Set((task.saveQuestionData || []).filter(item => item && Array.isArray(item.options)).map(item => repository.keyFor(item)))); const capturedRows = vue.computed(() => library.value.filter(item => item.activeOrigin === 'platform' && capturedHashes.value.has(repository.keyFor(item)))); const pageRows = vue.computed(() => library.value.filter(item => pageHashes.value.has(repository.keyFor(item)))); const localRows = vue.computed(() => library.value.filter(item => { if (localScope.value === 'captured' && (item.activeOrigin !== 'platform' || !capturedHashes.value.has(repository.keyFor(item)))) return false; if (localScope.value === 'page' && !pageHashes.value.has(repository.keyFor(item))) return false; if (localType.value && String(item.type) !== localType.value) return false; if (localOrigin.value && repository.sourceGroup(item) !== localOrigin.value) return false; const needle = localFilter.value.trim(); if (!needle) return true; const blob = `${cleanQuestionText(item.question)}\n${answerText(item.answer)}\n${(item.options || []).map(textOf).join('\n')}`; return blob.includes(needle); })); const visibleSources = vue.computed(() => Object.entries(repository.sourceLabels) .map(([id, label]) => ({id, label, count: library.value.filter(row => repository.sourceGroup(row) === id).length})) .filter(item => item.count > 0)); vue.watch(visibleSources, rows => { if (localOrigin.value && !rows.some(row => row.id === localOrigin.value)) localOrigin.value = ''; }); const pendingImportCount = vue.computed(() => { importQueueVersion.value; return (Cache.get('zkImportOutboxV3', []) || []).filter(row => row.owner === account.user?.id).reduce((sum, row) => sum + row.entries.length, 0); }); const filteredLogs = vue.computed(() => { const rows = [...(app.logs || [])].reverse(); if (logFilter.value === 'all') return rows.slice(0, 60); return rows.filter(x => x.type === logFilter.value).slice(0, 60); }); const noticeVisible = vue.computed(() => !!String(uiNotice.value || '').trim()); const scriptVersion = vue.computed(() => We?.script?.version || app?.script?.version || '1.0.1'); const updateState = vue.ref({checking: false, hasNew: false, showBanner: false, error: '', lastChecked: 0, release: null}); const updates = createWorkspaceUpdates({baseUrl: Ye, currentVersion: scriptVersion.value, cache: Cache, onChange: state => updateState.value = state, onAvailable: release => tell(`发现新版本 v${release.version},可在面板直接更新`, 'info')}); const checkUpdates = async () => { const state = await updates.check(true); if (state.error) tell(state.error, 'warning'); else tell(state.hasNew ? `发现新版本 v${state.release.version}` : '当前已是最新版本', state.hasNew ? 'info' : 'success'); }; const openUpdateSettings = () => { configTab.value = 'updates'; navigate('config'); }; const scrubChargeHint = text => String(text || '') .replace(/[;;,,]?\s*未扣积分/g, '') .replace(/[;;,,]?\s*积分已退回(?:,请重新查询)?/g, '') .replace(/[;;,,]?\s*未调用公共 AI/g, '') .replace(/返还积分/g, '') .replace(/^[;;,,\s]+|[;;,,\s]+$/g, '') .trim(); const safe = text => M.sanitize(String(text ?? ''), {ALLOWED_TAGS: ['img', 'br', 'sub', 'sup', 'code', 'b', 'strong', 'em'], ALLOWED_ATTR: ['src'], ALLOW_DATA_ATTR: false}); const rich = (className, text) => h('div', {class: className, innerHTML: safe(text)}); const textOf = value => typeof value === 'string' ? value : value == null ? '' : Array.isArray(value) || (value && typeof value === 'object') ? answerText(value) : String(value); const unwrapAnswerParts = value => { if (value == null || value === '') return []; if (typeof value === 'boolean') return [value ? '正确' : '错误']; if (typeof value === 'number') return Number.isFinite(value) ? [String(value)] : []; if (typeof value === 'string') { const text = value.trim(); if (!text) return []; if ((text.startsWith('[') && text.endsWith(']')) || (text.startsWith('{') && text.endsWith('}'))) { try { return unwrapAnswerParts(JSON.parse(text)); } catch {} } return [text]; } if (Array.isArray(value)) return value.flatMap(unwrapAnswerParts); if (typeof value === 'object') return Object.values(value).flatMap(unwrapAnswerParts); return [String(value)]; }; const answerText = value => unwrapAnswerParts(value).filter(Boolean).join(';'); const button = (label, click, options = {}) => h('button', {type: 'button', onClick: click, ...options}, label); const actions = children => h('div', {class: 'zk-actions'}, children); const field = (label, value, change, options = {}) => { const {tag = 'input', children, ...attrs} = options; return h('label', {class: 'zk-field'}, [h('span', label), h(tag, {type: attrs.type || 'text', value, 'aria-label': label, onInput: e => change(e.target.value), ...attrs}, children)]); }; const intervalSlider = (label, value, change, minimum = 0, maximum = 10000) => { const min = Math.max(0, Number(minimum) || 0); const current = Math.max(min, Number(value) || 0); const max = Math.max(maximum, current, min); return h('div', {class: 'zk-interval'}, [ h('span', {class: 'zk-interval-heading'}, [h('span', label), h('output', `${current} ms`)]), h('input', {type: 'range', min, max, step: 1, value: current, 'aria-label': label, 'aria-valuetext': `${current} 毫秒`, onInput: event => change(Number(event.target.value))}), h('span', {class: 'zk-interval-scale'}, [h('span', min ? `平台最低 ${min} ms` : '0 ms'), h('span', `${max} ms`)]) ]); }; const sw = (label, value, change) => h('label', {class: 'zk-switch'}, [ h('input', {type: 'checkbox', checked: value, onChange: e => change(e.target.checked)}), h('i'), h('span', label) ]); const chips = (items, active, change) => h('div', {class: 'zk-chips'}, items.map(([id, label]) => button(label, () => change(id), {class: {'is-on': active === id}}))); const empty = (title, description, action = null, glyph = 'book') => h('div', {class: 'zk-empty'}, [h('span', {class: 'zk-empty-icon'}, icon(glyph, 26)), h('b', title), h('p', description), action]); const scanWait = () => h('div', {class: 'zk-empty zk-scan', role: 'status', 'aria-live': 'polite'}, [ h('div', {class: 'zk-scan-spinner', 'aria-hidden': 'true'}), h('b', '正在读取网页题目'), h('p', task.scanText || '请稍候,正在识别当前页面…'), h('div', {class: 'zk-scan-dots', 'aria-hidden': 'true'}, [h('i'), h('i'), h('i')]) ]); const pageBar = (title, subtitle = '') => h('div', {class: 'zk-page-heading'}, [h('div', [h('span', {class: 'zk-eyebrow'}, '知库 / ' + (viewTitles[view.value] || '学习')), h('h2', title), subtitle ? h('p', subtitle) : null])]); const iconButton = (glyph, label, click, options = {}) => button(icon(glyph), click, {class: 'zk-icon-btn', title: label, 'aria-label': label, ...options}); const labeledButton = (glyph, label, click, options = {}) => button([icon(glyph, 16), h('span', label)], click, options); const sectionHeading = (title, hint = '') => h('div', {class: 'zk-section-heading'}, [h('h3', title), hint ? h('span', hint) : null]); const saveBlob = (value, name) => { const url = URL.createObjectURL(new Blob([typeof value === 'string' ? value : JSON.stringify(value, null, 2)], {type: 'application/json'})); const link = document.createElement('a'); link.href = url; link.download = name; link.click(); setTimeout(() => URL.revokeObjectURL(url), 20000); }; const selectQuestion = index => { task.toQuestion(index); try { task.rule?.toquestion?.(index); } catch {} }; function moveQuestion(step) { const list = questionIndexes.value; const position = list.indexOf(task.questionInx); const target = list[position + step]; if (target !== undefined) selectQuestion(target); } async function copyText(value) { try { const text = cleanQuestionText(String(value)); if (navigator.clipboard?.writeText) await navigator.clipboard.writeText(text); else { const input = document.createElement('textarea'); input.value = text; input.style.cssText = 'position:fixed;left:-9999px'; document.body.appendChild(input); input.select(); const ok = document.execCommand('copy'); input.remove(); if (!ok) throw new Error(); } tell('已复制到剪贴板', 'success'); } catch { tell('复制失败,请选中文本后复制', 'warning'); } } function collectQuestion(q) { if (workflow.saveManual(q, true)) tell('自选答案已存入本地缓存库', 'success'); else tell('请先在考试页面选择或填写完整答案', 'warning'); } function setAppearance(next) { appearance.value = next; Cache.set('zkAppearance', next); } function setDensity(next) { density.value = next; Cache.set('zkDensity', next); } async function openPersonalSpace(event, page = 'overview') { event.preventDefault(); if (!account.isLoggedIn) { tell('请先在本页使用账号密码登录,登录后可免密打开个人空间', 'warning'); navigate('account'); return; } if (spaceOpening.value) return; const popup = window.open('about:blank', '_blank'); if (!popup) { tell('请允许浏览器打开新标签页后重试', 'warning'); return; } popup.opener = null; popup.document.title = '正在打开个人空间'; popup.document.body.textContent = '正在登录知库个人空间…'; spaceOpening.value = true; const owner = Cache.get('user', {}).api_key; try { const result = await workspaceRequest('space-access', {}, 15000); if (!account.isLoggedIn || Cache.get('user', {}).api_key !== owner) throw new Error('登录状态已变更,请重新打开个人空间'); if (typeof result.ticket !== 'string' || !/^[A-Za-z0-9_-]{32,128}$/.test(result.ticket)) throw new Error('个人空间登录凭证无效,请重试'); popup.location.replace(`${Ye}/space#loginTicket=${encodeURIComponent(result.ticket)}&page=${encodeURIComponent(page)}`); } catch (problem) { popup.close(); tell(problem.message || '暂时无法打开个人空间,请重试', 'warning'); } finally { spaceOpening.value = false; } } async function login() { await run(async () => { const response = await account.loginByPassword(username.value.trim(), password.value); if (!response.success) throw new Error(response.message); password.value = ''; tell('已连接', 'success'); await vuePageChange(); navigate('account'); }); } async function register() { await run(async () => { const name = username.value.trim(), secret = password.value, mail = email.value.trim(); if (!name) throw new Error('请输入账户名'); if (!mail) throw new Error('请填写邮箱'); if (secret.length < 8) throw new Error('密码至少 8 位'); if (!agreeTerms.value) throw new Error('请先阅读并同意隐私政策与服务条款'); const [response] = await requestApi(apiUrl('accounts'), 'POST', {username: name, password: secret, email: mail}); const result = JSON.parse(response.responseText); if (result.code !== 200) throw new Error(result.message || '注册失败'); account.user = result.data.user; account.apiKey = result.data.api_key; account.isLoggedIn = true; account.loginTime = Date.now(); account.saveToCache(); password.value = ''; email.value = ''; agreeTerms.value = false; tell('注册成功', 'success'); await vuePageChange(); }); } async function start() { if (!account.isLoggedIn) { navigate('account'); tell('请先连接', 'warning'); return; } await run(async () => { await task.toggleStart(); await account.fetchUserInfo(); }); } async function restart() { if (!account.isLoggedIn) { navigate('account'); tell('请先连接', 'warning'); return; } await run(async () => { await task.restart(); await account.fetchUserInfo(); }); } async function researchQuestion(index = task.questionInx) { if (task.start) { tell('请先暂停自动答题', 'warning'); return; } if (task.loading || busy.value) return; if (!task.questionList[index]) return; await run(async () => { await task.reAnswer(index); await account.fetchUserInfo(); const row = task.questionList[index]; const ok = row && (row.phase === 'done' || row.status === 1); tell(ok ? '本题已重新匹配' : '本题已重新检索', ok ? 'success' : 'warning'); }); } async function rescan() { if (task.start) { tell('请先停止任务', 'warning'); return; } await run(async () => { await vuePageChange(); tell(`识别 ${task.questionList.length} 题`, 'success'); }); } async function searchWorkspace() { if (searchMode.value === 'ai') return searchAi(); if (query.value.trim().length < 2) { error.value = '请输入至少两个字符'; return; } await run(async () => { const needle = query.value.trim(); const local = repository.list().filter(item => `${cleanQuestionText(item.question)}\n${(item.options || []).map(textOf).join('\n')}`.includes(needle)).slice(0, 100) .map(item => ({...item, answerSource: repository.describe(item)})); results.value = local; searched.value = true; aiResult.value = ''; if (!account.isLoggedIn) { tell('已检索本地题库;登录后可同时检索知库题库'); return; } try { const result = await account.fuzzySearchQuestion({question: needle}); if (!result.success) throw new Error(result.message || '云端检索失败'); const keys = new Set(local.map(item => repository.keyFor(item))); results.value = [...local, ...result.data.filter(item => !keys.has(repository.keyFor(item)))]; } catch (e) { if (!local.length) throw e; tell('云端暂不可用,已显示本地免费结果:' + e.message, 'warning'); } }); } async function searchAi() { if (query.value.trim().length < 2) { error.value = '请输入至少两个字符'; return; } if (!models.settings.defaultChannelId && !account.user?.sources?.sharedAi) { error.value = '请先配置个人 AI 或启用后台公共 AI'; return; } await run(async () => { const text = query.value.trim(); const fake = {type: '8', question: text, options: []}; const result = await task.fetchAIAnswer(text, fake); const res = result?.res || result; aiResult.value = res?.rawText || answerText(res?.answer) || result?.reason || '模型未返回内容'; results.value = []; searched.value = true; }); } async function loadImportStatus() { const owner = account.user?.id; const page = importPage.value; try { const data = await workspaceRequest(`imports?page=${page}`); if (account.user?.id !== owner || !account.isLoggedIn || importPage.value !== page) return; importStatus.value = data.items; importTotal.value = data.total; importsError.value = ''; } catch (e) { if (account.isLoggedIn && account.user?.id === owner && importPage.value === page) importsError.value = e.message; } } async function flushImports() { if (!account.isLoggedIn || captureBusy.value) return; const owner = account.user.id; const outbox = Cache.get('zkImportOutboxV3', []); const batches = outbox.filter(x => x.owner === owner); if (!batches.length) { if (view.value === 'imports') await loadImportStatus(); return; } captureBusy.value = true; try { for (const batch of batches) { if (!account.isLoggedIn || account.user.id !== owner) break; const received = await workspaceRequest('captures', {entries: batch.entries, context: {platform: '个人文件导入'}}); if (received.issues?.length) importsError.value = `云端校验未通过:${received.issues.map(item => `第 ${item.row} 题 ${item.message}`).join(';')}`; Cache.set('zkImportOutboxV3', Cache.get('zkImportOutboxV3', []).filter(x => x.id !== batch.id)); importQueueVersion.value++; } if (account.isLoggedIn && account.user.id === owner) { if (view.value === 'imports') await loadImportStatus(); await account.fetchUserInfo(); } } catch (e) { tell('本地题目可正常使用;云端同步稍后自动重试:' + e.message, 'warning'); } finally { captureBusy.value = false; } } async function importRows(rows) { if (!account.isLoggedIn) throw new Error('请先登录后再导入'); if (!Array.isArray(rows) || rows.length > 5000) throw new Error('每次最多导入 5000 道题'); const imported = repository.importPrivate(rows.map(raw => raw?.kind !== undefined ? fromWorkspaceEntry(raw) : raw)); refreshLocal(); if (imported.rows.length) { const outbox = Cache.get('zkImportOutboxV3', []); const owner = account.user.id; const queued = new Set(outbox.filter(batch => batch.owner === owner).flatMap(batch => batch.entries.map(entry => JSON.stringify(entry)))); const entries = imported.rows.map(toWorkspaceEntry).filter(entry => !queued.has(JSON.stringify(entry))); for (let i = 0; i < entries.length; i += 100) outbox.push({id: `${Date.now()}-${Math.random()}`, owner, entries: entries.slice(i, i + 100)}); Cache.set('zkImportOutboxV3', outbox); importQueueVersion.value++; await flushImports(); } tell(`本地已保存 ${imported.rows.length} 题,可免费使用;重复 ${imported.duplicates} · 无效 ${imported.invalid}${pendingImportCount.value ? ';联网后将自动同步剩余题目' : ''}`, imported.invalid || pendingImportCount.value ? 'warning' : 'success'); return {imported: imported.rows.length, invalid: imported.invalid}; } function restorePrivateImport(record) { const imported = repository.importPrivate([fromWorkspaceEntry(record.payload)]); refreshLocal(); tell(imported.rows.length ? '已恢复到本地缓存库,可免费使用' : '该记录缺少完整题目或答案,无法恢复', imported.rows.length ? 'success' : 'warning'); } async function searchOfficial() { if (!account.isLoggedIn) { navigate('account'); return; } await run(async () => { officialRows.value = (await workspaceRequest('catalog/search', {text: officialQuery.value.trim()})).entries.map(fromWorkspaceEntry); }); } async function unlockOfficial(row) { await run(async () => { const cached = repository.get(row); const answer = cached ? {answer: cached.answer} : await workflow.query('official', row); row.answer = answer.answer; row.answerSource = cached ? repository.describe(cached) : '知库题库'; officialRows.value = [...officialRows.value]; if (!cached && repository.save({...row, answer: answer.answer, source: '知库题库'}, 'cloud')) refreshLocal(); await account.fetchUserInfo(); }); } function renderOfficial() { return h('div', {class: 'zk-page'}, [pageBar('知库题库', '已有本地答案可免费查看。'), h('div', {class: 'zk-card'}, [field('搜索题目', officialQuery.value, x => officialQuery.value = x, {placeholder: '输入至少两个字符'}), actions([button('检索题目', searchOfficial, {class: 'zk-main', disabled: busy.value || officialQuery.value.trim().length < 2})]), h('p', {class: 'zk-muted'}, '已有本地答案优先复用。')]), ...officialRows.value.map(row => h('article', {class: 'zk-card'}, [rich('zk-stem', row.question), ...renderOptions(row, new Set()), row.answer?.length ? [h('p', {class: 'zk-muted'}, row.answerSource), rich('zk-answer', answerText(row.answer))] : button(repository.get(row) ? '查看本地缓存' : '获取答案', () => unlockOfficial(row), {disabled: busy.value})]))]); } async function importLibrary(event) { const file = event.target.files?.[0]; if (!file) return; await run(async () => { if (file.size > 5 * 1024 * 1024) throw new Error('文件不能超过 5MB'); let text = (await file.text()).replace(/^\uFEFF/, '').trim(); if (/\.ecbak$/i.test(file.name)) { text = await decrypt(text); if (!text) throw new Error('无法读取本地题库备份,请检查文件是否完整'); } const rows = extractImportRows(JSON.parse(text)); await importRows(rows); }); event.target.value = ''; } function extractImportRows(json) { if (Array.isArray(json)) return json; if (!json || typeof json !== 'object') return null; if (Array.isArray(json.local) && Array.isArray(json.exam)) return [...json.local, ...json.exam]; return json.questions || json.questionList || json.examCache; } function parsePastedRows() { const text = importPaste.value.trim(); if (!text) return []; if (new Blob([text]).size > 5 * 1024 * 1024) throw new Error('内容不能超过 5MB'); let rows; if (text.startsWith('[') || text.startsWith('{')) { const json = JSON.parse(text); rows = extractImportRows(json); } else { rows = text.split(/\r?\n/).filter(line => line.trim()).map((line, i) => { const parts = line.split('\t').map(x => x.trim()); if (parts.length < 4) throw new Error(`第 ${i + 1} 行需要题干、至少两个选项和答案,用制表符分隔`); return {type: '0', question: parts[0], options: parts.slice(1, -1), answer: [parts[parts.length - 1]]}; }); } if (!Array.isArray(rows) || rows.length > 5000) throw new Error('请选择最多 5000 道题的题目数组'); return rows; } function previewPasteImport() { try { error.value = ''; const rows = parsePastedRows(); const valid = rows.map(row => repository.normalize(row?.kind !== undefined ? fromWorkspaceEntry(row) : row, 'imported')).filter(Boolean); importPreview.value = rows.length ? {count: rows.length, valid: valid.length, invalid: rows.length - valid.length, rows: valid.slice(0, 3)} : null; } catch (e) { importPreview.value = null; error.value = e.message; } } async function importFromPaste() { await run(async () => { const rows = parsePastedRows(); if (!rows.length) throw new Error('请先粘贴内容'); await importRows(rows); importPaste.value = ''; importPreview.value = null; }); } function chooseProvider(id) { aiForm.provider = id; const channel = models.catalog.channels.find(x => x.id === id); if (channel) { aiForm.baseUrl = channel.baseUrl; aiForm.model = channel.defaultModelId; } } function saveModel() { try { const url = new URL(aiForm.baseUrl.trim()); if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password || url.search || url.hash) throw new Error('模型地址无效'); const model = aiForm.model.trim(); if (!model) throw new Error('请填写模型名称'); const preset = models.catalog.channels.find(x => x.id === aiForm.provider); let id = preset?.id; if (!preset || !preset.models.some(x => x.id === model)) { id = 'zhiku-personal-model'; const channel = {id, name: '个人模型', providerKind: preset?.providerKind || 'openai-compatible', baseUrl: aiForm.baseUrl.trim().replace(/\/+$/, ''), model}; models.settings.customChannels = models.settings.customChannels.filter(x => x.id !== id); models.settings.customChannels.push(channel); } models.addChannel(id); const instance = models.settings.instances.find(x => x.channelId === id); instance.modelId = model; instance.enabled = true; models.updateCredential(id, {type: 'api-key', value: aiForm.credential.trim()}); models.settings.defaultChannelId = id; models.settings.enabledForAsk = aiForm.enabled; persistApp({zkAiEnabled: aiForm.enabled}); models.settings.adoptionStrategy = aiForm.adoption || 'preview'; models.settings.transport = 'direct'; models.saveSettings(); tell('模型已保存', 'success'); } catch (e) { error.value = e.message; } } function savePreferences() { task.delay = Math.max(Number(preferences.delay) || 0, task.minDelay || 0); task.optionDelay = Math.max(Number(preferences.optionDelay) || 0, task.optionMinDelay || 0); task.autoAnswer = preferences.autoStart; task.skipFinish = preferences.skipDone; task.autoNext = preferences.autoNext; task.randomAnswer = preferences.randomAnswer; Cache.set('delay', task.delay); Cache.set('optionDelay', task.optionDelay); Cache.set('autoAnswer', task.autoAnswer); Cache.set('skipFinish', task.skipFinish); Cache.set('autoNext', task.autoNext); Cache.set('randomAnswer', task.randomAnswer); tell('答题设置已保存', 'success'); settingsOpen.value = false; } async function clearLocalLibrary() { if (!await askConfirm('清空本地缓存', '不会删除云端题库。建议先导出。', {danger: true, ok: '清空'})) return; repository.clear(); refreshLocal(); tell('本地已清空', 'success'); } async function removeLocal(item) { if (!await askConfirm('移除题目', '从本地缓存移除?', {danger: true, ok: '移除'})) return; repository.remove(item); if (vaultFocus.value?.key === item.key) vaultFocus.value = null; refreshLocal(); } function sourceHit(item) { if (!item || item.matched === false) return false; if (item.matched === true) return true; return !!flattenAnswerTexts(item.answer || []).some(x => String(x).trim()); } function sourceRows(q) { const rows = Array.isArray(q.answer) ? q.answer : []; // Hit: keep the first priority source only. Miss: keep every attempted source. const hits = rows.filter(sourceHit); return hits.length ? [hits[0]] : rows; } function renderSources(q) { const rows = sourceRows(q); if (!rows.length) return h('div', {class: 'zk-muted'}, '尚无来源'); return h('div', {class: 'zk-source-list'}, rows.map(item => h('div', {class: ['zk-source-row', {'is-hit': sourceHit(item)}]}, [ h('div', {class: 'zk-source-meta'}, [ h('b', item.form || '题库'), item.duration != null ? h('small', `${item.duration}ms`) : null, item.needLogin ? button('登录', () => navigate('account'), {class: 'zk-link'}) : null ]), rich('zk-answer zk-source-answer', answerText(item.answer) || scrubChargeHint(item.msg) || '暂无结果') ]))); } function renderOptions(q, highlight) { return (q.options || []).map((option, i) => typeof option === 'string' ? h('div', {class: ['zk-choice', {'is-hit': highlight.has(option)}]}, [h('span', {class: 'zk-choice-key'}, String.fromCharCode(65 + i)), rich('', option)]) : h('details', {class: 'zk-details'}, [h('summary', `子题 ${i + 1}`), rich('zk-stem', option.question || answerText(option)), ...(option.options || []).map(x => rich('zk-choice', x))])); } function renderDetail() { const q = current.value; if (!q) return empty('等待题目', '进入作业页后自动识别,或点「识别」。'); const index = task.questionInx; const mark = currentMark.value; const preview = task.aiPreview?.index === index ? task.aiPreview : null; const source = repository.normalize({...q, answer: q.form?.answer})?.answer; const highlight = new Set(Array.isArray(source) ? source.map(x => String(x)) : []); const failure = task.aiFailureMap?.[index]; return h('article', {class: 'zk-detail'}, [ h('div', {class: 'zk-detail-head'}, [ h('span', {class: 'zk-num'}, `QUESTION ${String(index + 1).padStart(2, '0')}`), h('span', {class: 'zk-kind'}, typeConvert(String(q.type), false)), h('span', {class: ['zk-card-status', mark]}, [h('i'), {todo: '等待查询', run: '查询中', done: '已匹配', none: '未匹配', wait: '待确认'}[mark]]), task.loading && task.questionInx === index ? h('small', {class: 'zk-loading-text'}, task.loadingText || '…') : null ]), rich('zk-stem', q.question), h('div', {class: 'zk-options'}, renderOptions(q, highlight)), source ? h('div', {class: 'zk-answer-block'}, [h('div', {class: 'zk-answer-label'}, [icon('check', 16), '参考答案', labeledButton('copy', '复制答案', () => copyText(answerText(source)))]), rich('zk-answer', answerText(source))]) : null, failure || q.error ? h('p', {class: 'zk-error'}, scrubChargeHint(failure || q.error)) : null, preview ? h('div', {class: 'zk-preview'}, [ h('b', [icon('sparkles', 16), 'AI 建议 · 等待确认']), rich('zk-answer', answerText(preview.answer)), actions([ button('采用并继续', () => run(() => task.confirmAiPreview()), {class: 'zk-main', disabled: busy.value}), button('跳过建议', () => run(() => task.skipAiPreview()), {disabled: busy.value}) ]) ]) : null, h('details', {class: 'zk-details zk-sources', open: mark === 'none'}, [h('summary', [icon('link', 14), '查询来源', h('span', `${sourceRows(q).length} 个`)]), renderSources(q)]), q.aiMsg ? h('details', {class: 'zk-details'}, [h('summary', 'AI 分析'), h('div', {innerHTML: createSafeMarkdownHtml(q.aiMsg)})]) : null, actions([ labeledButton('focus', '定位原题', () => selectQuestion(index), {class: 'zk-ghost'}), labeledButton('copy', '复制题目', () => copyText(q.question + '\n' + (q.options || []).map(textOf).join('\n'))), labeledButton('library', '保存自选', () => collectQuestion(q), {disabled: task.start || task.loading}), mark === 'none' || mark === 'todo' ? labeledButton('refresh', busy.value || task.loading ? '检索中…' : '重新搜索本题', () => researchQuestion(index), {class: 'zk-main', disabled: busy.value || task.start || task.loading}) : null, labeledButton('sparkles', 'AI 分析', () => run(() => task.aiAnswer(index)), {class: 'zk-ghost', disabled: busy.value || task.start || !(models.settings.defaultChannelId || account.user?.sources?.sharedAi)}) ]) ]); } function renderNumberRail() { return h('div', {class: 'zk-rail'}, [ h('div', {class: 'zk-rail-heading'}, [h('strong', '题号详情'), h('span', `${questionIndexes.value.length} 题`)]), h('div', {class: 'zk-rail-grid'}, questionIndexes.value.map(index => { const mark = marks.value[index]; const markLabel = {done: '已匹配', todo: '未查询', none: '未匹配', wait: '待确认', run: '查询中'}[mark] || '未查询'; return button(String(index + 1), () => selectQuestion(index), { class: ['zk-num-btn', mark, {'is-current': index === task.questionInx}], title: `第 ${index + 1} 题 · ${markLabel} · ${cleanQuestionText(task.questionList[index].question).slice(0, 40)}`, 'aria-label': `第 ${index + 1} 题,${markLabel}`, 'aria-current': index === task.questionInx ? 'step' : undefined }); })), !questionIndexes.value.length ? h('p', {class: 'zk-muted'}, '该状态下暂无题目') : null, h('div', {class: 'zk-legend'}, [['done', '已匹配'], ['todo', '未查询'], ['none', '未匹配'], ['wait', '待确认']].map(([id, text]) => h('span', [h('i', {class: id, 'aria-hidden': 'true'}), text]))), h('div', {class: 'zk-rail-note'}, [icon('info', 14), '点击题号查看详情']) ]); } function renderSettingsModal() { if (!settingsOpen.value) return null; return h('div', {class: 'zk-modal', onClick: e => { if (e.target === e.currentTarget) settingsOpen.value = false; }}, [ h('div', {class: 'zk-modal-card', role: 'dialog', 'aria-modal': 'true', 'aria-label': '答题偏好'}, [ h('div', {class: 'zk-section-heading'}, [h('h3', '答题偏好'), iconButton('close', '关闭设置', () => settingsOpen.value = false)]), sw('进入页面自动执行', preferences.autoStart, x => preferences.autoStart = x), sw('跳过已完成', preferences.skipDone, x => preferences.skipDone = x), sw('自动跳下一题', preferences.autoNext, x => preferences.autoNext = x), sw('无答案随机', preferences.randomAnswer, x => preferences.randomAnswer = x), sw('启用 AI 答题', aiForm.enabled, x => { aiForm.enabled = x; models.settings.enabledForAsk = x; persistApp({zkAiEnabled: x}); models.saveSettings(); }), intervalSlider('题目间隔(毫秒)', preferences.delay, x => preferences.delay = x, task.minDelay), intervalSlider('选项间隔(毫秒)', preferences.optionDelay, x => preferences.optionDelay = x, task.optionMinDelay, 3000), actions([ button('取消', () => settingsOpen.value = false), button('保存偏好', savePreferences, {class: 'zk-main'}) ]) ]) ]); } function renderAsk() { return h('div', {class: 'zk-ask'}, [ h('div', {class: 'zk-heading-row'}, [pageBar('答题工作台'), labeledButton('settings', '答题偏好设置', () => settingsOpen.value = true)]), h('div', {class: 'zk-summary'}, [ h('div', {class: 'zk-summary-main'}, [h('div', [h('span', '自动答题进度'), h('strong', [String(processed.value), h('small', ` / ${task.questionList.length}`)])]), h('div', {class: 'zk-progress', role: 'progressbar', 'aria-valuenow': processed.value, 'aria-valuemin': 0, 'aria-valuemax': task.questionList.length || 1, 'aria-label': '答题进度'}, [h('i', {style: {width: `${task.questionList.length ? processed.value / task.questionList.length * 100 : 0}%`}})])]), ...[['done', complete.value, '已匹配'], ['none', missing.value, '未匹配'], ['wait', waiting.value, '待确认']].map(([id, count, text]) => button([h('strong', String(count).padStart(2, '0')), h('span', [h('i', {class: id}), text])], () => markFilter.value = markFilter.value === id ? 'all' : id, {class: ['zk-summary-stat', id, {'is-on': markFilter.value === id}], 'aria-label': `筛选${text}`})) ]), h('div', {class: 'zk-filter-bar'}, [chips([['all', '全部题目'], ['todo', '未查询'], ['none', '未匹配'], ['wait', '待确认']], markFilter.value, x => markFilter.value = x), h('span', {class: ['zk-task-state', {'is-running': task.start || task.scanning}]}, [h('i'), runLabel.value])]), sourceSummary.value.length && !task.start && runLabel.value === '已完成' ? h('div', {class: 'zk-finish-summary', role: 'status'}, [ h('div', {class: 'zk-finish-summary-head'}, [h('strong', '来源汇总'), h('span', {class: 'zk-muted'}, sourceSummaryText.value)]), h('div', {class: 'zk-finish-tags'}, sourceSummary.value.map(([name, count]) => h('span', {class: 'zk-kind'}, `${name} · ${count}`))) ]) : null, h('div', {class: 'zk-split'}, [ h('section', {class: 'zk-split-main'}, task.questionList.length ? renderDetail() : task.scanning ? scanWait() : empty('题目会出现在这里', '进入适配的作业或答案页,识别当前页面题目。', labeledButton('refresh', '识别当前页面', rescan, {disabled: busy.value, class: 'zk-main'}))), h('aside', {class: 'zk-split-side', 'aria-label': '题号详情'}, renderNumberRail()) ]), h('div', {class: 'zk-task-footer'}, [ h('div', {class: 'zk-pagination'}, [iconButton('chevron', '上一题', () => moveQuestion(-1), {class: 'zk-icon-btn zk-previous', disabled: questionIndexes.value.indexOf(task.questionInx) <= 0}), h('span', `${task.questionList.length ? task.questionInx + 1 : 0} / ${task.questionList.length}`), iconButton('chevron', '下一题', () => moveQuestion(1), {disabled: questionIndexes.value.indexOf(task.questionInx) >= questionIndexes.value.length - 1 || !questionIndexes.value.length})]), h('div', {class: 'zk-footer-actions'}, [ labeledButton('refresh', '重新识别', rescan, {disabled: busy.value || task.start || task.scanning}), labeledButton('log', '从头再答', restart, {disabled: busy.value || task.start || !task.questionList.length}), task.start ? labeledButton('pause', '暂停任务', () => { task.pause(); tell('任务已暂停'); }, {class: 'zk-main'}) : labeledButton('play', busy.value ? '处理中…' : '自动答题', start, {class: 'zk-main', disabled: busy.value || !task.questionList.length}) ]) ]), renderSettingsModal() ]); } function renderHome() { return h('div', {class: 'zk-home-page'}, [ pageBar(account.isLoggedIn ? `${account.nickname},欢迎回来` : '你的学习,从这里继续', '识别、检索、整理,让知识各得其所。'), noticeVisible.value ? h('article', {class: 'zk-notice', role: 'status'}, [ h('span', {class: 'zk-notice-mark', 'aria-hidden': 'true'}, icon('megaphone', 18)), h('div', {class: 'zk-notice-body'}, [ h('span', {class: 'zk-notice-label'}, '公告'), h('div', {class: 'zk-markdown zk-notice-content', innerHTML: createSafeMarkdownHtml(uiNotice.value)}) ]) ]) : null, h('div', {class: 'zk-home-hero'}, [ h('div', [h('span', {class: 'zk-eyebrow'}, 'CONTINUE LEARNING'), h('h3', task.questionList.length ? `当前页面有 ${task.questionList.length} 道题` : '准备好,开始今天的学习'), h('p', task.rule?.name || '打开适配平台的题目页,即可开始识别。'), labeledButton('arrow', task.questionList.length ? '进入答题工作台' : '查看当前页面', () => navigate('ask'), {class: 'zk-main'})]), h('div', {class: 'zk-hero-art', 'aria-hidden': 'true'}, [h('div', {class: 'zk-art-book'}, [icon('book', 48)]), h('span', {class: 'zk-art-spark'}, icon('sparkles', 22)), h('span', {class: 'zk-art-check'}, icon('check', 20))]) ]), h('div', {class: 'zk-overview-stats'}, [[task.questionList.length, '本页识别', 'edit'], [library.value.length, '本地题目', 'library'], [pageRows.value.length, '本页已保存', 'check']].map(([count, label, glyph]) => h('div', [icon(glyph, 18), h('strong', String(count)), h('span', label)]))), sectionHeading('常用工具', '按需打开,随时切换'), h('div', {class: 'zk-home-grid'}, [['search', '知识检索', '从题库或 AI 获取参考', 'search'], ['vault', '本地缓存库', '免费复用采集、查询与导入答案', 'library'], ['imports', '导入本地题库', '导入后即可本地免费使用', 'upload'], ['config', '模型与偏好', '按自己的习惯设置工作台', 'settings']].map(([id, title, hint, glyph]) => button([h('span', {class: 'zk-tile-icon'}, icon(glyph, 21)), h('span', {class: 'zk-tile-label'}, [h('strong', title), h('small', hint)]), icon('chevron', 16)], () => navigate(id)))), h('div', {class: 'zk-home-note'}, [icon('check', 16), '让每一次学习,都有所积累。']) ]); } function renderConfig() { const tabs = [['display', '显示设置'], ['system', '系统设置'], ['ai', 'AI设置'], ['hotkey', '快捷键'], ['updates', '脚本更新']]; let body = null; if (configTab.value === 'display') { body = h('div', {class: 'zk-card'}, [ sectionHeading('外观', '只保存在当前浏览器'), h('div', {class: 'zk-setting-row'}, [h('span', '主题'), chips([['light', '浅色'], ['dark', '深色']], appearance.value, setAppearance)]), h('div', {class: 'zk-setting-row'}, [h('span', '阅读间距'), chips([['comfortable', '舒适'], ['compact', '紧凑']], density.value, setDensity)]), sw('默认展开主面板', app.app.defaultShowFloat, x => { persistApp({defaultShowFloat: x}); app.app.showFloat = !app.app.hideFloat && !!x; }), sw('右下角气泡提示', app.app.alertBubble, x => persistApp({alertBubble: x})), sw('自动保存答题结果', app.app.examCacheEnabled !== false, x => persistApp({examCacheEnabled: x})), h('p', {class: 'zk-muted'}, '「默认展开主面板」开启后进入页面显示完整工作台;关闭后只保留右下角浮标,点浮标可展开。'), h('p', {class: 'zk-muted'}, '已保存的参考答案可免费复用,使用前请核对。'), h('p', {class: 'zk-muted'}, '拖动顶部标题栏可移动面板;右上角可切换专注模式或最小化。') ]); } else if (configTab.value === 'system') { body = h('div', {class: 'zk-card'}, [ sectionHeading('运行偏好'), sw('iframe 优化(测试)', app.app.iframe, x => persistApp({iframe: x})), sw('进入页面自动执行', preferences.autoStart, x => { preferences.autoStart = x; savePreferences(); }), sw('跳过已完成题目', preferences.skipDone, x => { preferences.skipDone = x; savePreferences(); }), sw('自动跳下一题', preferences.autoNext, x => { preferences.autoNext = x; savePreferences(); }), sw('无答案随机', preferences.randomAnswer, x => { preferences.randomAnswer = x; savePreferences(); }), intervalSlider('题目间隔(毫秒)', preferences.delay, x => preferences.delay = x, task.minDelay), intervalSlider('选项间隔(毫秒)', preferences.optionDelay, x => preferences.optionDelay = x, task.optionMinDelay, 3000), button('保存偏好', savePreferences, {class: 'zk-main'}), button('检查脚本更新', () => { openUpdateSettings(); checkUpdates(); }) ]); } else if (configTab.value === 'ai') { body = h('div', {class: 'zk-card'}, [ sectionHeading('个人 AI 模型', '优先使用个人配置,不扣知库积分'), h('p', {class: 'zk-muted'}, account.user?.sources?.sharedAi ? '后台已启用公共 AI:个人模型不可用时自动接续,每次有效答复扣 1 积分。' : '个人 AI 不可用时,仅在后台启用公共 AI 后继续调用。'), h('p', {class: 'zk-muted'}, account.user?.sources?.sharedAiVision ? '公共 AI 支持图片题。' : '公共 AI 图片题需管理员选择视觉模型并开启「支持图片题」。'), h('label', {class: 'zk-field'}, [h('span', '模型服务'), h('select', {'aria-label': '模型服务', value: aiForm.provider, onChange: e => chooseProvider(e.target.value)}, [...models.catalog.channels.map(c => h('option', {value: c.id}, c.name)), h('option', {value: 'custom'}, '自定义兼容服务')])]), field('服务 Base URL', aiForm.baseUrl, x => aiForm.baseUrl = x, {readOnly: aiForm.provider !== 'custom', placeholder: 'https://api.example.com/v1'}), h('div', {class: 'zk-form-grid'}, [field('模型名称', aiForm.model, x => aiForm.model = x), field('模型 API Key', aiForm.credential, x => aiForm.credential = x, {type: 'password', autocomplete: 'off'})]), field('答案采用方式', aiForm.adoption, x => aiForm.adoption = x, {tag: 'select', children: [h('option', {value: 'preview'}, '先预览,确认后回填'), h('option', {value: 'conservative'}, '保守匹配后采用'), h('option', {value: 'direct'}, '匹配后直接采用')]}), sw('查询未命中时使用 AI', aiForm.enabled, x => { aiForm.enabled = x; persistApp({zkAiEnabled: x}); }), actions([ labeledButton('check', '保存模型', saveModel, {class: 'zk-main'}), labeledButton('link', '测试连接', () => run(async () => { const result = await models.testConfig(models.settings.defaultChannelId); tell(result.success ? '模型连接成功' : result.displayMessage || '连接失败', result.success ? 'success' : 'warning'); }), {disabled: busy.value || !models.settings.defaultChannelId}) ]) ]); } else if (configTab.value === 'updates') { const state = updateState.value; body = h('div', {class: 'zk-card zk-update-settings'}, [ sectionHeading('脚本更新', `当前 v${scriptVersion.value}`), h('p', state.hasNew ? `发现新版本 v${state.release.version}` : state.release ? '当前已是最新版本' : '尚未检查云端版本'), h('p', {class: 'zk-muted'}, '每天自动检查一次'), h('p', {class: 'zk-muted'}, state.lastChecked ? `上次检查:${new Date(state.lastChecked).toLocaleString()}` : '更新检查不会影响账号登录和答题。'), state.error ? h('p', {class: 'zk-update-error', role: 'alert'}, state.error) : null, state.release?.notes?.length ? h('ul', {class: 'zk-update-notes'}, state.release.notes.map(note => h('li', note))) : null, actions([button(state.checking ? '正在检查…' : '手动检查更新', checkUpdates, {disabled: state.checking, class: 'zk-main'}), state.hasNew ? h('a', {class: 'zk-update-install', href: state.downloadUrl, target: '_blank', rel: 'noopener noreferrer'}, '立即更新') : null]) ]); } else { body = h('div', {class: 'zk-card'}, [ sw('启用快捷键', app.app.hotkeyEnabled, x => persistApp({hotkeyEnabled: x})), field('快捷键', app.app.hotkey || 'Ctrl+Shift+K', x => persistApp({hotkey: x.trim() || 'Ctrl+Shift+K'})), h('p', {class: 'zk-muted'}, '默认 Ctrl+Shift+K 显示或隐藏面板,修改后立即生效。在答题工作台内可用左右方向键切换题目。') ]); } return h('div', {class: 'zk-page'}, [ pageBar('偏好设置', '让工作台适合你的阅读与答题习惯。'), h('div', {class: 'zk-config'}, [ h('div', {class: 'zk-config-nav', role: 'tablist', 'aria-label': '设置分类'}, tabs.map(([id, label]) => button(label, () => configTab.value = id, {class: {'is-on': configTab.value === id}, role: 'tab', 'aria-selected': configTab.value === id}))), h('div', {class: 'zk-config-body'}, body) ]) ]); } function renderAccount() { const online = account.isLoggedIn && connection.status === 'online'; const checking = account.isLoggedIn && ['unknown', 'checking'].includes(connection.status); const exchange = account.user?.exchange || {}; const points = Number(account.user?.points ?? account.score ?? 0); const contributions = Number(account.user?.contributions || 0); const exchangeable = Number(account.user?.exchangeable || 0); const syncText = online ? '云端已同步' : checking ? '正在核对…' : (connection.error || '显示上次同步信息'); return h('div', {class: 'zk-page zk-account-page'}, [ pageBar('连接知识库', '查看管理个人中心'), account.isLoggedIn ? h('div', {class: 'zk-account-stack'}, [ h('section', {class: 'zk-card zk-account-profile'}, [ h('div', {class: 'zk-user-card'}, [ h('div', {class: 'zk-avatar'}, account.nickname?.slice(0, 1) || '知'), h('div', {class: 'zk-user-meta'}, [ h('strong', account.nickname || '知库用户'), h('span', {class: ['zk-account-sync', online ? 'is-online' : checking ? 'is-checking' : 'is-stale']}, syncText) ]), button([icon('refresh', 15)], () => refreshAccount(true), { class: 'zk-icon-btn zk-account-refresh', disabled: checking, 'aria-label': checking ? '正在刷新账户' : '刷新账户', title: '刷新账户' }) ]), h('div', {class: 'zk-account-metrics'}, [ h('div', {class: 'zk-account-metric'}, [h('span', '积分余额'), h('strong', String(points))]), h('div', {class: 'zk-account-metric'}, [h('span', '累计贡献'), h('strong', String(contributions))]), h('div', {class: 'zk-account-metric'}, [h('span', '可兑换'), h('strong', String(exchangeable))]) ]) ]), h('section', {class: 'zk-card zk-account-contrib'}, [ h('div', {class: 'zk-account-contrib-head'}, [ h('div', [h('h3', '我的贡献'), h('p', {class: 'zk-muted'}, '平台采集的新题计入贡献,重复题不重复计数。')]), h('span', {class: 'zk-kind'}, `可兑换 ${exchangeable} 题`) ]), h('div', {class: 'zk-account-contrib-body'}, [ h('p', {class: 'zk-account-rule'}, exchange.exchange_enabled ? `每 ${exchange.exchange_questions} 题兑换 ${exchange.exchange_points} 积分` : '后台尚未开放贡献兑换'), button('兑换贡献积分', () => run(async () => { const result = await workspaceRequest('contributions/exchange', {}); await account.fetchUserInfo(); tell(`已兑换 ${result.points} 积分`, 'success'); }), {class: 'zk-main', disabled: !exchange.exchange_enabled || busy.value || exchangeable < (exchange.exchange_questions || 1)}) ]) ]), h('section', {class: 'zk-card zk-account-space'}, [ h('div', {class: 'zk-account-space-row'}, [ h('div', [ h('h3', '查看个人账户详细情况') ]), h('div', {class: 'zk-account-space-actions'}, [ button(spaceOpening.value ? '正在进入…' : '进入个人空间', event => openPersonalSpace(event, 'overview'), {class: 'zk-main', disabled: spaceOpening.value}), account.user?.recharge?.enabled ? labeledButton('sparkles', '积分充值', event => openPersonalSpace(event, 'recharge'), {disabled: spaceOpening.value}) : null ]) ]), h('div', {class: 'zk-account-footer'}, [ labeledButton('logout', '退出登录', () => run(async () => { if (!await askConfirm('退出登录', '需要重新登录才能查询。')) return; await account.logout(); tell('已退出'); }), {class: 'zk-ghost zk-danger'}) ]) ]) ]) : h('div', {class: 'zk-card zk-account-card'}, [ h('form', {onSubmit: e => { e.preventDefault(); loginMode.value === 'register' ? register() : login(); }}, [ chips([['account', '账号登录'], ['register', '注册账号']], loginMode.value, x => { loginMode.value = x; error.value = ''; agreeTerms.value = false; }), h('div', [ field(loginMode.value === 'register' ? '账户名' : '用户名或邮箱', username.value, x => username.value = x, {autocomplete: 'username', maxLength: 80, required: true}), loginMode.value === 'register' ? field('邮箱', email.value, x => email.value = x, {type: 'email', autocomplete: 'email', maxLength: 254, required: true}) : null, field('密码', password.value, x => password.value = x, {type: 'password', minLength: loginMode.value === 'register' ? 8 : undefined, maxLength: 256, autocomplete: loginMode.value === 'register' ? 'new-password' : 'current-password', required: true}) ]), loginMode.value === 'register' ? h('label', {class: 'zk-agree'}, [ h('input', {type: 'checkbox', checked: agreeTerms.value, onChange: e => agreeTerms.value = e.target.checked}), h('span', ['我已阅读并同意 ', h('a', {class: 'zk-text-link', href: `${Ye}/privacy`, target: '_blank', rel: 'noopener noreferrer'}, '隐私政策'), ' 与 ', h('a', {class: 'zk-text-link', href: `${Ye}/terms`, target: '_blank', rel: 'noopener noreferrer'}, '服务条款')]) ]) : null, button(busy.value ? '正在连接…' : loginMode.value === 'register' ? '注册并连接' : '连接知识库', undefined, {type: 'submit', class: 'zk-main zk-full', disabled: busy.value}), h('p', {class: 'zk-muted'}, loginMode.value === 'register' ? '邮箱必填,用于登录、找回密码与系统通知;密码至少 8 位。' : '可用用户名或邮箱登录,与个人空间同一账号。') ]), h('p', {class: 'zk-muted zk-account-space-link'}, [h('a', {class: 'zk-text-link', href: `${Ye}/space`, target: '_blank', rel: 'noopener noreferrer', onClick: openPersonalSpace}, '打开个人空间'), ' · 管理密码、Key 与账户记录']) ]), h('div', {class: 'zk-info-line'}, [icon('info', 16), '采集和导入的答案可在本地免费使用,联网后会自动同步。']) ]); } function renderVaultList(limit) { const types = [...new Set(library.value.map(x => String(x.type)))].sort(); return [ h('div', {class: 'zk-card zk-library-filters'}, [ field('搜索本地题目', localFilter.value, x => { localFilter.value = x; libraryLimit.value = 40; }, {placeholder: '搜索题干、选项或答案'}), h('div', {class: 'zk-form-grid'}, [ field('题型筛选', localType.value, x => { localType.value = x; libraryLimit.value = 40; }, {tag: 'select', children: [h('option', {value: ''}, '全部题型'), ...types.map(t => h('option', {value: t}, typeConvert(t, false)))]}), field('分类筛选', localOrigin.value, x => { localOrigin.value = x; libraryLimit.value = 40; }, {tag: 'select', children: [h('option', {value: ''}, '全部分类'), ...visibleSources.value.map(({id, label, count}) => h('option', {value: id}, `${label} (${count})`))]}) ]), chips([['all', `全部 ${library.value.length}`], ['page', `本页题目 ${pageRows.value.length}`], ['captured', `本页采集 ${capturedRows.value.length}`]], localScope.value, x => { localScope.value = x; libraryLimit.value = 40; }) ]), actions([ labeledButton('download', '导出筛选', () => saveBlob(localRows.value, 'zhiku-collection.json'), {disabled: !localRows.value.length}), labeledButton('trash', '清空本地缓存库', clearLocalLibrary, {class: 'zk-icon-btn zk-danger', disabled: !library.value.length}) ]), h('div', {class: 'zk-result-count'}, `共 ${library.value.length} 道有效题目 · 筛选 ${localRows.value.length} 道 · 已显示 ${Math.min(limit, localRows.value.length)} 道`), hiddenRecords.value ? h('p', {class: 'zk-muted'}, `已隐藏 ${hiddenRecords.value} 条空题干、空答案或无效缓存,不参与查询和导出。`) : null, ...localRows.value.slice(0, limit).map(item => { const open = vaultFocus.value?.key === item.key; return h('article', {class: ['zk-card zk-library-item', {'is-on': open}], key: item.key}, [ h('div', {class: 'zk-detail-head'}, [ h('span', {class: 'zk-kind'}, typeConvert(String(item.type), false)), button(open ? '收起详情' : '展开详情', () => vaultFocus.value = open ? null : item, {class: 'zk-link', 'aria-expanded': open}), labeledButton('copy', '复制题目与答案', () => copyText(item.question + '\n' + answerText(item.answer))), labeledButton('trash', '删除本地题目', () => removeLocal(item), {class: 'zk-icon-btn zk-danger'}) ]), rich('zk-stem', item.question), h('div', {class: 'zk-origin-tags'}, [h('span', repository.sourceLabels[repository.sourceGroup(item)]), repository.sourceGroup(item) === 'query' ? h('span', item.source) : null, h('span', repository.verification(item))]), open ? [...renderOptions(item, new Set(unwrapAnswerParts(item.answer))), rich('zk-answer', answerText(item.answer)), item.alternatives?.length ? h('details', {class: 'zk-details'}, [h('summary', `历史答案 ${item.alternatives.length} 条`), h('p', {class: 'zk-muted'}, '同题更新时保留的不同答案,当前回填使用上方答案。'), ...item.alternatives.map(previous => h('div', [h('small', {class: 'zk-muted'}, previous.source || '历史答案'), rich('zk-answer', answerText(previous.answer))]))]) : null ] : rich('zk-answer zk-answer-excerpt', answerText(item.answer)) ]); }), !localRows.value.length ? empty(library.value.length ? '没有符合筛选的题目' : '积累你的第一道题', library.value.length ? '试试其他关键词或切换题型。' : '采集、导入或收藏的题目,会整理在这里。') : null, localRows.value.length > limit ? button('加载更多', () => libraryLimit.value += 40) : null ]; } function renderVault() { return h('div', {class: 'zk-page'}, [ pageBar('本地缓存库', '本地保存的答案请在使用前核对。'), renderVaultList(libraryLimit.value) ]); } function renderImportPage() { return h('div', {class: 'zk-page'}, [ pageBar('导入本地题库', '导入后即可本地免费使用,联网时自动同步。'), h('p', {class: 'zk-muted'}, '导入的题目本人可立即使用。平台标准答案优先保留,同题其他答案保存在历史记录。离线时先写入本地,恢复连接后自动同步。'), pendingImportCount.value ? actions([h('span', {class: 'zk-muted'}, `待同步 ${pendingImportCount.value} 题 · 本地可用,联网后自动重试`), button('重试同步', () => run(flushImports), {disabled: busy.value || captureBusy.value})]) : null, button([h('span', {class: 'zk-upload-icon'}, icon('upload', 27)), h('strong', '选择题库文件'), h('span', 'JSON / .ecbak 备份 · 单次最多 5000 题 · 最大 5MB'), h('span', {class: 'zk-badge'}, '浏览文件')], () => importInput.value?.click(), {class: 'zk-upload-zone'}), h('div', {class: 'zk-card'}, [ sectionHeading('或者粘贴题目', 'JSON / 制表符文本'), field('题库内容', importPaste.value, x => { importPaste.value = x; importPreview.value = null; }, {tag: 'textarea', rows: 7, placeholder: '[{"type":"0","question":"题干","options":["选项一","选项二"],"answer":["A"]}]'}), h('p', {class: 'zk-muted'}, '制表符文本每行一道单选题:题干 → 选项一 → 选项二 → 答案。'), actions([ labeledButton('search', '预览题目', previewPasteImport, {disabled: !importPaste.value.trim()}), labeledButton('download', '导入到本地', importFromPaste, {class: 'zk-main', disabled: busy.value || !importPaste.value.trim()}) ]), h('input', {ref: importInput, type: 'file', accept: '.json,.ecbak', class: 'zk-file', onChange: importLibrary}) ]), h('div', {class: 'zk-card'}, [sectionHeading('我的导入记录', `共 ${importTotal.value} 题`), importsError.value ? h('p', {class: 'zk-section-error', role: 'status'}, importsError.value) : null, ...importStatus.value.map(row => h('div', {class: 'zk-import-status'}, [h('span', {class: 'zk-kind'}, {pending:'同步中',approved:'已同步',rejected:'未收录'}[row.status]), rich('zk-stem', row.payload.stem), button(repository.get(fromWorkspaceEntry(row.payload)) ? '本地可用 · 免费' : '保存到本地免费使用', () => restorePrivateImport(row), {class: 'zk-link', disabled: !!repository.get(fromWorkspaceEntry(row.payload))})])), actions([button('刷新', loadImportStatus), button('上一页', () => { importPage.value--; loadImportStatus(); }, {disabled: importPage.value <= 1}), button('下一页', () => { importPage.value++; loadImportStatus(); }, {disabled: importPage.value * 20 >= importTotal.value})])]), importPreview.value ? h('div', {class: 'zk-import-preview'}, [sectionHeading('导入预览', `有效 ${importPreview.value.valid} / ${importPreview.value.count} · 无效 ${importPreview.value.invalid}`), ...importPreview.value.rows.map((item, i) => h('article', {class: 'zk-card'}, [h('span', {class: 'zk-kind'}, `题目 ${i + 1}`), rich('zk-stem', item.question), rich('zk-answer', answerText(item.answer))]))]) : null ]); } function renderLogs() { return h('div', {class: 'zk-page'}, [ pageBar('运行日志', '查看识别、查询与采集过程中的运行记录。'), h('div', {class: 'zk-card'}, [ chips([['all', '全部'], ['info', '信息'], ['success', '成功'], ['warning', '提醒'], ['error', '错误']], logFilter.value, x => logFilter.value = x), actions([ button('导出', () => saveBlob((app.logs || []).map(x => `[${x.time}][${x.type}] ${cleanQuestionText(x.content)}`).join('\n'), 'zhiku-logs.txt')), button('清空', async () => { if (!await askConfirm('清空日志', '清除运行记录?')) return; app.logs.splice(0, app.logs.length); }, {class: 'zk-danger'}) ]), ...filteredLogs.value.map((log, i) => h('div', {class: ['zk-log-row', `is-${log.type}`], key: i}, [h('i'), h('div', [h('time', log.time), h('p', cleanQuestionText(log.content))])])), !filteredLogs.value.length ? h('p', {class: 'zk-muted'}, '暂无日志') : null ]) ]); } function renderSearch() { return h('div', {class: 'zk-page'}, [ pageBar('知识检索', '输入题干或知识点,查找答案与解析。'), h('div', {class: 'zk-search-modes'}, [['bank', '知识库检索', '查找已收录的参考答案', 'library'], ['ai', 'AI 分析', '个人模型优先,公共 AI 自动接续', 'sparkles']].map(([id, title, hint, glyph]) => button([icon(glyph, 21), h('span', [h('strong', title), h('small', hint)]), h('i')], () => { searchMode.value = id; searched.value = false; results.value = []; aiResult.value = ''; }, {class: {'is-on': searchMode.value === id}, 'aria-pressed': searchMode.value === id}))), h('form', {class: 'zk-form zk-card zk-search-form', onSubmit: e => { e.preventDefault(); searchWorkspace(); }}, [ field('题干或关键句', query.value, x => query.value = x, {tag: 'textarea', rows: 4, placeholder: '粘贴一道题,或者输入你想了解的知识点…'}), actions([ labeledButton(searchMode.value === 'ai' ? 'sparkles' : 'search', busy.value ? '正在检索…' : searchMode.value === 'ai' ? '开始分析' : '检索知识库', undefined, {type: 'submit', class: 'zk-main', disabled: busy.value || !query.value.trim()}), button('清空内容', () => { query.value = ''; results.value = []; aiResult.value = ''; searched.value = false; }, {class: 'zk-ghost'}), searchMode.value === 'ai' ? button('配置模型', () => { configTab.value = 'ai'; navigate('config'); }, {class: 'zk-link'}) : null ]) ]), aiResult.value ? h('article', {class: 'zk-card'}, [h('div', {class: 'zk-detail-head'}, [h('span', {class: 'zk-kind'}, [icon('sparkles', 14), 'AI 分析']), labeledButton('copy', '复制 AI 分析', () => copyText(aiResult.value))]), h('div', {class: 'zk-markdown', innerHTML: createSafeMarkdownHtml(aiResult.value)})]) : null, searched.value && results.value.length ? sectionHeading('检索结果', `${results.value.length} 道相关题目`) : null, ...results.value.map((item, i) => h('article', {class: 'zk-card zk-library-item', key: item.id || i}, [ h('div', {class: 'zk-detail-head'}, [h('span', {class: 'zk-kind'}, typeConvert(item.type, false)), h('span', {class: 'zk-muted'}, item.answerSource || item.source || '')]), rich('zk-stem', item.question), rich('zk-answer', answerText(item.answer)), actions([labeledButton('library', repository.get(item) ? '查看免费缓存' : '获取答案 · 1 积分', () => run(async () => { const cached = repository.get(item); const result = cached ? {answer: cached.answer} : await workflow.query('official', item); item.answer = result.answer; item.answerSource = cached ? repository.describe(cached) : '知库题库'; if (!cached && repository.save({...item, source:'知库题库'}, 'cloud')) refreshLocal(); results.value = [...results.value]; await account.fetchUserInfo(); }), {class: 'zk-ghost'}), labeledButton('copy', '复制检索结果', () => copyText(item.question + '\n' + answerText(item.answer)))]) ])), searched.value && !results.value.length && !aiResult.value ? empty('暂时没有找到答案', '缩短题干或换个关键词,再试一次。', null, 'search') : null, !searched.value && !busy.value ? h('div', {class: 'zk-search-hint'}, [icon(searchMode.value === 'ai' ? 'sparkles' : 'search', 30), h('strong', searchMode.value === 'ai' ? '把问题交给你的模型' : '让积累的知识,再次派上用场'), h('p', searchMode.value === 'ai' ? '请先配置个人模型。分析结果供学习参考。' : '优先使用完整题干,或保留最关键的一句话。')]) : null ]); } const hotkey = event => { const origin = event.composedPath?.()[0] || event.target; const editing = origin?.matches?.('input,textarea,select,[contenteditable="true"]'); if (event.key === 'Escape') { if (confirmBox.value) closeConfirm(false); else settingsOpen.value = false; return; } if (app.app.showFloat && view.value === 'ask' && !editing && shellRef.value?.contains(origin) && ['ArrowLeft', 'ArrowRight'].includes(event.key)) { event.preventDefault(); moveQuestion(event.key === 'ArrowLeft' ? -1 : 1); return; } if (!app.app.hotkeyEnabled) return; const keys = (app.app.hotkey || 'Ctrl+Shift+K').toLowerCase().split('+').map(x => x.trim()); const key = keys[keys.length - 1]; if (!!event.ctrlKey === keys.includes('ctrl') && !!event.shiftKey === keys.includes('shift') && !!event.altKey === keys.includes('alt') && !!event.metaKey === keys.includes('meta') && event.key.toLowerCase() === key) { event.preventDefault(); app.app.showFloat = !app.app.showFloat; } }; document.addEventListener('keydown', hotkey); const sessionExpired = () => { if (!account.isLoggedIn) return; account.user = null; account.apiKey = ''; account.isLoggedIn = false; account.loginTime = 0; Cache.remove('user'); importStatus.value = []; importTotal.value = 0; importsError.value = ''; connection.status = 'unknown'; connection.error = ''; tell('登录已失效,请重新使用账号密码登录', 'warning'); }; window.addEventListener('zk-session-expired', sessionExpired); const requestUpdate = () => { openUpdateSettings(); checkUpdates(); }; const automaticUpdate = () => { if (document.visibilityState !== 'hidden') updates.check(); }; let updateStart = 0, updateTimer = 0, importTimer = 0; window.addEventListener('zk-check-update', requestUpdate); panelNotification = (text, type = 'info') => tell(text, type); app.app.showFloat = !app.app.hideFloat && !!app.app.defaultShowFloat; repository.onChange = refreshLocal; Answer.cacheAnswer = (row, oldKey) => { if (['cloud', 'ai'].includes(row?.cacheOrigin) && app.app.examCacheEnabled === false) return false; const saved = repository.save(row, row?.cacheOrigin, oldKey); if (saved) repository.onChange?.(); return saved; }; Answer.getCacheAnswer = async question => { const row = repository.get(question) || findCompatibleCachedQuestion(question, () => repository.list()); return row ? {form: '本地缓存库', answer: cachedQuestionAnswer(row), duration: 0, source: row.source, msg: repository.describe(row)} : {form: '本地缓存库', answer: '', duration: 0, msg: '未找到完整的缓存答案'}; }; // Compatibility methods share the same repository; no second copy is written. Answer.listExamCache = () => repository.list(); Answer.saveExamCache = row => Answer.cacheAnswer({...row, cacheOrigin: /AI/i.test(row.source || '') ? 'ai' : 'personal'}); Answer.getExamCacheAnswer = question => Answer.getCacheAnswer(question); Answer.clearExamCache = () => { repository.clear(); repository.onChange?.(); return true; }; const workflow = installWorkspaceWorkflow({task, account, models, app, repository}); let lastAccountRefresh = 0, profileRequest = null; async function refreshAccount(force = false) { if (!account.isLoggedIn || (!force && (task.start || document.hidden || Date.now()-lastAccountRefresh<15000))) return; const owner = account.apiKey; if (profileRequest?.owner === owner) return profileRequest.promise; lastAccountRefresh = Date.now(); connection.status = 'checking'; connection.error = ''; const pending = (async () => { try { const profile = await workspaceRequest('profile', undefined, 12000); if (!account.isLoggedIn || account.apiKey !== owner) return; if (!profile?.id || !profile.quota || !Number.isFinite(profile.points)) throw workspaceTransportError('profile', 'response'); account.user = engineProfile(profile); account.saveToCache(); connection.status = 'online'; connection.error = ''; } catch (problem) { if (!account.isLoggedIn || account.apiKey !== owner) return; connection.status = 'unavailable'; connection.error = problem.message; } finally { if (profileRequest?.owner === owner) profileRequest = null; } })(); profileRequest = {owner, promise: pending}; return pending; } // The engine also refreshes after login and answering; share one guarded request. account.fetchUserInfo = () => refreshAccount(true); const automaticAccountRefresh = () => refreshAccount(); vue.watch(() => app.page, page => { if (['account', 'config', 'vault', 'search', 'official', 'imports'].includes(view.value)) return; if (page === 'ask') navigate('ask'); else if (page === 'home') navigate('home'); else if (page === 'library') navigate('vault'); else if (page === 'settings') navigate('config'); }); vue.watch(() => task.questionInx, () => vue.nextTick(() => { shellRef.value?.querySelector('.zk-split-main')?.scrollTo({top: 0}); })); window.addEventListener('resize', keepInView); vue.watch(() => app.app.showFloat, () => vue.nextTick(keepInView)); // Defer non-critical boot work so the first panel paint is not blocked. vue.onMounted(() => { vue.nextTick(keepInView); refreshLocal(); vue.watch(() => task.saveQuestionData, refreshLocal, {deep: true}); vue.watch(() => account.isLoggedIn ? account.apiKey : null, token => { importStatus.value = []; importTotal.value = 0; importPage.value = 1; importsError.value = ''; connection.status = 'unknown'; connection.error = ''; if (token) {flushImports(); refreshAccount(true); window.dispatchEvent(new Event('zk-account-changed'));} }, {immediate: true}); account.fetchNotice().then(response => { if (response.success) uiNotice.value = String(response.notice || '').trim(); }); window.addEventListener('focus', automaticAccountRefresh); window.addEventListener('online', automaticAccountRefresh); document.addEventListener('visibilitychange', automaticUpdate); updateStart = setTimeout(automaticUpdate, 2500); updateTimer = setInterval(automaticUpdate, 60000); importTimer = setInterval(() => { if (account.isLoggedIn && Cache.get('zkImportOutboxV3', []).some(x => x.owner === account.user.id)) flushImports(); }, 30000); }); vue.onBeforeUnmount(() => { document.removeEventListener('keydown', hotkey); window.removeEventListener('zk-session-expired', sessionExpired); window.removeEventListener('zk-check-update', requestUpdate); document.removeEventListener('visibilitychange', automaticUpdate); clearTimeout(updateStart); clearInterval(updateTimer); window.removeEventListener('resize', keepInView); window.removeEventListener('focus', automaticAccountRefresh); window.removeEventListener('online', automaticAccountRefresh); releaseDrag?.(); closeConfirm(false); clearTimeout(notificationTimer); clearInterval(importTimer); panelNotification = null; if (repository.onChange === refreshLocal) repository.onChange = null; }); const renderBody = () => { switch (view.value) { case 'home': return renderHome(); case 'official': return renderOfficial(); case 'imports': return renderImportPage(); case 'ask': return renderAsk(); case 'config': return renderConfig(); case 'account': return renderAccount(); case 'vault': return renderVault(); case 'logs': return renderLogs(); case 'search': return renderSearch(); default: return renderHome(); } }; return () => { if (!app.app.showFloat) { const total = task.questionList.length; const done = processed.value; const ratio = total ? done / total : 0; const pct = Math.round(ratio * 100); const active = !!(task.scanning || task.start); const countLabel = total ? `${done}/${total}` : '展开'; const tip = app.app.alertBubble && app.app.alert ? String(app.app.alert) : ''; return h('div', { ref: ballRef, class: 'zk-launcher-wrap', style: {left: `${ballPos.x}px`, top: `${ballPos.y}px`}, onPointerdown: onBallDrag }, [ tip ? h('div', {class: 'zk-launcher-bubble', role: 'status'}, tip) : null, button([ h('span', {class: 'zk-launcher-mark'}, [ brand(32), h('svg', {class: 'zk-launcher-ring', viewBox: '0 0 40 40', 'aria-hidden': 'true'}, [ h('circle', {class: 'zk-launcher-ring-track', cx: 20, cy: 20, r: 18, fill: 'none', stroke: 'currentColor', 'stroke-width': 2.5}), h('circle', {class: 'zk-launcher-ring-value', cx: 20, cy: 20, r: 18, fill: 'none', stroke: 'currentColor', 'stroke-width': 2.5, 'stroke-dasharray': 113.1, 'stroke-dashoffset': 113.1 * (1 - ratio)}) ]) ]), h('span', {class: 'zk-launcher-meta'}, [ h('span', {class: 'zk-launcher-title'}, [h('strong', '知库'), h('small', countLabel)]), h('span', { class: ['zk-launcher-bar', {'is-indeterminate': task.scanning && !total}], role: 'progressbar', 'aria-valuemin': 0, 'aria-valuemax': total || 100, 'aria-valuenow': total ? done : undefined, 'aria-valuetext': total ? `已完成 ${done} / ${total}` : '等待识别题目', 'aria-label': '答题进度' }, [h('i', {style: total ? {width: `${pct}%`} : null})]) ]) ], () => { if (dragMoved) { dragMoved = false; return; } app.app.showFloat = true; }, { class: ['zk-launcher', {'is-active': active, 'is-done': total > 0 && done >= total}], title: tip || (total ? `已完成 ${done}/${total}(${pct}%)` : '展开知库学习工作台'), 'aria-label': tip || (total ? `展开知库,已完成 ${done}/${total}` : '展开知库学习工作台') }) ]); } const isAsk = view.value === 'ask'; const body = renderBody(); const err = error.value ? h('p', {class: 'zk-error', role: 'alert'}, error.value) : null; return h('aside', { ref: shellRef, class: ['zk-shell', isAsk ? 'is-ask' : 'is-page', {'is-focus': focusMode.value, 'is-compact': density.value === 'compact'}], 'data-theme': appearance.value, role: 'complementary', 'aria-label': '知库学习工作台', style: {left: `${shellPos.x}px`, top: `${shellPos.y}px`, right: 'auto', bottom: 'auto'}, onPointerdown: onShellDrag }, [ h('header', {class: 'zk-header', 'data-zk-drag': ''}, [ h('span', {class: 'zk-emblem'}, brand(40)), h('div', {class: 'zk-brand', 'data-zk-drag': ''}, [ h('strong', ['知库', h('span', '学习工作空间')]), h('small', 'Z H I K U W O R K S P A C E') ]), h('div', {class: 'zk-header-status'}, [h('i', {class: account.isLoggedIn && connection.status === 'online' ? 'is-online' : ''}), !account.isLoggedIn ? '本地工作空间' : connection.status === 'online' ? '云端已连接' : connection.status === 'unavailable' ? '连接待恢复' : '正在检查连接']), iconButton(appearance.value === 'dark' ? 'sun' : 'moon', appearance.value === 'dark' ? '切换浅色主题' : '切换深色主题', () => setAppearance(appearance.value === 'dark' ? 'light' : 'dark')), iconButton('focus', focusMode.value ? '退出专注模式' : '专注模式', () => focusMode.value = !focusMode.value, {'aria-pressed': focusMode.value}), iconButton('minus', '最小化工作台', () => { ballPos.x = shellPos.x; ballPos.y = shellPos.y; Cache.set('zkBallPos', {x: ballPos.x, y: ballPos.y}); app.app.showFloat = false; }) ]), updateState.value.showBanner ? h('div', {class: 'zk-update-banner', role: 'status'}, [ h('span', [h('strong', `新版本 v${updateState.value.release.version}`), h('small', '可直接在线更新,无需登录')]), h('a', {class: 'zk-update-install', href: updateState.value.downloadUrl, target: '_blank', rel: 'noopener noreferrer'}, '立即更新'), button('查看更新', openUpdateSettings), iconButton('close', '今天稍后提醒', updates.dismiss) ]) : null, h('div', {class: 'zk-frame'}, [ h('nav', {class: 'zk-sidebar', 'aria-label': '工作台导航'}, [ h('div', {class: 'zk-nav-groups'}, navigation.map(group => h('div', {class: 'zk-nav-group'}, [ h('span', {class: 'zk-nav-caption'}, group.label), ...group.items.map(([id, title, glyph]) => button([ h('span', {class: ['zk-nav-glyph', 'zk-glyph-' + glyph]}, icon(glyph, 19)), h('span', title), id === 'ask' && task.questionList.length ? h('small', String(task.questionList.length)) : null, id === 'vault' && library.value.length ? h('small', String(library.value.length)) : null ], () => navigate(id), { class: ['zk-nav-item', {'is-active': view.value === id}], 'aria-current': view.value === id ? 'page' : undefined, 'aria-label': title, title })) ]) )), h('div', {class: 'zk-nav-bottom'}, [ button([ h('span', {class: ['zk-mini-avatar', account.isLoggedIn ? 'is-user' : '']}, account.isLoggedIn ? (account.nickname || '知').slice(0, 1) : icon('user', 16)), h('span', {class: 'zk-account-nav-meta'}, [ h('strong', account.isLoggedIn ? account.nickname : '连接与账户'), account.isLoggedIn ? h('span', {class: 'zk-account-nav-stats'}, [ h('span', [h('b', String(account.score)), '积分']), h('span', [h('b', String(account.user?.contributions || 0)), '贡献']) ]) : h('small', '登录后同步账户') ]), h('span', {class: 'zk-account-nav-go', 'aria-hidden': 'true'}, icon('chevron', 12)) ], () => navigate('account'), { class: ['zk-account-nav', {'is-active': view.value === 'account', 'is-guest': !account.isLoggedIn}], 'aria-label': account.isLoggedIn ? `连接与账户,${account.nickname},积分 ${account.score},贡献 ${account.user?.contributions || 0}` : '连接与账户' }), button(`v${scriptVersion.value} · ${updateState.value.hasNew ? '发现新版' : '检查更新'}`, requestUpdate, {class: 'zk-nav-version', 'aria-label': '检查脚本更新', disabled: updateState.value.checking}) ]) ]), h('main', {class: isAsk ? 'zk-body' : 'zk-scroll', key: view.value}, [body, err]) ]), snackbar.value ? h('div', {class: ['zk-snackbar', `is-${snackbar.value.type || 'info'}`], role: 'status'}, snackbar.value.text) : null, confirmBox.value ? h('div', {class: 'zk-confirm'}, [ h('div', {class: 'zk-confirm-card', role: 'dialog', 'aria-modal': 'true', 'aria-label': confirmBox.value.title}, [ h('h3', confirmBox.value.title), h('p', confirmBox.value.body), actions([ button(confirmBox.value.cancel, () => closeConfirm(false)), button(confirmBox.value.ok, () => closeConfirm(true), {class: confirmBox.value.danger ? 'zk-danger zk-main' : 'zk-main'}) ]) ]) ]) : null ]); }; } }); const Jm = ":host{all:initial;color-scheme:light}\n.zk-connection-banner.is-unavailable{background:var(--warn-bg);color:var(--warn)}.zk-connection-banner p{overflow-wrap:anywhere}.zk-connection-retry{flex:none}.zk-section-error{color:var(--warn);background:var(--warn-bg);padding:10px;border-radius:8px;margin:8px 0;overflow-wrap:anywhere}.zk-section-error button{margin-top:8px}\n.zk-origin-tags{display:flex;flex-wrap:wrap;gap:5px;margin:8px 0}.zk-origin-tags span{font-size:10px;line-height:1.5;padding:2px 7px;border-radius:5px;background:var(--nav);color:var(--muted)}\n.zk-library-filters{display:flex;flex-direction:column;gap:12px}.zk-shell .zk-library-filters .zk-field{margin:0}.zk-library-filters .zk-form-grid{gap:12px}.zk-library-filters .zk-chips{padding-top:2px}\n.zk-shell{--ink:#282b3f;--ink-2:#525970;--muted:#7d849b;--faint:#9299ae;--paper:#f7f8fc;--surface:#fff;--nav:#f3f5fa;--line:#e5e8f0;--line-2:#eef0f6;--accent:#6956df;--accent-2:#5541c6;--soft:#eeebfc;--soft-2:#f7f5ff;--ok:#278168;--ok-bg:#edf8f2;--bad:#bd625e;--bad-bg:#fbefee;--warn:#ac792e;--warn-bg:#fff7e7;--mark-done:#1b6b93;--mark-done-bg:#e7f3fa;--mark-done-line:#9ec9de;--mark-todo:#6b7280;--mark-todo-bg:#f3f4f6;--mark-todo-line:#d1d5db;--mark-none:#c2410c;--mark-none-bg:#fff4ed;--mark-none-line:#fdba74;--mark-wait:#6d28d9;--mark-wait-bg:#f3e8ff;--mark-wait-line:#d8b4fe;position:fixed;z-index:2147483646;width:min(900px,calc(100vw - 32px));height:min(780px,calc(100dvh - 48px));display:flex;flex-direction:column;overflow:hidden;text-align:left;color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:18px;box-shadow:0 24px 80px #1b20402b,0 3px 15px #1b20400d;font:13px/1.55 -apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;-webkit-font-smoothing:antialiased;isolation:isolate;color-scheme:light}\n.zk-shell[data-theme=dark]{--ink:#e4e6f1;--ink-2:#b6bbd0;--muted:#939ab4;--faint:#7d869e;--paper:#191c29;--surface:#212534;--nav:#1d202e;--line:#33394c;--line-2:#2b3043;--accent:#ad9cff;--accent-2:#c1b3ff;--soft:#34304e;--soft-2:#29263d;--ok:#77cfa8;--ok-bg:#223b35;--bad:#ed9c94;--bad-bg:#412c33;--warn:#e2bc76;--warn-bg:#3f3629;--mark-done:#7cc4e8;--mark-done-bg:#1c3344;--mark-done-line:#3d6d8a;--mark-todo:#9ca3af;--mark-todo-bg:#2a2f3d;--mark-todo-line:#4b5563;--mark-none:#fb923c;--mark-none-bg:#3f2a1d;--mark-none-line:#9a5b2f;--mark-wait:#c4b5fd;--mark-wait-bg:#342656;--mark-wait-line:#6d4fb0;box-shadow:0 24px 80px #0006;color-scheme:dark}\n.zk-shell *,.zk-shell *::before,.zk-shell *::after,.zk-launcher{box-sizing:border-box}\n.zk-shell h2,.zk-shell h3,.zk-shell p{margin:0}.zk-shell a{color:var(--accent);text-decoration:none}.zk-shell a:hover{text-decoration:underline}.zk-icon{display:block;flex:none;vertical-align:middle}\n.zk-shell button,.zk-shell input,.zk-shell select,.zk-shell textarea{font:inherit;color:inherit}\n.zk-shell button{display:inline-flex;align-items:center;justify-content:center;gap:7px;min-height:34px;padding:7px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--ink-2);cursor:pointer;font-weight:500;line-height:1.35;transition:background .15s,border-color .15s,color .15s;touch-action:manipulation}\n.zk-shell button:hover{background:var(--nav);border-color:#b9b7d5;color:var(--ink)}.zk-shell button:disabled{opacity:.42;cursor:not-allowed}\n.zk-shell button:focus-visible,.zk-shell a:focus-visible,.zk-shell summary:focus-visible{outline:3px solid var(--accent);outline-offset:3px}\n.zk-shell button.zk-main{background:var(--accent);border-color:var(--accent);color:#fff;box-shadow:0 2px 3px #5541c614}.zk-shell button.zk-main:hover{background:var(--accent-2);border-color:var(--accent-2)}\n.zk-shell[data-theme=dark] button.zk-main{background:#8773ed;border-color:#8773ed;color:white}\n.zk-shell button.zk-ghost{background:transparent;border-color:transparent;color:var(--muted)}.zk-shell button.zk-ghost:hover{color:var(--accent);background:var(--soft)}\n.zk-shell button.zk-link{min-height:24px;border:0;background:none;padding:2px 0;font-size:12px;color:var(--accent)}.zk-shell button.zk-danger{color:var(--bad)}.zk-shell button.zk-danger.zk-main{background:var(--bad);border-color:var(--bad);color:#fff}\n.zk-shell button.zk-icon-btn{height:32px;width:32px;min-height:32px;flex:none;padding:0;border-color:transparent;background:transparent;border-radius:8px;color:var(--muted)}.zk-shell button.zk-icon-btn:hover,.zk-shell button.zk-icon-btn[aria-pressed=true]{background:var(--soft);color:var(--accent)}.zk-shell button.zk-full{width:100%;min-height:40px}\n.zk-header{height:65px;min-height:65px;display:flex;align-items:center;gap:10px;padding:0 18px;background:var(--surface);border-bottom:1px solid var(--line);cursor:grab;touch-action:none;user-select:none}.zk-header:active{cursor:grabbing}\n.zk-emblem{display:grid;place-items:center;width:36px;height:36px;border-radius:10px;background:var(--accent);color:white;flex:none}.zk-brand{flex:1;min-width:0;line-height:1.2}.zk-brand strong{display:flex;align-items:center;gap:10px;font-size:20px;letter-spacing:-.04em;font-weight:750}.zk-brand strong span{font-size:12px;font-weight:450;color:var(--muted);letter-spacing:0;padding-left:10px;border-left:1px solid var(--line)}.zk-brand small{display:block;font-size:8px;color:var(--faint);margin-top:5px;letter-spacing:.04em}\n.zk-header-status{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--muted);margin-right:12px;white-space:nowrap}.zk-header-status i,.zk-task-state i{width:6px;height:6px;border-radius:50%;background:var(--faint)}.zk-header-status .is-online{background:var(--ok)}\n.zk-frame{display:grid;grid-template-columns:156px minmax(0,1fr);flex:1;min-height:0}.zk-sidebar{display:flex;flex-direction:column;min-height:0;background:var(--nav);border-right:1px solid var(--line);padding:16px 10px 10px;overflow:auto;scrollbar-width:thin}.zk-nav-groups{display:flex;flex-direction:column;gap:24px}.zk-nav-group{display:flex;flex-direction:column;gap:4px}.zk-nav-caption{padding:0 12px 7px;font-size:10px;letter-spacing:.07em;color:var(--faint);font-weight:550}\n.zk-shell button.zk-nav-item{justify-content:flex-start;gap:10px;width:100%;padding:10px;border:0;background:none;font-size:12px;color:var(--ink-2);border-radius:8px;white-space:nowrap}.zk-nav-item small{margin-left:auto;font-size:10px;font-weight:600;color:var(--faint);font-variant-numeric:tabular-nums}.zk-shell button.zk-nav-item:hover{background:var(--line-2)}.zk-shell button.zk-nav-item.is-active{color:var(--accent);background:var(--soft);font-weight:650}.zk-nav-item.is-active small{color:var(--accent)}\n.zk-nav-bottom{margin-top:auto;padding-top:14px;display:flex;flex-direction:column;gap:8px}.zk-shell button.zk-account-nav{justify-content:flex-start;align-items:center;text-align:left;width:100%;gap:9px;min-height:0;padding:8px;border:0;border-radius:12px;background:transparent;box-shadow:none}.zk-shell button.zk-account-nav:hover{background:var(--line-2);color:var(--ink)}.zk-shell button.zk-account-nav.is-active{background:var(--soft)}.zk-account-nav-meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}.zk-account-nav strong{display:block;font-size:12px;font-weight:650;letter-spacing:-.02em;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.zk-account-nav small{display:block;font-size:9px;color:var(--muted);line-height:1.35}.zk-account-nav-stats{display:flex;flex-wrap:wrap;gap:4px}.zk-account-nav-stats>span{display:inline-flex;align-items:baseline;gap:2px;padding:2px 6px;border-radius:999px;background:var(--surface);font-size:9px;color:var(--muted);line-height:1.35;white-space:nowrap}.zk-account-nav.is-active .zk-account-nav-stats>span{background:var(--surface)}.zk-account-nav-stats b{font-size:10px;font-weight:650;color:var(--ink);font-variant-numeric:tabular-nums}.zk-account-nav-go{display:grid;place-items:center;flex:none;color:var(--faint);opacity:.75}.zk-mini-avatar{display:grid;place-items:center;width:34px;height:34px;flex:none;border:0;border-radius:11px;background:linear-gradient(165deg,#f0edfc,#e4e0f8);font-size:14px;font-weight:700;color:var(--accent);text-transform:uppercase}.zk-mini-avatar.is-user{background:var(--accent);color:#fff;box-shadow:0 4px 10px #6956df2e}.zk-shell[data-theme=dark] .zk-mini-avatar{background:var(--soft);color:var(--accent)}.zk-shell[data-theme=dark] .zk-mini-avatar.is-user{background:var(--accent);color:#1b1830}.zk-nav-version{display:block;text-align:center;color:var(--faint);font-size:9px;padding-top:10px;border-top:1px solid var(--line);margin-top:0}\n.zk-body,.zk-scroll{padding:22px 22px 0;display:flex;flex-direction:column;min-height:0;min-width:0;background:var(--paper);overscroll-behavior:contain}.zk-body{overflow:hidden}.zk-scroll{overflow:auto;padding-bottom:24px;scrollbar-width:thin;scrollbar-color:var(--line) transparent}.zk-page,.zk-home-page{display:flex;flex-direction:column;gap:16px;flex:none;min-width:0}.zk-home-page{gap:12px}.zk-home-page .zk-page-heading h2{font-size:20px}.zk-home-page .zk-page-heading p{margin-top:4px}.zk-home-page .zk-eyebrow{margin-bottom:4px}.zk-ask{display:flex;flex-direction:column;gap:14px;min-height:0;flex:1}\n.zk-heading-row{display:flex;align-items:center;justify-content:space-between;gap:12px;flex:none}.zk-page-heading{min-width:0}.zk-eyebrow{display:block;font-size:10px;letter-spacing:.045em;color:var(--faint);font-weight:550;margin-bottom:6px}.zk-page-heading h2{font-size:23px;font-weight:720;letter-spacing:-.045em;line-height:1.3;color:var(--ink)}.zk-page-heading p{font-size:11px;line-height:1.6;color:var(--muted);margin-top:7px;overflow-wrap:anywhere}\n.zk-summary{display:grid;grid-template-columns:1.45fr repeat(3,1fr);border:1px solid var(--line);border-radius:12px;background:var(--surface);padding:16px 8px;flex:none}.zk-summary-main{padding:0 15px;display:flex;flex-direction:column;justify-content:center;gap:8px}.zk-summary-main>div:first-child{display:flex;align-items:center;justify-content:space-between;gap:10px}.zk-summary-main span{font-size:10px;color:var(--muted);white-space:nowrap}.zk-summary-main strong{font-size:23px;line-height:1;font-weight:650;letter-spacing:-1px;font-variant-numeric:tabular-nums}.zk-summary-main small{font-size:12px;font-weight:450;letter-spacing:0;color:var(--faint)}.zk-progress{height:4px;border-radius:5px;background:var(--line-2);overflow:hidden}.zk-progress i{display:block;height:100%;border-radius:5px;background:var(--accent);transition:width .25s}\n.zk-shell button.zk-summary-stat{border:0;border-left:1px solid var(--line-2);border-radius:0;flex-direction:column;gap:5px;padding:0;background:none}.zk-summary-stat strong{font-size:23px;line-height:1;font-weight:600;letter-spacing:-.03em;font-variant-numeric:tabular-nums;color:var(--ink)}.zk-summary-stat span{display:flex;align-items:center;gap:5px;font-size:10px;color:var(--muted)}.zk-summary-stat i,.zk-legend i{display:inline-block;width:8px;height:8px;flex:none;background:var(--faint)}.zk-summary-stat .done,.zk-legend i.done{background:var(--mark-done);border-radius:50%}.zk-summary-stat .todo,.zk-legend i.todo{background:transparent;border:1.5px solid var(--mark-todo);border-radius:50%;box-sizing:border-box}.zk-summary-stat .none,.zk-legend i.none{background:var(--mark-none);border-radius:2px}.zk-summary-stat .wait,.zk-legend i.wait{background:var(--mark-wait);clip-path:polygon(50% 8%,100% 92%,0 92%);border-radius:0}.zk-shell button.zk-summary-stat.is-on{background:var(--soft);border-radius:6px}\n.zk-finish-summary{display:flex;flex-direction:column;gap:8px;padding:12px 14px;border:1px solid color-mix(in srgb,var(--accent) 14%,var(--line));border-radius:10px;background:var(--soft-2);flex:none}.zk-finish-summary-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px}.zk-finish-summary-head strong{font-size:12px;font-weight:650}.zk-finish-summary-head .zk-muted{font-size:10px;margin:0;white-space:normal}.zk-finish-tags{display:flex;flex-wrap:wrap;gap:6px}.zk-filter-bar{display:flex;align-items:center;justify-content:space-between;gap:10px;flex:none}.zk-chips{display:flex;flex-wrap:wrap;gap:5px}.zk-shell .zk-chips button{min-height:28px;padding:5px 10px;font-size:11px;border-radius:6px;background:transparent;border-color:transparent;color:var(--muted)}.zk-shell .zk-chips button:hover{background:var(--surface);color:var(--ink)}.zk-shell .zk-chips button.is-on{background:var(--surface);border-color:var(--line);box-shadow:0 1px 2px #20204006;color:var(--accent);font-weight:600}.zk-task-state{display:flex;align-items:center;gap:6px;color:var(--muted);font-size:10px;white-space:nowrap}.zk-task-state.is-running{color:var(--accent)}.zk-task-state.is-running i{background:var(--accent);animation:zk-pulse 1.4s ease-in-out infinite}\n.zk-split{display:grid;grid-template-columns:minmax(0,1fr) 145px;gap:14px;flex:1;min-height:0}.zk-split-main,.zk-split-side{min-height:0;min-width:0;border:1px solid var(--line);border-radius:12px;background:var(--surface);overflow:auto;scrollbar-width:thin;scrollbar-color:var(--line) transparent}.zk-split-main{padding:20px}.zk-split-side{padding:13px 11px}.zk-rail{display:flex;flex-direction:column;gap:14px;min-height:100%}.zk-rail-heading{display:flex;align-items:center;justify-content:space-between;gap:6px}.zk-rail-heading strong{font-size:11px;font-weight:600}.zk-rail-heading>span{font-size:10px;color:var(--faint)}.zk-rail-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;align-content:start}\n.zk-shell button.zk-num-btn{aspect-ratio:1;min-height:27px;min-width:0;width:100%;border-radius:6px;padding:0;font-size:10px;font-variant-numeric:tabular-nums;color:var(--mark-todo);background:var(--mark-todo-bg);border-color:var(--mark-todo-line)}.zk-shell button.zk-num-btn.done{background:var(--mark-done-bg);border-color:var(--mark-done-line);color:var(--mark-done)}.zk-shell button.zk-num-btn.todo{background:var(--mark-todo-bg);border-color:var(--mark-todo-line);color:var(--mark-todo)}.zk-shell button.zk-num-btn.none{background:var(--mark-none-bg);border-color:var(--mark-none-line);color:var(--mark-none)}.zk-shell button.zk-num-btn.wait{background:var(--mark-wait-bg);border-color:var(--mark-wait-line);color:var(--mark-wait)}.zk-shell button.zk-num-btn.run{background:var(--soft);color:var(--accent);border-color:var(--soft)}.zk-shell button.zk-num-btn.is-current{border-color:var(--accent);color:var(--accent);box-shadow:0 0 0 2px var(--soft);background:var(--surface);font-weight:700}.zk-legend{display:grid;grid-template-columns:1fr 1fr;gap:8px 4px;padding-top:12px;border-top:1px solid var(--line-2);margin-top:auto}.zk-legend span{display:flex;gap:6px;align-items:center;font-size:9px;color:var(--muted)}.zk-rail-note{display:flex;align-items:center;gap:5px;font-size:9px;color:var(--faint)}\n.zk-detail-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:16px}.zk-num{font-size:9px;letter-spacing:.07em;color:var(--faint);font-weight:600}.zk-kind{display:inline-flex;align-items:center;gap:5px;font-size:10px;border-radius:5px;padding:3px 7px;line-height:1.5;background:var(--soft);color:var(--accent);font-weight:500}.zk-card-status{margin-left:auto;font-size:10px;display:inline-flex;align-items:center;gap:5px;color:var(--muted)}.zk-card-status i{width:5px;height:5px;border-radius:50%;background:currentColor}.zk-card-status.done{color:var(--mark-done)}.zk-card-status.none{color:var(--mark-none)}.zk-card-status.wait{color:var(--mark-wait)}.zk-card-status.todo{color:var(--mark-todo)}.zk-card-status.run{color:var(--accent)}.zk-loading-text{width:100%;font-size:10px;color:var(--accent)}\n.zk-stem{font-size:14px;line-height:1.85;font-weight:500;white-space:pre-wrap;overflow-wrap:anywhere;margin-bottom:16px;color:var(--ink);user-select:text}.zk-stem img,.zk-choice img,.zk-answer img,.zk-markdown img{max-width:100%;height:auto;vertical-align:middle;border-radius:4px}.zk-options{display:flex;flex-direction:column;gap:8px}.zk-choice{display:flex;align-items:flex-start;gap:12px;padding:11px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--ink-2);font-size:12px;line-height:1.65;overflow-wrap:anywhere;user-select:text}.zk-choice-key{display:grid;place-items:center;width:22px;height:22px;border-radius:5px;background:var(--nav);color:var(--muted);font-size:10px;font-weight:600;flex:none}.zk-choice>div{min-width:0;padding-top:1px}.zk-choice.is-hit{background:var(--ok-bg);border-color:color-mix(in srgb,var(--ok) 25%,transparent);color:var(--ok)}.zk-choice.is-hit .zk-choice-key{background:var(--ok);color:var(--surface)}\n.zk-answer-block{margin-top:20px;padding:13px 14px;border-radius:8px;background:var(--ok-bg)}.zk-answer-label{display:flex;align-items:center;gap:6px;color:var(--ok);font-size:10px;font-weight:600}.zk-answer-label .zk-icon-btn{margin-left:auto;margin-top:-6px;margin-bottom:-6px}.zk-answer{padding:11px 13px;border-radius:8px;background:var(--ok-bg);color:var(--ok);font-size:12px;line-height:1.75;white-space:pre-wrap;overflow-wrap:anywhere;user-select:text}.zk-answer-block .zk-answer{padding:7px 0 0}.zk-answer-excerpt{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n.zk-details{margin-top:18px;color:var(--ink-2);font-size:12px;overflow-wrap:anywhere}.zk-details summary{display:flex;align-items:center;gap:6px;cursor:pointer;font-size:11px;color:var(--muted);list-style:none;min-height:26px}.zk-details summary::before{content:'›';font-size:16px;transition:transform .15s;line-height:1}.zk-details[open]>summary::before{transform:rotate(90deg)}.zk-details summary>span{margin-left:auto;color:var(--faint);font-size:10px}.zk-sources{padding-top:12px;border-top:1px solid var(--line-2)}.zk-source-row{padding:10px 0;border-bottom:1px solid var(--line-2);font-size:11px;overflow-wrap:anywhere}.zk-source-meta{display:flex;align-items:center;gap:8px;margin-bottom:4px}.zk-source-meta small{margin-left:auto;color:var(--faint);font-size:10px}.zk-source-row.is-hit{color:var(--ok)}\n.zk-actions{display:flex;align-items:center;flex-wrap:wrap;gap:8px}.zk-detail>.zk-actions{padding-top:15px;margin-top:16px;border-top:1px solid var(--line-2);gap:2px}.zk-detail>.zk-actions>button:last-child{margin-left:auto}.zk-preview{margin-top:16px;padding:14px;border:1px solid color-mix(in srgb,var(--warn) 30%,transparent);border-radius:9px;background:var(--warn-bg);color:var(--warn)}.zk-preview b{display:flex;gap:6px;align-items:center;font-size:12px}.zk-preview p{margin:10px 0;white-space:pre-wrap;font-size:13px;overflow-wrap:anywhere}\n.zk-task-footer{display:flex;justify-content:space-between;align-items:center;gap:10px;background:var(--surface);border-top:1px solid var(--line);flex:none;margin:0 -22px;padding:12px 22px}.zk-pagination{display:flex;align-items:center;gap:5px;color:var(--muted);font-size:10px;white-space:nowrap;font-variant-numeric:tabular-nums}.zk-previous .zk-icon{transform:rotate(180deg)}.zk-footer-actions{display:flex;align-items:center;gap:7px}.zk-footer-actions .zk-main{min-height:38px;padding:8px 17px;font-size:12px}\n.zk-section-heading{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:4px}.zk-section-heading h3{font-size:13px;font-weight:650;color:var(--ink)}.zk-section-heading>span{font-size:10px;color:var(--faint)}.zk-card{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:18px;min-width:0}.zk-card.is-on{border-color:var(--accent)}.zk-card .zk-stem{margin-top:10px;margin-bottom:12px}.zk-library-item .zk-detail-head{margin-bottom:4px}.zk-library-item .zk-detail-head .zk-link{margin-left:auto}.zk-result-count{font-size:10px;color:var(--muted);padding:0 2px}\n.zk-field{display:flex;flex-direction:column;gap:7px;min-width:0;font-size:11px;font-weight:500;color:var(--ink-2);margin:14px 0}.zk-field:first-child{margin-top:0}.zk-shell input,.zk-shell textarea,.zk-shell select{width:100%;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--ink);padding:10px 12px;outline:none;line-height:1.6;min-width:0;font-size:12px}.zk-shell input:read-only{background:var(--paper);color:var(--muted)}.zk-shell input::placeholder,.zk-shell textarea::placeholder{color:var(--faint);font-weight:400}.zk-shell input:focus,.zk-shell textarea:focus,.zk-shell select:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--soft)}.zk-shell textarea{resize:vertical;min-height:86px}\n.zk-switch{display:flex;flex-direction:row-reverse;align-items:center;justify-content:space-between;gap:20px;padding:15px 0;border-bottom:1px solid var(--line-2);cursor:pointer;color:var(--ink-2);font-size:12px}.zk-switch span{flex:1}.zk-switch input{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none}.zk-switch i{display:block;flex:none;width:32px;height:19px;border-radius:20px;background:var(--line);transition:background .15s}.zk-switch i::after{content:'';display:block;width:15px;height:15px;border-radius:50%;margin:2px;background:white;box-shadow:0 1px 3px #0002;transition:transform .15s}.zk-switch input:checked+i{background:var(--accent)}.zk-switch input:checked+i::after{transform:translateX(13px)}.zk-switch input:focus-visible+i{outline:3px solid var(--accent);outline-offset:3px}\n.zk-setting-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:15px 0;border-bottom:1px solid var(--line-2);font-size:12px;color:var(--ink-2)}.zk-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}.zk-form-grid .zk-field{margin:0 0 14px}.zk-form{display:flex;flex-direction:column}.zk-form .zk-actions{margin-top:3px}.zk-config{display:flex;flex-direction:column;gap:16px}.zk-config-nav{display:flex;gap:4px;border-bottom:1px solid var(--line)}.zk-shell .zk-config-nav button{border:0;border-radius:0;position:relative;background:none;color:var(--muted);padding:10px 15px;font-size:12px}.zk-shell .zk-config-nav button.is-on{color:var(--accent);font-weight:650}.zk-config-nav button.is-on::after{content:'';position:absolute;height:2px;background:var(--accent);bottom:-1px;left:12px;right:12px;border-radius:2px}.zk-config-body .zk-muted{margin:12px 0}\n.zk-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;min-height:220px;text-align:center;padding:28px 16px;color:var(--muted)}.zk-empty-icon{display:grid;place-items:center;background:var(--nav);color:var(--faint);border-radius:16px;width:58px;height:58px;margin-bottom:5px}.zk-empty b{font-size:14px;font-weight:600;color:var(--ink-2)}.zk-empty p{max-width:270px;font-size:11px;line-height:1.8}.zk-empty button{margin-top:7px}.zk-muted{color:var(--muted);font-size:11px;line-height:1.7;white-space:pre-wrap;overflow-wrap:anywhere}.zk-error{border:1px solid color-mix(in srgb,var(--bad) 25%,transparent);padding:10px 12px;border-radius:8px;background:var(--bad-bg);color:var(--bad);font-size:11px;white-space:pre-wrap;flex:none;overflow-wrap:anywhere}.zk-body>.zk-error{margin-bottom:10px}\n.zk-info-line{display:flex;align-items:flex-start;gap:9px;border:1px solid var(--line);padding:11px 13px;border-radius:9px;background:var(--surface);font-size:11px;color:var(--muted);line-height:1.8}.zk-info-line .zk-icon{margin-top:2px;color:var(--accent)}.zk-notice{display:flex;align-items:flex-start;gap:12px;padding:12px 14px;border-radius:12px;border:1px solid color-mix(in srgb,var(--accent) 14%,var(--line));background:var(--soft-2)}.zk-notice-mark{display:grid;place-items:center;width:34px;height:34px;border-radius:10px;background:color-mix(in srgb,var(--accent) 12%,var(--surface));color:var(--accent);flex:none}.zk-notice-body{flex:1;min-width:0;padding-top:0}.zk-notice-label{display:block;font-size:10px;font-weight:650;letter-spacing:.08em;color:var(--accent);margin-bottom:4px}.zk-notice-content{font-size:12px;line-height:1.65;color:var(--ink);overflow-wrap:anywhere}.zk-notice-content :is(h1,h2,h3){margin:0 0 6px;font-size:14px;font-weight:650;color:var(--ink);line-height:1.45}.zk-notice-content p{margin:0 0 6px}.zk-notice-content ul,.zk-notice-content ol{margin:4px 0 6px;padding-left:1.2em}.zk-notice-content li{margin:2px 0}.zk-notice-content a{color:var(--accent);font-weight:600;text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--accent) 35%,transparent)}.zk-notice-content a:hover{border-bottom-color:var(--accent)}.zk-notice-content code{font-size:11px;padding:1px 5px;border-radius:5px;background:var(--nav);color:var(--ink-2)}.zk-notice-content strong{color:var(--ink);font-weight:650}.zk-badge{display:inline-flex;align-items:center;justify-content:center;padding:4px 8px;border:1px solid var(--line);border-radius:6px;background:var(--surface);color:var(--muted);font-size:10px;white-space:nowrap}\n.zk-home-hero{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:16px 18px;border:1px solid color-mix(in srgb,var(--accent) 12%,var(--line));border-radius:12px;background:var(--soft-2);overflow:hidden}.zk-home-hero .zk-eyebrow{margin-bottom:4px}.zk-home-hero h3{font-size:18px;line-height:1.4;letter-spacing:-.03em;font-weight:650;max-width:320px;margin:4px 0}.zk-home-hero p{font-size:11px;color:var(--muted);margin-bottom:10px;max-width:320px}.zk-home-hero .zk-main{min-height:32px;padding:6px 12px;font-size:12px}.zk-hero-art{width:92px;min-width:80px;position:relative;display:grid;place-items:center;flex:none}.zk-art-book{display:grid;place-items:center;width:68px;height:82px;border:1px solid color-mix(in srgb,var(--accent) 25%,transparent);background:var(--surface);border-radius:12px;transform:rotate(-8deg);box-shadow:7px 8px 0 var(--soft);color:var(--accent)}.zk-art-book .zk-icon{width:28px;height:28px}.zk-art-spark{position:absolute;right:0;top:0;color:var(--accent)}.zk-art-spark .zk-icon{width:16px;height:16px}.zk-art-check{position:absolute;right:0;bottom:8px;background:var(--ok-bg);color:var(--ok);padding:6px;border:3px solid var(--soft-2);border-radius:50%}.zk-art-check .zk-icon{width:12px;height:12px}\n.zk-overview-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.zk-overview-stats>div{display:grid;grid-template-columns:1fr auto;gap:6px;padding:12px;border:1px solid var(--line);border-radius:10px;background:var(--surface)}.zk-overview-stats .zk-icon{grid-row:span 2;align-self:center;color:var(--faint)}.zk-overview-stats strong{font-size:20px;font-weight:600;text-align:right;line-height:1;font-variant-numeric:tabular-nums}.zk-overview-stats span{font-size:10px;color:var(--muted)}.zk-home-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}.zk-shell .zk-home-grid button{justify-content:flex-start;text-align:left;padding:12px;gap:10px;border-radius:10px;min-height:0}.zk-home-grid button>.zk-icon{margin-left:auto;color:var(--faint)}.zk-tile-icon{display:grid;place-items:center;width:32px;height:32px;border-radius:9px;background:var(--soft-2);color:var(--accent);flex:none}.zk-tile-label{min-width:0;flex:1}.zk-tile-label strong{display:block;font-size:12px;font-weight:600;color:var(--ink)}.zk-tile-label small{display:block;font-size:9px;color:var(--faint);margin-top:4px;line-height:1.45;font-weight:400}.zk-home-note{display:flex;align-items:center;gap:6px;font-size:10px;color:var(--faint);padding-top:0}\n.zk-connection-banner{display:flex;align-items:center;gap:14px;border-radius:12px;padding:20px;background:var(--soft);color:var(--accent)}.zk-connection-banner>div{flex:1;min-width:0}.zk-connection-banner strong{font-size:15px;font-weight:650}.zk-connection-banner p{font-size:11px;margin-top:5px;color:var(--muted)}.zk-connection-icon{display:grid;place-items:center;width:44px;height:44px;border-radius:13px;background:var(--surface);flex:none}.zk-connection-banner.is-online{background:var(--ok-bg);color:var(--ok)}.zk-account-page{gap:16px}.zk-account-stack{display:flex;flex-direction:column;gap:14px}.zk-account-card{padding:22px}.zk-account-card form{max-width:430px;margin:0 auto 20px}.zk-account-card .zk-chips{margin-bottom:20px}.zk-account-card .zk-chips button.is-on{background:var(--soft);color:var(--accent);border-color:transparent}.zk-account-space-link{margin-top:4px}.zk-agree{display:flex;align-items:flex-start;gap:8px;margin:0 0 14px;font-size:11px;line-height:1.7;color:var(--muted);cursor:pointer}.zk-agree input{margin-top:3px;flex:none}.zk-agree .zk-text-link{font-size:11px}.zk-user-card{display:flex;align-items:center;gap:14px}.zk-user-meta{min-width:0;flex:1;display:flex;flex-direction:column;gap:6px}.zk-user-card strong{font-size:18px;font-weight:680;letter-spacing:-.03em}.zk-avatar{display:grid;place-items:center;width:48px;height:48px;flex:none;background:var(--accent);color:#fff;border-radius:14px;font-size:20px;font-weight:700;text-transform:uppercase;box-shadow:0 6px 14px #6956df28}.zk-account-sync{display:inline-flex;align-items:center;gap:6px;width:fit-content;padding:3px 8px;border-radius:999px;font-size:10px;line-height:1.35;background:var(--nav);color:var(--muted)}.zk-account-sync::before{content:\"\";width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}.zk-account-sync.is-online{background:var(--ok-bg);color:var(--ok)}.zk-account-sync.is-checking{background:var(--soft);color:var(--accent)}.zk-account-sync.is-stale{background:var(--warn-bg);color:var(--warn)}.zk-shell button.zk-account-refresh{flex:none;color:var(--muted)}.zk-account-profile{display:flex;flex-direction:column;gap:18px;padding:22px}.zk-account-metrics{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.zk-account-metric{padding:14px 12px;border-radius:12px;background:linear-gradient(180deg,var(--paper),var(--surface));border:1px solid var(--line-2)}.zk-account-metric span{display:block;font-size:10px;color:var(--muted);margin-bottom:8px}.zk-account-metric strong{display:block;font-size:24px;line-height:1;font-weight:680;font-variant-numeric:tabular-nums;letter-spacing:-.04em}.zk-account-contrib,.zk-account-space{padding:20px 22px;display:flex;flex-direction:column;gap:16px}.zk-account-contrib-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.zk-account-contrib-head h3,.zk-account-space h3{margin:0;font-size:15px;font-weight:650}.zk-account-contrib-head p,.zk-account-space p{margin-top:6px}.zk-account-contrib-body{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.zk-account-rule{margin:0;flex:1;min-width:180px;font-size:12px;color:var(--ink-2);padding:12px 14px;border-radius:10px;background:var(--soft-2);border:1px solid var(--line-2)}.zk-account-space-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:16px}.zk-account-space-actions{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end}.zk-account-footer{display:flex;justify-content:flex-end;padding-top:14px;border-top:1px solid var(--line-2)}.zk-shell .zk-account-contrib-body>.zk-main,.zk-shell .zk-account-space-actions .zk-main{min-width:132px}@media (max-width:640px){.zk-account-metrics{grid-template-columns:1fr}.zk-account-space-row,.zk-account-contrib-body{grid-template-columns:1fr;display:flex;flex-direction:column;align-items:stretch}.zk-account-space-actions{justify-content:stretch}.zk-account-space-actions>*{flex:1}.zk-account-footer{justify-content:stretch}.zk-account-footer>*{flex:1}}\n.zk-stat-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:8px}.zk-stat-grid .zk-card{display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px 6px}.zk-stat-grid b{font-size:21px;font-weight:600;font-variant-numeric:tabular-nums}.zk-stat-grid span{font-size:9px;color:var(--muted)}.zk-shell button.zk-upload-zone{min-height:176px;flex-direction:column;gap:8px;border:1.5px dashed color-mix(in srgb,var(--accent) 35%,var(--line));background:var(--soft-2);border-radius:12px;padding:22px;color:var(--muted)}.zk-upload-icon{color:var(--accent);margin-bottom:4px}.zk-upload-zone strong{color:var(--ink);font-size:14px;font-weight:600}.zk-upload-zone>span:nth-last-child(2){font-size:10px}.zk-upload-zone .zk-badge{margin-top:6px;padding:5px 14px}.zk-import-preview{display:flex;flex-direction:column;gap:12px}.zk-import-preview .zk-stem{font-size:12px}\n.zk-log-row{display:flex;align-items:flex-start;gap:10px;padding:14px 0;border-bottom:1px solid var(--line-2)}.zk-log-row>i{display:block;width:6px;height:6px;flex:none;background:var(--faint);border-radius:50%;margin-top:5px}.zk-log-row.is-success>i{background:var(--ok)}.zk-log-row.is-error>i{background:var(--bad)}.zk-log-row.is-warning>i{background:var(--warn)}.zk-log-row time{font-size:9px;color:var(--faint);font-variant-numeric:tabular-nums}.zk-log-row p{font-size:11px;line-height:1.75;overflow-wrap:anywhere;margin-top:5px;color:var(--ink-2)}\n.zk-search-modes{display:grid;grid-template-columns:1fr 1fr;gap:12px}.zk-shell .zk-search-modes button{justify-content:flex-start;padding:16px;text-align:left;gap:12px;border-radius:10px;background:var(--surface)}.zk-search-modes button>.zk-icon{color:var(--muted)}.zk-search-modes span{flex:1;min-width:0}.zk-search-modes strong{display:block;font-size:12px;font-weight:600}.zk-search-modes small{display:block;font-size:9px;color:var(--muted);margin-top:5px;font-weight:400}.zk-search-modes i{width:12px;height:12px;border:1px solid var(--line);border-radius:50%;flex:none}.zk-shell .zk-search-modes button.is-on{border-color:var(--accent);background:var(--soft-2);color:var(--accent)}.zk-search-modes .is-on>.zk-icon{color:var(--accent)}.zk-search-modes .is-on i{border:4px solid var(--accent)}.zk-search-form .zk-field{margin:0 0 12px}.zk-search-form textarea{border:0;padding:0;resize:vertical;background:none;min-height:90px;box-shadow:none!important;font-size:13px}.zk-search-form .zk-actions{border-top:1px solid var(--line-2);padding-top:14px}.zk-search-form .zk-actions>.zk-link{margin-left:auto}.zk-search-hint{display:flex;align-items:center;flex-direction:column;gap:12px;text-align:center;padding:28px 10px;color:var(--faint)}.zk-search-hint strong{color:var(--muted);font-size:12px;font-weight:500}.zk-search-hint p{font-size:10px;line-height:1.8}.zk-markdown{font-size:13px;line-height:1.85;overflow-wrap:anywhere;user-select:text}.zk-markdown pre{overflow:auto;max-width:100%;background:var(--nav);padding:12px;border-radius:8px}.zk-markdown p{margin:8px 0}.zk-file{display:none!important}.zk-count-hero{border:1px solid var(--line);padding:20px;background:var(--surface);border-radius:12px;text-align:center}.zk-count-hero b{display:block;font-size:28px;color:var(--accent)}.zk-count-hero span{color:var(--muted);font-size:11px}\n.zk-modal,.zk-confirm{position:absolute;inset:0;z-index:8;display:grid;place-items:center;padding:24px;background:#151a3259;backdrop-filter:blur(4px)}.zk-confirm{z-index:9}.zk-modal-card,.zk-confirm-card{width:100%;max-width:390px;max-height:100%;overflow:auto;background:var(--surface);padding:24px;border:1px solid var(--line);border-radius:16px;box-shadow:0 20px 80px #151a3240;scrollbar-width:thin}.zk-confirm-card h3{font-size:17px;margin-bottom:10px}.zk-confirm-card p{font-size:12px;line-height:1.8;margin-bottom:22px;color:var(--muted)}.zk-confirm-card .zk-actions{justify-content:flex-end}.zk-modal-card>.zk-actions{justify-content:flex-end;padding-top:14px}.zk-snackbar{position:absolute;left:50%;bottom:18px;transform:translateX(-50%);z-index:10;max-width:calc(100% - 32px);padding:11px 18px;border:1px solid #ffffff16;border-radius:10px;background:#30344d;box-shadow:0 6px 30px #10152425;color:white;font-size:12px;line-height:1.7;overflow-wrap:anywhere;pointer-events:none}.zk-snackbar.is-success{background:#286c58}.zk-snackbar.is-warning{background:#916826}.zk-snackbar.is-error{background:#a45454}\n.zk-launcher-wrap{position:fixed;z-index:2147483646;display:flex;flex-direction:column;align-items:flex-end;gap:8px}.zk-launcher-wrap>.zk-launcher{position:relative;left:auto!important;top:auto!important}.zk-launcher-bubble{position:relative;pointer-events:none;max-width:min(280px,70vw);padding:10px 12px;border-radius:12px;background:#1f2937;color:#fff;font:12px/1.55 -apple-system,BlinkMacSystemFont,\"PingFang SC\",\"Microsoft YaHei\",sans-serif;box-shadow:0 8px 24px #10182833;animation:zk-launcher-pop .28s ease}.zk-launcher-bubble::after{content:\"\";position:absolute;right:22px;bottom:-6px;width:12px;height:12px;background:#1f2937;transform:rotate(45deg);border-radius:2px}.zk-launcher{position:relative;display:flex;align-items:center;gap:10px;min-width:148px;padding:8px 14px 8px 8px;border:1px solid #8b7cda;border-radius:16px;background:linear-gradient(135deg,#5144b8 0%,#463d91 55%,#3d3482 100%);box-shadow:0 8px 24px #30286c33;color:white;cursor:grab;touch-action:none;font:13px/1.35 -apple-system,BlinkMacSystemFont,\"PingFang SC\",\"Microsoft YaHei\",sans-serif;overflow:hidden;isolation:isolate}.zk-launcher::before{content:\"\";position:absolute;inset:-40% -30%;background:linear-gradient(110deg,transparent 35%,#ffffff22 48%,transparent 62%);transform:translateX(-40%);pointer-events:none;opacity:.55}.zk-launcher.is-active::before{animation:zk-launcher-sheen 1.8s ease-in-out infinite}.zk-launcher.is-active{animation:zk-launcher-breathe 1.6s ease-in-out infinite}.zk-launcher.is-done{border-color:#7dceb0;box-shadow:0 8px 24px #1f6b5130}.zk-launcher-meta{display:flex;flex-direction:column;gap:5px;min-width:0;flex:1}.zk-launcher-title{display:flex;align-items:center;gap:8px;min-width:0}.zk-launcher-title strong{font-size:13px;font-weight:650;letter-spacing:.02em}.zk-launcher-title small{padding-left:8px;border-left:1px solid #ffffff33;font-size:11px;color:#c8f6e8;font-variant-numeric:tabular-nums;font-weight:600;white-space:nowrap}.zk-launcher-bar{position:relative;display:block;width:100%;height:4px;border-radius:999px;background:#ffffff24;overflow:hidden}.zk-launcher-bar>i{display:block;height:100%;width:0;border-radius:inherit;background:linear-gradient(90deg,#9cf1d7,#7dceb0);box-shadow:0 0 8px #9cf1d780;transition:width .35s ease}.zk-launcher-bar.is-indeterminate>i{width:42%!important;animation:zk-launcher-indeterminate 1.1s ease-in-out infinite}\n.zk-shell.is-focus .zk-frame{grid-template-columns:minmax(0,1fr)}.zk-shell.is-focus .zk-sidebar,.zk-shell.is-focus .zk-split-side{display:none}.zk-shell.is-focus .zk-split{grid-template-columns:minmax(0,1fr)}.zk-shell.is-compact .zk-choice{padding:7px 10px}.zk-shell.is-compact .zk-options{gap:5px}.zk-shell.is-compact .zk-stem{font-size:13px;line-height:1.65}.zk-shell.is-compact .zk-split-main{padding:15px}.zk-shell.is-compact .zk-card{padding:13px}\n@keyframes zk-pulse{50%{opacity:.4}}\n@keyframes zk-spin{to{transform:rotate(360deg)}}\n@keyframes zk-scan-dot{0%,80%,100%{opacity:.28;transform:translateY(0)}40%{opacity:1;transform:translateY(-3px)}}\n.zk-scan{gap:12px}.zk-scan-spinner{width:36px;height:36px;border:3px solid var(--line);border-top-color:var(--accent);border-radius:50%;animation:zk-spin .75s linear infinite;margin-bottom:2px}.zk-scan-dots{display:flex;gap:6px;margin-top:2px}.zk-scan-dots i{width:6px;height:6px;border-radius:50%;background:var(--accent);animation:zk-scan-dot 1s ease-in-out infinite}.zk-scan-dots i:nth-child(2){animation-delay:.15s}.zk-scan-dots i:nth-child(3){animation-delay:.3s}\n@media(max-width:820px){.zk-shell{width:calc(100vw - 24px);height:calc(100dvh - 24px)}.zk-frame{grid-template-columns:58px minmax(0,1fr)}.zk-sidebar{padding:12px 6px}.zk-nav-groups{gap:18px}.zk-nav-caption,.zk-nav-item>span,.zk-nav-item small,.zk-account-nav-meta,.zk-account-nav-go,.zk-nav-version{display:none}.zk-shell button.zk-nav-item{justify-content:center;padding:12px 0}.zk-shell button.zk-account-nav{justify-content:center;padding:6px;width:auto;border:0;background:transparent;box-shadow:none}.zk-shell button.zk-account-nav.is-active{background:var(--soft)}.zk-body,.zk-scroll{padding-left:18px;padding-right:18px}.zk-task-footer{margin-left:-18px;margin-right:-18px;padding-left:18px;padding-right:18px}}\n@media(max-width:560px){\n .zk-shell{width:calc(100vw - 16px);height:calc(100dvh - 16px);border-radius:14px}.zk-header{height:57px;min-height:57px;padding:0 12px;gap:5px}.zk-emblem{width:31px;height:31px;border-radius:9px;margin-right:4px}.zk-brand strong{font-size:18px;gap:7px}.zk-brand strong span{font-size:9px;padding-left:7px}.zk-brand small{font-size:6px;letter-spacing:0}.zk-header-status{display:none}.zk-header .zk-icon-btn{width:29px;height:29px;min-height:29px}\n .zk-frame{display:flex;flex-direction:column}.zk-sidebar{flex-direction:row;align-items:center;flex:none;border-right:0;border-bottom:1px solid var(--line);padding:6px 8px;gap:4px;overflow-x:auto;scrollbar-width:none}.zk-nav-groups,.zk-nav-group{display:contents}.zk-nav-bottom{display:contents}.zk-shell button.zk-nav-item{width:auto;flex:none;padding:7px 10px;gap:6px;font-size:10px;min-height:32px}.zk-nav-item>span{display:block}.zk-nav-item>.zk-icon{width:14px;height:14px}.zk-shell button.zk-account-nav{width:32px;height:32px;min-height:32px;padding:0;flex:none;border-radius:10px}.zk-mini-avatar{width:26px;height:26px;border-radius:8px;font-size:12px;box-shadow:none}\n .zk-body,.zk-scroll{padding:16px 12px 0;flex:1}.zk-scroll{padding-bottom:18px}.zk-page,.zk-home-page{gap:14px}.zk-ask{gap:11px}.zk-page-heading h2{font-size:20px}.zk-page-heading p{font-size:10px;margin-top:5px}.zk-eyebrow{font-size:9px;margin-bottom:4px}\n .zk-summary{padding:13px 3px;grid-template-columns:1.4fr repeat(3,1fr)}.zk-summary-main{padding:0 10px;gap:7px}.zk-summary-main strong,.zk-summary-stat strong{font-size:21px}.zk-summary-main span,.zk-summary-stat span{font-size:9px}.zk-summary-main small{font-size:10px}.zk-summary-main>div:first-child{gap:5px;align-items:flex-start;flex-direction:column}.zk-filter-bar{gap:4px}.zk-filter-bar .zk-chips{gap:1px}.zk-filter-bar .zk-chips button{font-size:9px;padding:4px 7px;min-height:25px}.zk-task-state{font-size:9px}\n .zk-split{display:flex;flex-direction:column;gap:10px}.zk-split-side{order:-1;padding:9px 10px;flex:none;max-height:115px}.zk-rail{min-height:0;gap:8px}.zk-rail-heading strong{font-size:10px}.zk-rail-grid{grid-template-columns:repeat(10,minmax(0,1fr));gap:5px;max-height:62px;overflow-y:auto;padding:2px}.zk-shell button.zk-num-btn{font-size:9px;min-height:23px;aspect-ratio:1}.zk-legend,.zk-rail-note{display:none}.zk-split-main{flex:1;padding:15px}.zk-stem{font-size:13px;line-height:1.8;margin-bottom:14px}.zk-detail-head{gap:6px;margin-bottom:13px}.zk-num{font-size:8px}.zk-card-status{font-size:9px}.zk-choice{padding:9px 10px;gap:10px;font-size:12px}.zk-choice-key{width:21px;height:21px}\n .zk-task-footer{margin-left:-12px;margin-right:-12px;padding:10px 12px;gap:4px}.zk-footer-actions{gap:3px}.zk-footer-actions .zk-main{padding:8px 11px;font-size:11px}.zk-pagination{gap:0;font-size:9px}.zk-pagination .zk-icon-btn{width:26px}\n .zk-home-hero{padding:20px;gap:10px}.zk-home-hero h3{font-size:19px}.zk-hero-art{width:78px;min-width:78px}.zk-art-book{width:65px;height:83px;border-radius:10px;box-shadow:6px 8px 0 var(--soft)}.zk-art-book .zk-icon{width:33px}.zk-art-spark{right:-4px}.zk-art-check{padding:5px;border-width:3px;right:-4px;bottom:12px}.zk-art-check .zk-icon{width:14px;height:14px}.zk-overview-stats{gap:8px}.zk-overview-stats>div{padding:12px;gap:6px}.zk-overview-stats .zk-icon{width:15px}.zk-overview-stats strong{font-size:20px}.zk-overview-stats span{font-size:9px}.zk-home-grid{gap:8px}.zk-shell .zk-home-grid button{padding:13px 10px;gap:8px}.zk-tile-icon{width:29px;height:29px;border-radius:8px}.zk-tile-icon .zk-icon{width:17px;height:17px}.zk-tile-label strong{font-size:11px}.zk-tile-label small{font-size:9px;line-height:1.5}.zk-home-grid button>.zk-icon{display:none}.zk-home-note{font-size:9px;align-items:flex-start}\n .zk-form-grid{grid-template-columns:1fr;gap:0}.zk-card{padding:15px}.zk-actions{gap:6px}.zk-actions button{font-size:11px;padding:7px 10px}.zk-config-nav{gap:0}.zk-shell .zk-config-nav button{padding:10px 11px;font-size:11px}.zk-connection-banner{padding:15px;gap:10px}.zk-connection-banner strong{font-size:13px}.zk-connection-banner p{font-size:10px}.zk-connection-icon{width:34px;height:34px;border-radius:10px}.zk-connection-banner .zk-badge{font-size:9px}.zk-search-modes{gap:8px}.zk-shell .zk-search-modes button{padding:13px 10px;gap:8px}.zk-search-modes strong{font-size:11px}.zk-search-modes small{font-size:8px}.zk-search-modes button>.zk-icon{width:17px}.zk-search-modes i{width:10px;height:10px}.zk-modal,.zk-confirm{padding:16px}.zk-modal-card,.zk-confirm-card{padding:20px}.zk-setting-row{gap:6px;font-size:11px}.zk-section-heading>span{font-size:9px}.zk-empty{min-height:180px;padding:18px 10px}.zk-empty p{font-size:10px}\n}\n@media(prefers-reduced-motion:reduce){.zk-shell *,.zk-launcher,.zk-launcher *{transition:none!important;animation:none!important}}\n\n.zk-import-status{padding:12px 0;border-bottom:1px solid var(--line);display:flex;flex-direction:column;gap:8px}.zk-import-status:last-of-type{border-bottom:0}\n.zk-update-banner{display:flex;align-items:center;gap:10px;padding:11px 18px;background:var(--soft);border-bottom:1px solid var(--line);flex:none;min-width:0}.zk-update-banner>span{flex:1;min-width:0}.zk-update-banner strong,.zk-update-banner small{display:block}.zk-update-banner strong{font-size:12px}.zk-update-banner small{font-size:10px;color:var(--muted)}.zk-shell a.zk-update-install{display:inline-flex;justify-content:center;align-items:center;flex:none;padding:8px 12px;border-radius:7px;background:var(--accent);color:var(--surface);font-size:12px;text-decoration:none;white-space:nowrap}.zk-update-error{color:var(--bad)}.zk-update-notes{padding-left:20px;line-height:1.8;font-size:12px}.zk-update-settings>p{margin:12px 0}.zk-shell button.zk-nav-version{background:transparent;width:100%;font-size:10px;border:0;border-top:1px solid var(--line);border-radius:0;white-space:normal}.zk-config-nav{overflow-x:auto;flex:none}.zk-config-nav button{white-space:nowrap;flex:none}@media(max-width:600px){.zk-update-banner{padding:9px 12px;gap:7px;flex-wrap:wrap}.zk-update-banner>span{flex-basis:calc(100% - 100px)}.zk-update-banner>button:not(.zk-icon-btn){padding:5px 9px;font-size:11px}.zk-shell a.zk-update-install{font-size:11px;padding:7px 10px}}\n.zk-interval{display:flex;flex-direction:column;gap:8px;margin:16px 0;min-width:0}.zk-interval-heading,.zk-interval-scale{display:flex;justify-content:space-between;gap:12px;align-items:center}.zk-interval-heading{font-size:12px;color:var(--ink-2)}.zk-interval-heading output{font-variant-numeric:tabular-nums;color:var(--accent);background:var(--nav);border-radius:6px;padding:4px 8px;font-size:12px}.zk-interval-scale{font-size:10px;color:var(--muted)}.zk-shell .zk-interval input[type=range]{width:100%;height:26px;padding:0;border:0;box-shadow:none;accent-color:var(--accent);background:transparent;cursor:pointer}.zk-interval input[type=range]:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:5px}\n\n.zk-brand-logo{display:block;flex:none;object-fit:contain}.zk-emblem{width:40px;height:40px;background:none;border-radius:12px}.zk-nav-glyph{display:grid;place-items:center;width:30px;height:30px;flex:none;border-radius:9px;color:#7164c3;background:#f0edfc;transition:all .18s}.zk-glyph-edit{color:#4478b6;background:#ecf3fc}.zk-glyph-search{color:#358c7c;background:#e9f6f0}.zk-glyph-library{color:#a27738;background:#fbf3e5}.zk-glyph-upload{color:#5185a4;background:#ecf4f8}.zk-glyph-log{color:#98739c;background:#f5eef8}.zk-shell .zk-nav-item{gap:9px;min-height:44px;padding:6px 9px}.zk-nav-item.is-active .zk-nav-glyph{background:var(--accent);color:white;box-shadow:0 3px 8px #6956df30}.zk-shell[data-theme=dark] .zk-nav-glyph{background:var(--soft);color:var(--accent)}.zk-launcher-mark{position:relative;display:grid;place-items:center;width:40px;height:40px;flex:none}.zk-launcher-ring{position:absolute;inset:0;width:40px;height:40px;transform:rotate(-90deg);color:#9cf1d7;pointer-events:none}.zk-launcher-ring-track{opacity:.22}.zk-launcher-ring-value{transition:stroke-dashoffset .35s ease}.zk-launcher.is-active .zk-launcher-ring{animation:zk-launcher-spin 1.2s linear infinite;color:#b7ffe8}.zk-launcher.is-done .zk-launcher-ring{color:#9cf1d7;animation:none}.zk-footer-actions{flex-wrap:wrap}.zk-shell button.zk-icon-btn:has(.zk-icon+span){width:auto;padding:6px 9px}.zk-shell .zk-detail-head{flex-wrap:wrap}\n@keyframes zk-launcher-breathe{0%,100%{box-shadow:0 8px 24px #30286c33,0 0 0 0 #9cf1d700}50%{box-shadow:0 10px 28px #30286c45,0 0 0 6px #9cf1d718}}\n@keyframes zk-launcher-sheen{0%{transform:translateX(-50%)}100%{transform:translateX(50%)}}\n@keyframes zk-launcher-spin{to{transform:rotate(270deg)}}\n@keyframes zk-launcher-indeterminate{0%{transform:translateX(-120%)}100%{transform:translateX(280%)}}\n@keyframes zk-launcher-pop{0%{opacity:0;transform:translateY(6px) scale(.96)}100%{opacity:1;transform:translateY(0) scale(1)}}\n@media(max-width:560px){.zk-shell .zk-footer{flex-wrap:wrap;gap:8px}.zk-shell .zk-footer-actions{gap:5px}.zk-shell .zk-footer-actions button{padding:6px 8px}.zk-shell .zk-nav-glyph{width:25px;height:25px}}\n", Zm = "__zhikuXHRObserver", installXHRHook = (e, t) => { const n = Object.getOwnPropertyDescriptor(e.prototype, "send"), a = (null == n ? void 0 : n.value) ?? e.prototype.send; if ("function" == typeof (r = a) && true === r[Zm]) return false; var r; if ("function" != typeof a) return false; if (false === (null == n ? void 0 : n.configurable) && false === n.writable) return false; const i = a, hookedSend = function(e) { return this.addEventListener("readystatechange", (function() { t.call(this, this); })), i.call(this, e); }; return Object.defineProperty(hookedSend, Zm, { value: true }), Object.defineProperty(e.prototype, "send", { configurable: true, writable: true, value: hookedSend }), true; }, get_href = () => location.href, comHook = () => { if (hookXHR(), /onlineexamh5new.zhihuishu.com/i.test(get_href())) { const e = ie.yxyz; ie.yxyz = function(t, n) { !ie.yxyzpush && (ie.yxyzpush = []); let a = e(t, n); return ie.yxyzpush.push({ ...t, data: a }), a; }; } if (/icve.com.cn/i.test(get_href()) || /courshare.cn/i.test(get_href()) || /webtrn.cn/i.test(get_href())) { const e = ie.open; ie.open = function() { return arguments[2] = "", e.apply(this, arguments); }; } if (/ytccr.com/i.test(get_href())) { const e = localStorage.getItem; localStorage.getItem = function(t) { if ("_debugger" === t) return true; return e.apply(this, arguments); }; } if (/91huayi.com/i.test(get_href())) { const e = ie.$.cookie; ie.$.cookie = function(t, n, a) { return console.log("Cookie\u64cd\u4f5c:", t, n, a), t.startsWith("switchTime") && void 0 !== n ? (n = void 0, e.apply(this, [ t, n, a ])) : e.apply(this, arguments); }; } }, hookXHR = () => { installXHRHook(XMLHttpRequest, (function() { var e; switch (true) { case /geovisearth\.com/i.test(location.host): if (4 === this.readyState && this.responseURL && this.responseURL.includes("/education/exam/startExam")) try { const e = "string" == typeof this.response ? this.response : this.responseText, t = JSON.parse(e), n = t && t.data ? Object.values(t.data) : []; n.length > 0 && (ie.antaiques = n, n.length, waitUntil((() => O(".n-card.n-modal .el-carousel__item").length > 0), { timeout: 15e3 }).then((() => vuePageChange())).catch((() => {}))); } catch (t) {} break; case /onlineexamh5new.zhihuishu.com/i.test(get_href()): if (4 === this.readyState && this.responseURL && /\/student\/(doHomework|doExam)/i.test(this.responseURL)) try { const e = "string" == typeof this.response ? this.response : this.responseText; if (!e || !e.includes("workExamParts")) break; const t = JSON.parse(e), n = t.rt || t, a = extractZhihuishuExamQuestions(n).length; a > 0 && (ie.zhsques = n); } catch (t) {} break; case /icve.com.cn/i.test(location.host): 4 === this.readyState && this.responseURL && (this.responseURL.includes("examRecordPaperList") || this.responseURL.includes("queryXsDtjgSjInfo")) && JSON.parse(this.response); break; case /qingshuxuetang.com/i.test(get_href()): if (4 === this.readyState && this.responseURL && /\/Student\/(?:DetailData|(?:SimulationExercise|Quiz)\/DetailData)(?:\?|$)/i.test(this.responseURL)) try { const e = "string" == typeof this.response ? this.response : this.responseText, t = ((e, t, n) => { var a, r; if (!isQingshuPage(n)) return null; const i = new URL(n); let s; try { s = new URL(e); } catch { return null; } if (s.origin !== i.origin || !/\/Student\/(?:DetailData|(?:SimulationExercise|Quiz)\/DetailData)$/i.test(s.pathname)) return null; const o = i.searchParams.get("quizId") || i.searchParams.get("id"); if (o && o !== (s.searchParams.get("quizId") || s.searchParams.get("id"))) return null; const l = null == (r = null == (a = null == t ? void 0 : t.data) ? void 0 : a.paperDetail) ? void 0 : r.questions; return Array.isArray(l) && l.length <= 500 ? l : []; })(this.responseURL, e.length <= 2097152 ? JSON.parse(e) : null, location.href); if (null === t) break; ie.qsques = t, t.length; } catch { ie.qsques = []; } break; case /bgzk-edu\.cn/i.test(location.host): if (4 === this.readyState && this.responseURL && this.responseURL.includes("/student/course/quiz/detail")) try { const t = "string" == typeof this.response ? this.response : this.responseText, n = JSON.parse(t), a = null == (e = null == n ? void 0 : n.data) ? void 0 : e.studentQuestions; Array.isArray(a) && a.length > 0 && (ie.bgzkquiz = n.data, ie.bgzkques = a, a.length); } catch (t) {} break; case /cce.org.uooconline.com/i.test(get_href()): if (4 === this.readyState && this.responseURL.includes("/exam/view?cid=")) { const e = JSON.parse(this.response); ie.cceques = e.data.questions, e.data.questions; } break; case /cj-edu.com/i.test(get_href()): if (4 === this.readyState && this.responseURL.includes("api/student/getHomeworkStudentInfo.do")) { const e = JSON.parse(this.response); ie.cjques = e.data, e.data; } break; case /gxk.yxlearning.com/i.test(get_href()): if (4 === this.readyState && this.responseURL.includes("cms/paper/start-do-paper-or-test.gson")) { const e = JSON.parse(this.response); ie.yxques = e.attribute.data, e.data; } } })); }; (e => { if ("function" != typeof e) return; const t = e, n = getRuntime(); "function" != typeof n.GM_xmlhttpRequest && (n.GM_xmlhttpRequest = t), n.GM || (n.GM = {}), "function" != typeof n.GM.xmlHttpRequest && (n.GM.xmlHttpRequest = t); })(re); let Ym = null, Xm = false; const installHooks = () => { Xm || isPageClaimedByNewLine(document) || (Xm = true, comHook(), $n.filter((e => isRuleMatched(e) && e.hook)).forEach((e => { e.hook(); }))); }, run = () => { if (isPageClaimedByNewLine(document)) return; if (Ym) return; installHooks(); (ie === ie.top || [ /\/work\/doHomeWorkNew/i, /selectWorkQuestionYiPiYue/i, /page\/quiz\/stu\/answerQuestion2/i, /page\/active\/stuActiveList/i, /uooconline.com/i, /edu-edu.com/i, /hblearning\/exam\/portal\/exam.jsp/i ].some((e => e.test(location.href))) || $n.some((e => "hook" !== e.type && isRuleMatched(e)))) && (Ym = (() => { var e; const t = pinia.createPinia(), n = vue.createApp(WorkspacePanel); n.use(t); const a = document.createElement("div"), r = document.createElement("div"); r.id = "ZhikuWorkspace", (e => { var t, n; if (!Kn.iframe || e.self === e.top) return false; try { return (null == (n = null == (t = e.top) ? void 0 : t.location) ? void 0 : n.origin) === e.location.origin; } catch { return false; } })(window) ? (r.id = "ZhikuWorkspaceTop", null == (e = window.top) || e.document.body.appendChild(a)) : document.body.append(a); const i = a.attachShadow({ mode: "open" }); i.appendChild(r); try { const e = document.createElement("style"); e.textContent = Jm, i.appendChild(e); } catch (s) { console.error("\u5e94\u7528\u6837\u5f0f\u8868\u65f6\u51fa\u9519:", s); } n.mount(r); try { const bootApp = Wn(), bootAsk = Xn(); bootApp.app.showFloat = !bootApp.app.hideFloat && !!bootApp.app.defaultShowFloat; bootApp.setPage("ask"); bootAsk.scanning = true; bootAsk.scanText = "正在读取网页题目…"; Promise.resolve(parseRule($n)).catch(() => {}).finally(() => { bootAsk.scanning = false; bootAsk.scanText = ""; }); } catch (bootErr) { Promise.resolve(parseRule($n)).catch(() => {}); } return { app: n, main_root: a }; })(), installGlobalAutoScan(), installWorkspaceCaptureWatch()); }, watchOwnership = () => { const e = ((e, t, n = ("undefined" == typeof MutationObserver ? void 0 : MutationObserver)) => { let a = isPageClaimedByNewLine(e); t(a); const r = e.documentElement; if (!r || !n) return () => {}; let i = false; const s = new n((() => { const n = isPageClaimedByNewLine(e); i || n === a || (a = n, t(n)); })); return s.observe(r, { attributes: true, attributeFilter: [ qn ] }), () => { i = true, s.disconnect(); }; })(document, (e => { var t; e ? Ym && (null == (t = getAskStore()) || t.pause(), Ym.app.unmount(), Ym.main_root.remove(), Ym = null) : run(); })); window.addEventListener("pagehide", (t => { t.persisted || e(); })); }; isPageClaimedByNewLine(document) || installHooks(), (() => { const start = () => { document.body ? watchOwnership() : document.addEventListener("DOMContentLoaded", watchOwnership, { once: true }); }; "loading" !== document.readyState ? start() : document.addEventListener("DOMContentLoaded", start, { once: true }); })(); })(Vue, Icon, Pinia, DOMPurify, CryptoJS, $);