pikpak助手plus

pikpak网盘助手的增强版,搭配代理可实现直连下载,支持推送文件夹到aria2中!

// ==UserScript==
// @name         pikpak助手plus
// @namespace    http://tampermonkey.net/
// @version      1.4
// @author       jdysya
// @description  pikpak网盘助手的增强版,搭配代理可实现直连下载,支持推送文件夹到aria2中!
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=mypikpak.com
// @match        https://mypikpak.com/*
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.prod.js
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// ==/UserScript==

(t=>{const a=document.createElement("style");a.dataset.source="vite-plugin-monkey",a.innerText=t,document.head.appendChild(a)})(' .dialog[data-v-a2749c9c]{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:linear-gradient(135deg,#ffffff 0%,#f8fafc 100%);z-index:10000;padding:32px;box-shadow:0 25px 50px -12px #00000040,0 0 0 1px #ffffff0d;border-radius:20px;width:90vw;max-width:800px;min-width:320px;max-height:90vh;box-sizing:border-box;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);animation:dialogFadeIn-a2749c9c .3s cubic-bezier(.4,0,.2,1)}@keyframes dialogFadeIn-a2749c9c{0%{opacity:0;transform:translate(-50%,-50%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}@media (max-width: 768px){.dialog[data-v-a2749c9c]{width:95vw;padding:24px;border-radius:16px}}@media (max-width: 480px){.dialog[data-v-a2749c9c]{width:100vw;height:100vh;max-height:100vh;border-radius:0;padding:20px}}.dialog h2[data-v-a2749c9c]{text-align:center;color:#1e293b;margin-bottom:24px;font-size:24px;font-weight:700;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}@media (max-width: 480px){.dialog h2[data-v-a2749c9c]{font-size:20px;margin-bottom:20px}}.dialog .close[data-v-a2749c9c]{position:absolute;right:20px;top:20px;width:40px;height:40px;display:flex;align-items:center;justify-content:center;font-size:24px;cursor:pointer;color:#64748b;background:rgba(248,250,252,.8);border-radius:50%;transition:all .3s cubic-bezier(.4,0,.2,1);border:1px solid rgba(226,232,240,.5)}.dialog .close[data-v-a2749c9c]:hover{color:#ef4444;background:rgba(254,226,226,.8);border-color:#f871714d;transform:scale(1.05)}.toolbar[data-v-a2749c9c]{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;padding:16px 20px;background:linear-gradient(135deg,rgba(99,102,241,.05) 0%,rgba(168,85,247,.05) 100%);border-radius:12px;border:1px solid rgba(99,102,241,.1)}@media (max-width: 640px){.toolbar[data-v-a2749c9c]{flex-direction:column;gap:16px;align-items:stretch}}.toolbar input[type=checkbox][data-v-a2749c9c]{margin-right:8px;transform:scale(1.3);accent-color:#6366f1}.toolbar label[data-v-a2749c9c]{font-weight:600;color:#374151;display:flex;align-items:center;cursor:pointer;transition:color .2s ease}.toolbar label[data-v-a2749c9c]:hover{color:#6366f1}.sort-options[data-v-a2749c9c]{display:flex;align-items:center;gap:12px;flex-wrap:wrap}@media (max-width: 640px){.sort-options[data-v-a2749c9c]{justify-content:center}}.sort-options label[data-v-a2749c9c]{font-size:14px;font-weight:500;color:#6b7280}.sort-options select[data-v-a2749c9c]{padding:8px 12px;border:2px solid #e5e7eb;background:white;color:#374151;border-radius:8px;font-size:14px;transition:all .2s ease;cursor:pointer}.sort-options select[data-v-a2749c9c]:focus{outline:none;border-color:#6366f1;box-shadow:0 0 0 3px #6366f11a}.sort-options select[data-v-a2749c9c]:hover{border-color:#9ca3af}.movies[data-v-a2749c9c]{margin-top:16px;height:400px;overflow-y:auto;border:2px solid #f1f5f9;border-radius:16px;padding:0;background:linear-gradient(135deg,#ffffff 0%,#f8fafc 100%);box-shadow:inset 0 2px 4px #0000000f}@media (max-width: 480px){.movies[data-v-a2749c9c]{height:300px}}.movies[data-v-a2749c9c]::-webkit-scrollbar{width:8px}.movies[data-v-a2749c9c]::-webkit-scrollbar-track{background:#f1f5f9;border-radius:8px}.movies[data-v-a2749c9c]::-webkit-scrollbar-thumb{background:linear-gradient(135deg,#cbd5e1 0%,#94a3b8 100%);border-radius:8px;transition:background .2s ease}.movies[data-v-a2749c9c]::-webkit-scrollbar-thumb:hover{background:linear-gradient(135deg,#94a3b8 0%,#64748b 100%)}.movies li[data-v-a2749c9c]{display:flex;align-items:center;padding:16px 20px;border-bottom:1px solid rgba(226,232,240,.6);font-size:14px;color:#334155;transition:all .2s ease;cursor:pointer}.movies li[data-v-a2749c9c]:hover{background:linear-gradient(135deg,rgba(99,102,241,.05) 0%,rgba(168,85,247,.05) 100%);transform:translate(4px)}.movies li[data-v-a2749c9c]:last-child{border-bottom:none}.movies li input[type=checkbox][data-v-a2749c9c]{margin-right:16px;transform:scale(1.2);accent-color:#6366f1}.movies li .icon[data-v-a2749c9c]{margin-right:12px;font-size:1.5em;filter:drop-shadow(0 1px 2px rgba(0,0,0,.1))}.movies li .file-info[data-v-a2749c9c]{margin-left:auto;color:#64748b;font-size:12px;font-weight:500;padding:4px 8px;background:rgba(248,250,252,.8);border-radius:6px;border:1px solid rgba(226,232,240,.5)}.footer[data-v-a2749c9c]{margin-top:24px;display:flex;justify-content:space-between;align-items:center;gap:16px;padding-top:20px;border-top:1px solid rgba(226,232,240,.6)}@media (max-width: 480px){.footer[data-v-a2749c9c]{flex-direction:column;gap:12px}}.btn.el-button[data-v-a2749c9c]{padding:14px 28px;border:none;border-radius:12px;cursor:pointer;font-size:16px;font-weight:600;transition:all .3s cubic-bezier(.4,0,.2,1);position:relative;overflow:hidden}.btn.el-button--primary[data-v-a2749c9c]{background:linear-gradient(135deg,#6366f1 0%,#8b5cf6 100%);color:#fff;box-shadow:0 4px 14px #6366f14d}.btn.el-button--secondary[data-v-a2749c9c]{background:linear-gradient(135deg,#f8fafc 0%,#e2e8f0 100%);color:#475569;border:2px solid #cbd5e1;box-shadow:0 2px 8px #4755691a}.btn.el-button[data-v-a2749c9c]:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.2),transparent);transition:left .5s}.btn.el-button--primary[data-v-a2749c9c]:hover{background:linear-gradient(135deg,#5b21b6 0%,#7c3aed 100%);box-shadow:0 8px 25px #6366f166;transform:translateY(-2px)}.btn.el-button--secondary[data-v-a2749c9c]:hover{background:linear-gradient(135deg,#e2e8f0 0%,#cbd5e1 100%);border-color:#94a3b8;box-shadow:0 4px 12px #47556926;transform:translateY(-2px)}.btn.el-button[data-v-a2749c9c]:hover:before{left:100%}.btn.el-button[data-v-a2749c9c]:active{transform:translateY(0);box-shadow:0 4px 14px #6366f14d}@media (max-width: 480px){.btn.el-button[data-v-a2749c9c]{width:100%;padding:16px;font-size:18px}}.connection-status[data-v-a2749c9c]{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;margin:16px 0;background:#f8f9fa;border-radius:8px;border:1px solid #e9ecef}.status-indicator[data-v-a2749c9c]{display:flex;align-items:center;gap:8px}.status-dot[data-v-a2749c9c]{width:8px;height:8px;border-radius:50%;transition:all .3s ease}.status-dot.connected[data-v-a2749c9c]{background:#52c41a;box-shadow:0 0 0 2px #52c41a33;animation:pulse-a2749c9c 2s infinite}.status-dot.disconnected[data-v-a2749c9c]{background:#ff4d4f;box-shadow:0 0 0 2px #ff4d4f33}.status-dot.testing[data-v-a2749c9c]{background:#1890ff;box-shadow:0 0 0 2px #1890ff33;animation:pulse-a2749c9c 1s infinite}.status-dot.unknown[data-v-a2749c9c]{background:#d9d9d9}.status-text[data-v-a2749c9c]{font-size:14px;color:#666;font-weight:500}.test-btn[data-v-a2749c9c]{padding:6px 12px;font-size:12px;border:1px solid #d9d9d9;border-radius:4px;background:white;color:#666;cursor:pointer;transition:all .2s ease}.test-btn[data-v-a2749c9c]:hover:not(:disabled){border-color:#409eff;color:#409eff}.test-btn[data-v-a2749c9c]:disabled{opacity:.6;cursor:not-allowed}@keyframes pulse-a2749c9c{0%{transform:scale(1);opacity:1}50%{transform:scale(1.1);opacity:.7}to{transform:scale(1);opacity:1}}.connection-status[data-v-df78435e]{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;margin-bottom:20px;background:linear-gradient(135deg,rgba(99,102,241,.05) 0%,rgba(168,85,247,.05) 100%);border-radius:12px;border:1px solid rgba(99,102,241,.1)}.status-indicator[data-v-df78435e]{display:flex;align-items:center;gap:12px}.status-dot[data-v-df78435e]{width:12px;height:12px;border-radius:50%;position:relative}.status-dot.connected[data-v-df78435e]{background-color:#10b981;box-shadow:0 0 0 2px #10b98133}.status-dot.connected[data-v-df78435e]:before{content:"";position:absolute;width:12px;height:12px;border-radius:50%;background-color:#10b981;animation:pulse-df78435e 2s infinite}.status-dot.disconnected[data-v-df78435e]{background-color:#ef4444;box-shadow:0 0 0 2px #ef444433}.status-dot.testing[data-v-df78435e]{background-color:#f59e0b;box-shadow:0 0 0 2px #f59e0b33;animation:pulse-df78435e 1s infinite}.status-dot.unknown[data-v-df78435e]{background-color:#6b7280;box-shadow:0 0 0 2px #6b728033}@keyframes pulse-df78435e{0%{transform:scale(1);opacity:1}50%{transform:scale(1.2);opacity:.7}to{transform:scale(1);opacity:1}}.status-text[data-v-df78435e]{font-size:14px;font-weight:500;color:#374151}.test-btn[data-v-df78435e]{padding:8px 16px;background:linear-gradient(135deg,#f8fafc 0%,#e2e8f0 100%);color:#475569;border:2px solid #cbd5e1;border-radius:8px;cursor:pointer;font-size:14px;font-weight:500;transition:all .2s ease}.test-btn[data-v-df78435e]:hover:not(:disabled){background:linear-gradient(135deg,#e2e8f0 0%,#cbd5e1 100%);border-color:#94a3b8;transform:translateY(-1px)}.test-btn[data-v-df78435e]:disabled{opacity:.6;cursor:not-allowed}.dialog[data-v-df78435e]{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;z-index:10000;padding:30px;box-shadow:0 5px 15px #0000004d;border-radius:10px;width:90%;max-width:500px;box-sizing:border-box}.dialog h2[data-v-df78435e]{text-align:center;color:#333;margin-bottom:20px}.dialog .close[data-v-df78435e]{position:absolute;right:15px;top:15px;font-size:30px;cursor:pointer;color:#999;transition:color .3s ease}.dialog .close[data-v-df78435e]:hover{color:#666}.config-list[data-v-df78435e]{margin-top:20px}.config-list li[data-v-df78435e]{margin-bottom:15px}.config-list li .label[data-v-df78435e]{font-weight:700;margin-bottom:5px;display:block;color:#555}.config-list li input[type=text][data-v-df78435e]{width:100%;padding:10px;border:1px solid #dcdfe6;border-radius:4px;box-sizing:border-box;font-size:14px;transition:border-color .3s ease}.config-list li input[type=text][data-v-df78435e]:focus{border-color:#409eff;outline:none}.footer[data-v-df78435e]{margin-top:20px;display:flex;justify-content:right;align-items:center;gap:12px}.btn.el-button[data-v-df78435e]{padding:12px 24px;border:none;border-radius:8px;cursor:pointer;font-size:14px;font-weight:500;transition:all .2s ease}.btn.el-button--primary[data-v-df78435e]{background:linear-gradient(135deg,#6366f1 0%,#8b5cf6 100%);color:#fff}.btn.el-button--primary[data-v-df78435e]:hover{background:linear-gradient(135deg,#5b21b6 0%,#7c3aed 100%);transform:translateY(-1px)}.btn.el-button--secondary[data-v-df78435e]{background:linear-gradient(135deg,#f8fafc 0%,#e2e8f0 100%);color:#475569;border:2px solid #cbd5e1}.btn.el-button--secondary[data-v-df78435e]:hover:not(:disabled){background:linear-gradient(135deg,#e2e8f0 0%,#cbd5e1 100%);border-color:#94a3b8;transform:translateY(-1px)}.btn.el-button[data-v-df78435e]:disabled{opacity:.6;cursor:not-allowed;transform:none}.guidance[data-v-df78435e]{font-size:12px;color:#909399;margin-top:5px;line-height:1.5}.form[data-v-df78435e]{margin-top:20px}.xz-input[data-v-df78435e]{border:#d9d9d9 1px solid;margin-bottom:10px;padding:5px;margin-top:5px}.aria2-tip[data-v-5e02a151]{padding:15px 20px;position:absolute;top:30px;left:50%;transform:translate(-50%);color:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;font-size:14px;z-index:9999;min-width:300px;text-align:center;display:flex;align-items:center;gap:10px}.aria2-tip--success[data-v-5e02a151]{background:rgba(103,194,58,.9)}.aria2-tip--error[data-v-5e02a151]{background:rgba(245,108,108,.9)}.aria2-tip--warning[data-v-5e02a151]{background:rgba(230,162,60,.9)}.aria2-tip--info[data-v-5e02a151]{background:rgba(64,158,255,.9)}.aria2-tip__icon[data-v-5e02a151]{font-size:18px;font-weight:700;flex-shrink:0}.aria2-tip__content[data-v-5e02a151]{flex:1}.floating-window[data-v-4681666b]{position:fixed;z-index:9999;-webkit-user-select:none;user-select:none;transition:all .2s ease}.floating-window.dragging[data-v-4681666b]{transition:none}.download-button[data-v-4681666b]{display:flex;align-items:center;justify-content:center;width:50px;height:50px;padding:0;background:linear-gradient(135deg,#409eff,#66b1ff);border-radius:50%;cursor:pointer;box-shadow:0 4px 12px #409eff4d;color:#fff;transition:all .3s ease}.download-button[data-v-4681666b]:hover{transform:scale(1.05);box-shadow:0 6px 16px #409eff66}.download-button[data-v-4681666b]:active{transform:scale(.95)}@media (max-width: 768px){.main-button[data-v-4681666b]{width:45px;height:45px}.options[data-v-4681666b]{left:55px;min-width:110px}.option[data-v-4681666b]{padding:8px 12px}.option span[data-v-4681666b]{font-size:13px}} ');

(function(vue) {
  "use strict";
  function getPlatform() {
    let u = navigator.userAgent;
    let isAndroid = u.indexOf("Android") > -1 || u.indexOf("Adr") > -1;
    let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
    if (isAndroid) {
      return "Android";
    } else if (isIOS) {
      return "IOS";
    } else {
      return "PC";
    }
  }
  var monkeyWindow = window;
  var GM_xmlhttpRequest = /* @__PURE__ */ (() => monkeyWindow.GM_xmlhttpRequest)();
  function post(url, data, headers, type) {
    data = JSON.stringify(data);
    return new Promise((resolve, reject) => {
      GM_xmlhttpRequest({
        method: "POST",
        url,
        headers,
        data,
        responseType: type || "json",
        onload: (res) => {
          type === "blob" ? resolve(res) : res.response ? resolve(res.response || res.responseText) : reject(res);
        },
        onerror: (err) => {
          reject(err);
        }
      });
    });
  }
  function postData(url = "", data = {}, customHeaders = {}, method = "GET") {
    ({
      method,
      // *GET, POST, PUT, DELETE, etc.
      mode: "cors",
      // no-cors, *cors, same-origin
      cache: "no-cache",
      // *default, no-cache, reload, force-cache, only-if-cached
      credentials: "same-origin",
      // include, *same-origin, omit
      headers: {
        "Content-Type": "application/json",
        // 'Content-Type': 'application/x-www-form-urlencoded',
        ...customHeaders
      },
      redirect: "follow",
      // manual, *follow, error
      referrerPolicy: "no-referrer"
    });
    if (method === "GET") {
      return fetch(url, {
        method: "GET",
        // *GET, POST, PUT, DELETE, etc.
        mode: "cors",
        // no-cors, *cors, same-origin
        cache: "no-cache",
        // *default, no-cache, reload, force-cache, only-if-cached
        credentials: "same-origin",
        // include, *same-origin, omit
        headers: {
          "Content-Type": "application/json",
          // 'Content-Type': 'application/x-www-form-urlencoded',
          ...customHeaders
        },
        redirect: "follow",
        // manual, *follow, error
        referrerPolicy: "no-referrer"
        // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
      }).then((response) => response.json());
    } else {
      return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
          if (xhr.readyState === 4) {
            if (xhr.status === 200) {
              resolve(JSON.parse(xhr.response));
            } else {
              reject({});
            }
          }
        };
        xhr.open(method, url);
        xhr.setRequestHeader("content-type", "application/json");
        xhr.send(JSON.stringify(data));
      });
    }
  }
  function getHeader() {
    let token = "";
    let captcha = "";
    for (let i = 0; i < 40; i++) {
      let key = window.localStorage.key(i);
      if (key === null)
        break;
      if (key && key.startsWith("credentials")) {
        let tokenData = JSON.parse(window.localStorage.getItem(key));
        token = tokenData.token_type + " " + tokenData.access_token;
        continue;
      }
      if (key && key.startsWith("captcha")) {
        let tokenData = JSON.parse(window.localStorage.getItem(key));
        captcha = tokenData.captcha_token;
      }
    }
    return {
      Authorization: token,
      "x-device-id": window.localStorage.getItem("deviceid"),
      "x-captcha-token": captcha
    };
  }
  function getList(parent_id) {
    let url = `https://api-drive.mypikpak.com/drive/v1/files?thumbnail_size=SIZE_MEDIUM&limit=500&parent_id=${parent_id}&with_audit=true&filters=%7B%22phase%22%3A%7B%22eq%22%3A%22PHASE_TYPE_COMPLETE%22%7D%2C%22trashed%22%3A%7B%22eq%22%3Afalse%7D%7D`;
    return postData(url, {}, getHeader());
  }
  function getDownload(id) {
    for (let i = 0; i < 40; i++) {
      let key = window.localStorage.key(i);
      if (key === null)
        break;
      if (key && key.startsWith("credentials")) {
        let tokenData = JSON.parse(window.localStorage.getItem(key));
        tokenData.token_type + " " + tokenData.access_token;
        continue;
      }
      if (key && key.startsWith("captcha")) {
        let tokenData = JSON.parse(window.localStorage.getItem(key));
        tokenData.captcha_token;
      }
    }
    let header = getHeader();
    return postData("https://api-drive.mypikpak.com/drive/v1/files/" + id + "?", {}, header);
  }
  function pushToAria(url, data) {
    if (["Android", "IOS"].includes(getPlatform()) && !GM_xmlhttpRequest) {
      return postData(url, data, {}, "POST");
    } else {
      return post(url, data, {}, "");
    }
  }
  for (let i = 0; i < 999; i++) {
    let key = window.localStorage.key(i);
    console.log(key);
  }
  const AriaDownloadDialog_vue_vue_type_style_index_0_scoped_a2749c9c_lang = "";
  const _export_sfc = (sfc, props) => {
    const target = sfc.__vccOpts || sfc;
    for (const [key, val] of props) {
      target[key] = val;
    }
    return target;
  };
  const _withScopeId$2 = (n) => (vue.pushScopeId("data-v-a2749c9c"), n = n(), vue.popScopeId(), n);
  const _hoisted_1$3 = {
    key: 0,
    style: { "width": "60%" },
    class: "dialog"
  };
  const _hoisted_2$3 = /* @__PURE__ */ _withScopeId$2(() => /* @__PURE__ */ vue.createElementVNode("h2", null, "请勾选你要下载的", -1));
  const _hoisted_3$2 = { class: "toolbar" };
  const _hoisted_4$2 = { for: "checkbox" };
  const _hoisted_5$2 = { class: "sort-options" };
  const _hoisted_6$2 = /* @__PURE__ */ _withScopeId$2(() => /* @__PURE__ */ vue.createElementVNode("label", { for: "sort-by" }, "排序方式:", -1));
  const _hoisted_7$1 = /* @__PURE__ */ vue.createStaticVNode('<option value="name" data-v-a2749c9c>名称</option><option value="created_time" data-v-a2749c9c>创建时间</option><option value="modified_time" data-v-a2749c9c>修改时间</option><option value="size" data-v-a2749c9c>大小</option><option value="file_category" data-v-a2749c9c>文件类型</option>', 5);
  const _hoisted_12$1 = [
    _hoisted_7$1
  ];
  const _hoisted_13$1 = /* @__PURE__ */ _withScopeId$2(() => /* @__PURE__ */ vue.createElementVNode("option", { value: "asc" }, "升序", -1));
  const _hoisted_14$1 = /* @__PURE__ */ _withScopeId$2(() => /* @__PURE__ */ vue.createElementVNode("option", { value: "desc" }, "降序", -1));
  const _hoisted_15$1 = [
    _hoisted_13$1,
    _hoisted_14$1
  ];
  const _hoisted_16 = { class: "movies" };
  const _hoisted_17 = ["id", "value"];
  const _hoisted_18 = { class: "icon" };
  const _hoisted_19 = { class: "file-info" };
  const _hoisted_20 = { class: "connection-status" };
  const _hoisted_21 = { class: "status-indicator" };
  const _hoisted_22 = { class: "status-text" };
  const _hoisted_23 = ["disabled"];
  const _sfc_main$4 = {
    __name: "AriaDownloadDialog",
    props: {
      show: Boolean
    },
    emits: ["close", "msg", "openConfig"],
    setup(__props, { emit: __emit }) {
      const props = __props;
      const emits = __emit;
      const list = vue.ref([]);
      const selected = vue.ref([]);
      const checkedAll = vue.ref(false);
      const selectedItems = vue.ref([]);
      const isForbidden = vue.ref(false);
      const sortBy = vue.ref("name");
      const sortDirection = vue.ref("asc");
      const connectionState = vue.ref("unknown");
      const isTestingConnection = vue.ref(false);
      const connectionStatus = vue.computed(() => {
        switch (connectionState.value) {
          case "connected":
            return { class: "connected", text: "Aria2连接正常" };
          case "disconnected":
            return { class: "disconnected", text: "Aria2连接失败" };
          case "testing":
            return { class: "testing", text: "正在测试连接..." };
          default:
            return { class: "unknown", text: "Aria2连接状态未知" };
        }
      });
      vue.watch(
        () => props.show,
        (val) => {
          if (val) {
            const tempList = [];
            let parent_id = window.location.href.split("/").pop();
            if (parent_id == "all")
              parent_id = "";
            emits("msg", "开始加载文件列表,请稍等", "info");
            getList(parent_id).then((res) => {
              res.files.forEach((item) => {
                tempList.push({ id: item.id, name: item.name, type: item.kind, created_time: item.created_time, modified_time: item.modified_time, size: item.size, file_category: item.file_category });
              });
              list.value = tempList;
              sortList();
            }).finally(() => {
              emits("msg", "文件列表加载完成", "success");
            });
            setTimeout(() => {
              testConnection();
            }, 500);
          }
        }
      );
      const close = () => {
        selected.value = [];
        checkedAll.value = false;
        isForbidden.value = false;
        emits("close");
      };
      const openConfig = () => {
        emits("openConfig");
      };
      const testConnection = async () => {
        if (isTestingConnection.value)
          return;
        isTestingConnection.value = true;
        connectionState.value = "testing";
        try {
          const host = window.localStorage.getItem("ariaHost") || "";
          const token = window.localStorage.getItem("ariaToken") || "";
          if (!host) {
            throw new Error("请先配置Aria2 RPC地址");
          }
          const payload = {
            jsonrpc: "2.0",
            method: "aria2.getVersion",
            id: 1,
            params: token ? [`token:${token}`] : []
          };
          const response = await pushToAria(host, payload);
          if (response && response.result) {
            connectionState.value = "connected";
            emits("msg", "Aria2连接测试成功", "success");
          } else {
            connectionState.value = "disconnected";
            emits("msg", "Aria2连接失败,请检查配置", "error");
          }
        } catch (error) {
          connectionState.value = "disconnected";
          emits("msg", `Aria2连接测试失败: ${error.message}`, "error");
        } finally {
          isTestingConnection.value = false;
        }
      };
      vue.onMounted(() => {
        setTimeout(() => {
          testConnection();
        }, 1e3);
      });
      const onCheckAll = () => {
        if (checkedAll.value) {
          selected.value = list.value.map((item, index) => index);
        } else {
          selected.value = [];
        }
      };
      const onCheck = () => {
        checkedAll.value = selected.value.length === list.value.length;
      };
      const sortList = () => {
        list.value.sort((a, b) => {
          if (a.type === "drive#folder" && b.type !== "drive#folder") {
            return -1;
          }
          if (a.type !== "drive#folder" && b.type === "drive#folder") {
            return 1;
          }
          let aValue = a[sortBy.value];
          let bValue = b[sortBy.value];
          if (sortBy.value === "size") {
            aValue = parseInt(aValue);
            bValue = parseInt(bValue);
          } else if (sortBy.value === "created_time" || sortBy.value === "modified_time") {
            aValue = new Date(aValue).getTime();
            bValue = new Date(bValue).getTime();
          }
          let comparison = 0;
          if (aValue > bValue) {
            comparison = 1;
          } else if (aValue < bValue) {
            comparison = -1;
          }
          return sortDirection.value === "asc" ? comparison : -comparison;
        });
        updateSelectedIndices();
      };
      const formatBytes = (bytes, decimals = 2) => {
        if (bytes === 0)
          return "0 Bytes";
        const k = 1024;
        const dm = decimals < 0 ? 0 : decimals;
        const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
      };
      const formatFileInfo = (item) => {
        switch (sortBy.value) {
          case "size":
            return item.size ? formatBytes(parseInt(item.size)) : "N/A";
          case "created_time":
            return item.created_time ? new Date(item.created_time).toLocaleString() : "N/A";
          case "modified_time":
            return item.modified_time ? new Date(item.modified_time).toLocaleString() : "N/A";
          case "file_category":
            return item.file_category || "N/A";
          default:
            return "";
        }
      };
      const updateSelectedIndices = () => {
        const currentlySelectedIds = new Set(selected.value.map((index) => list.value[index].id));
        selected.value = [];
        list.value.forEach((item, index) => {
          if (currentlySelectedIds.has(item.id)) {
            selected.value.push(index);
          }
        });
      };
      const getAllList = async () => {
        emits("msg", "开始获取文件内容", "info");
        const initialSelectedItems = [];
        for (const index of selected.value) {
          initialSelectedItems.push(list.value[index]);
        }
        const allFiles = [];
        const foldersToProcess = [];
        initialSelectedItems.forEach((item) => {
          if (item.type === "drive#folder") {
            foldersToProcess.push({ id: item.id, name: item.name, path: item.name });
          } else {
            allFiles.push({ ...item, path: "" });
          }
        });
        let processedCount = 0;
        while (foldersToProcess.length > 0) {
          const currentFolder = foldersToProcess.shift();
          processedCount++;
          emits("msg", `正在扫描第 ${processedCount} 个文件夹: ${currentFolder.name}`, "info");
          try {
            const result = await getList(currentFolder.id);
            if (result.files) {
              for (const file of result.files) {
                if (file.kind === "drive#folder") {
                  foldersToProcess.push({ id: file.id, name: file.name, path: `${currentFolder.path}/${file.name}` });
                } else {
                  allFiles.push({ ...file, path: currentFolder.path });
                }
              }
            }
          } catch (e) {
            emits("msg", `获取文件夹 ${currentFolder.name} 内容失败`, "error");
            console.error(e);
          }
        }
        selectedItems.value = allFiles;
        emits("msg", `文件获取完毕,共${allFiles.length}个文件。`, "success");
      };
      const pushBefore = async () => {
        if (!isForbidden.value) {
          isForbidden.value = true;
          await getAllList();
          push();
        } else {
          emits("msg", "已经开始推送了", "warning");
        }
      };
      const push = async () => {
        let total = selectedItems.value.length;
        let success = 0;
        let fail = 0;
        let ariaHost = window.localStorage.getItem("ariaHost") || "";
        let ariaPath = window.localStorage.getItem("ariaPath") || "";
        let ariaToken = window.localStorage.getItem("ariaToken") || "";
        let ariaParams = window.localStorage.getItem("ariaParams") || "";
        let errorMSG = "";
        let retryList = [];
        if (!ariaHost) {
          emits("msg", "请先配置aria2", "error");
          close();
          return;
        }
        console.log(`共${selectedItems.value.length}个项目`);
        let testIndex = 0;
        for (let item of selectedItems.value) {
          getDownload(item.id).then((res) => {
            if (res.error_description) {
              emits("msg", `失败原因: ${res.error_description} 请刷新!`, "error");
              return;
            }
            emits("msg", `第${testIndex + 1}个项目下载链接获取成功`, "success");
            console.log(`第${testIndex + 1}个项目下载链接获取成功`);
            let ariaData = {
              id: (/* @__PURE__ */ new Date()).getTime(),
              jsonrpc: "2.0",
              method: "aria2.addUri",
              params: [
                [res.web_content_link],
                { out: res.name }
              ]
            };
            if (ariaPath) {
              ariaData.params[1].dir = ariaPath + (item.path || "");
            }
            if (ariaParams) {
              const customParams = ariaParams.split(";");
              customParams.forEach((item2) => {
                const customParam = item2.split("=");
                ariaData.params[1][customParam[0]] = customParam[1];
              });
            }
            ariaToken && ariaData.params.unshift(`token:${ariaToken}`);
            pushToAria(ariaHost, ariaData).then((ariares2) => {
              let resoj = ariares2;
              if (typeof ariares2 === "string") {
                resoj = JSON.parse(ariares2);
              }
              if (resoj.result) {
                success++;
              } else {
                console.log(resoj);
                console.log(ariaData);
                errorMSG = resoj.error.message === "Unauthorized" ? "密钥不对" : "推送失败";
                fail++;
              }
            }).catch((e) => {
              console.warn(e);
              console.log(ariares);
              console.log(ariaData);
              errorMSG = `${e.statusText} 请检测配置`;
              emits("msg", `失败原因: ${e.statusText}`, "error");
              fail++;
            }).finally(() => {
              total--;
              if (total === 0) {
                const resultType = fail === 0 ? "success" : success === 0 ? "error" : "warning";
                emits("msg", `成功:${success} 失败: ${fail} ${fail !== 0 ? "失败原因:" + errorMSG : ""}`, resultType);
                console.info(`成功:${success} 失败: ${fail} ${fail !== 0 ? "失败原因:" + errorMSG : ""}`);
                if (retryList.length > 0) {
                  console.log(retryList);
                  emits("msg", `即将重试${retryList.length}个项目`, "warning");
                  console.log(`即将重试${retryList.length}个项目`);
                  selectedItems.value = retryList;
                  retryList = [];
                  push();
                } else {
                  close();
                }
              }
            });
          }).catch((e) => {
            console.warn(`第${testIndex + 1}个项目下载链接获取失败`);
            retryList.push(selectedItems.value[testIndex]);
            fail++;
            total--;
          }).finally(() => {
            testIndex++;
          });
        }
      };
      return (_ctx, _cache) => {
        return __props.show ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, [
          _hoisted_2$3,
          vue.createElementVNode("div", {
            class: "close",
            onClick: close
          }, "×"),
          vue.createElementVNode("div", _hoisted_3$2, [
            vue.createElementVNode("label", _hoisted_4$2, [
              vue.withDirectives(vue.createElementVNode("input", {
                onChange: onCheckAll,
                type: "checkbox",
                id: "checkbox",
                "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => checkedAll.value = $event)
              }, null, 544), [
                [vue.vModelCheckbox, checkedAll.value]
              ]),
              vue.createTextVNode(" 全选 ")
            ]),
            vue.createElementVNode("div", _hoisted_5$2, [
              _hoisted_6$2,
              vue.withDirectives(vue.createElementVNode("select", {
                id: "sort-by",
                "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => sortBy.value = $event),
                onChange: sortList
              }, _hoisted_12$1, 544), [
                [vue.vModelSelect, sortBy.value]
              ]),
              vue.withDirectives(vue.createElementVNode("select", {
                id: "sort-direction",
                "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => sortDirection.value = $event),
                onChange: sortList
              }, _hoisted_15$1, 544), [
                [vue.vModelSelect, sortDirection.value]
              ])
            ])
          ]),
          vue.createElementVNode("ul", _hoisted_16, [
            (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(list.value, (item, index) => {
              return vue.openBlock(), vue.createElementBlock("li", {
                key: item.id
              }, [
                vue.withDirectives(vue.createElementVNode("input", {
                  onChange: onCheck,
                  type: "checkbox",
                  id: item.id,
                  value: index,
                  "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => selected.value = $event)
                }, null, 40, _hoisted_17), [
                  [vue.vModelCheckbox, selected.value]
                ]),
                vue.createElementVNode("span", _hoisted_18, vue.toDisplayString(item.type === "drive#folder" ? "📁" : "📄"), 1),
                vue.createElementVNode("span", null, vue.toDisplayString(item.name), 1),
                vue.createElementVNode("span", _hoisted_19, vue.toDisplayString(formatFileInfo(item)), 1)
              ]);
            }), 128))
          ]),
          vue.createElementVNode("div", _hoisted_20, [
            vue.createElementVNode("div", _hoisted_21, [
              vue.createElementVNode("div", {
                class: vue.normalizeClass(["status-dot", connectionStatus.value.class])
              }, null, 2),
              vue.createElementVNode("span", _hoisted_22, vue.toDisplayString(connectionStatus.value.text), 1)
            ]),
            vue.createElementVNode("button", {
              class: "test-btn",
              onClick: testConnection,
              disabled: isTestingConnection.value
            }, vue.toDisplayString(isTestingConnection.value ? "测试中..." : "测试连接"), 9, _hoisted_23)
          ]),
          vue.createElementVNode("div", { class: "footer" }, [
            vue.createElementVNode("div", {
              class: "btn el-button el-button--secondary",
              onClick: openConfig
            }, "配置aria2"),
            vue.createElementVNode("div", {
              class: "btn el-button el-button--primary",
              onClick: pushBefore
            }, "推送到aria2")
          ])
        ])) : vue.createCommentVNode("", true);
      };
    }
  };
  const AriaDownloadDialog = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-a2749c9c"]]);
  const AriaConfigDialog_vue_vue_type_style_index_0_scoped_df78435e_lang = "";
  const _withScopeId$1 = (n) => (vue.pushScopeId("data-v-df78435e"), n = n(), vue.popScopeId(), n);
  const _hoisted_1$2 = {
    key: 0,
    style: { "width": "400px" },
    class: "dialog"
  };
  const _hoisted_2$2 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("h2", null, "请配置你的aria2", -1));
  const _hoisted_3$1 = { class: "connection-status" };
  const _hoisted_4$1 = { class: "status-indicator" };
  const _hoisted_5$1 = { class: "status-text" };
  const _hoisted_6$1 = ["disabled"];
  const _hoisted_7 = { class: "config-list" };
  const _hoisted_8 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "label" }, "RPC地址", -1));
  const _hoisted_9 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("p", { class: "guidance" }, "Aria2 RPC服务的地址,通常是 `http://127.0.0.1:6800/jsonrpc`。如果你在Docker中运行,可能需要使用宿主机的IP地址。", -1));
  const _hoisted_10 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "label" }, "RPC密钥", -1));
  const _hoisted_11 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("p", { class: "guidance" }, "Aria2 RPC的密钥,如果你在Aria2配置中设置了 `rpc-secret`,请在此填写。如果没有设置,请留空。", -1));
  const _hoisted_12 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "label" }, "下载路径", -1));
  const _hoisted_13 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("p", { class: "guidance" }, "文件在服务器上的保存路径。例如:`/downloads/` (Linux) 或 `D:\\Downloads` (Windows)\\。请确保Aria2有写入该目录的权限。", -1));
  const _hoisted_14 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "label" }, "其他参数", -1));
  const _hoisted_15 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("p", { class: "guidance" }, "Aria2的额外参数,以分号 `;` 分隔,例如 `user-agent=Mozilla;split=10`。这些参数会直接传递给Aria2。", -1));
  const _sfc_main$3 = {
    __name: "AriaConfigDialog",
    props: {
      show: Boolean
    },
    emits: ["close", "msg"],
    setup(__props, { emit: __emit }) {
      const emits = __emit;
      const close = () => {
        emits("close");
      };
      const form = vue.reactive({
        host: window.localStorage.getItem("ariaHost") || "",
        path: window.localStorage.getItem("ariaPath") || "",
        token: window.localStorage.getItem("ariaToken") || "",
        params: window.localStorage.getItem("ariaParams") || ""
      });
      const connectionState = vue.ref("unknown");
      const isTestingConnection = vue.ref(false);
      const connectionStatus = vue.computed(() => {
        switch (connectionState.value) {
          case "connected":
            return { class: "connected", text: "Aria2连接正常" };
          case "disconnected":
            return { class: "disconnected", text: "Aria2连接失败" };
          case "testing":
            return { class: "testing", text: "正在测试连接..." };
          default:
            return { class: "unknown", text: "连接状态未知" };
        }
      });
      const testConnection = async () => {
        if (!form.host) {
          emits("msg", "请先填写RPC地址", "warning");
          return;
        }
        isTestingConnection.value = true;
        connectionState.value = "testing";
        try {
          const rpcUrl = form.host;
          const rpcToken = form.token ? `token:${form.token}` : "";
          const payload = {
            jsonrpc: "2.0",
            method: "aria2.getVersion",
            id: 1,
            params: rpcToken ? [rpcToken] : []
          };
          const response = await pushToAria(rpcUrl, payload);
          if (response && response.result) {
            connectionState.value = "connected";
            emits("msg", `Aria2连接成功!`, "success");
          } else {
            connectionState.value = "disconnected";
            emits("msg", "Aria2连接失败,请检查配置", "error");
          }
        } catch (error) {
          console.error("Aria2连接测试失败:", error);
          connectionState.value = "disconnected";
          emits("msg", `连接失败: ${error.message || "请检查RPC地址和密钥"}`, "error");
        } finally {
          isTestingConnection.value = false;
        }
      };
      const save = async () => {
        if (form.path && !form.path.endsWith("/") && !form.path.endsWith("\\")) {
          form.path += "/";
        }
        window.localStorage.setItem("ariaHost", form.host);
        window.localStorage.setItem("ariaPath", form.path);
        window.localStorage.setItem("ariaToken", form.token);
        window.localStorage.setItem("ariaParams", form.params);
        emits("msg", "配置保存成功!", "success");
        close();
      };
      vue.onMounted(() => {
        if (form.host) {
          testConnection();
        }
      });
      return (_ctx, _cache) => {
        return __props.show ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2, [
          _hoisted_2$2,
          vue.createElementVNode("div", {
            class: "close",
            onClick: close
          }, "×"),
          vue.createElementVNode("div", _hoisted_3$1, [
            vue.createElementVNode("div", _hoisted_4$1, [
              vue.createElementVNode("div", {
                class: vue.normalizeClass(["status-dot", connectionStatus.value.class])
              }, null, 2),
              vue.createElementVNode("span", _hoisted_5$1, vue.toDisplayString(connectionStatus.value.text), 1)
            ]),
            vue.createElementVNode("button", {
              class: "test-btn",
              onClick: testConnection,
              disabled: isTestingConnection.value
            }, vue.toDisplayString(isTestingConnection.value ? "测试中..." : "测试连接"), 9, _hoisted_6$1)
          ]),
          vue.createElementVNode("ul", _hoisted_7, [
            vue.createElementVNode("li", null, [
              _hoisted_8,
              vue.withDirectives(vue.createElementVNode("input", {
                "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => form.host = $event),
                type: "text",
                placeholder: "http://127.0.0.1:6800/jsonrpc"
              }, null, 512), [
                [vue.vModelText, form.host]
              ]),
              _hoisted_9
            ]),
            vue.createElementVNode("li", null, [
              _hoisted_10,
              vue.withDirectives(vue.createElementVNode("input", {
                "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => form.token = $event),
                type: "text",
                placeholder: "没有请留空"
              }, null, 512), [
                [vue.vModelText, form.token]
              ]),
              _hoisted_11
            ]),
            vue.createElementVNode("li", null, [
              _hoisted_12,
              vue.withDirectives(vue.createElementVNode("input", {
                "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => form.path = $event),
                type: "text",
                placeholder: "C:/Users/admin/Downloads/"
              }, null, 512), [
                [vue.vModelText, form.path]
              ]),
              _hoisted_13
            ]),
            vue.createElementVNode("li", null, [
              _hoisted_14,
              vue.withDirectives(vue.createElementVNode("input", {
                "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => form.params = $event),
                type: "text",
                placeholder: "user-agent=xxx;header=xxx"
              }, null, 512), [
                [vue.vModelText, form.params]
              ]),
              _hoisted_15
            ])
          ]),
          vue.createElementVNode("div", { class: "footer" }, [
            vue.createElementVNode("div", {
              class: "btn el-button el-button--primary",
              onClick: save
            }, "保存")
          ])
        ])) : vue.createCommentVNode("", true);
      };
    }
  };
  const AriaConfigDialog = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-df78435e"]]);
  const Aria2Toast_vue_vue_type_style_index_0_scoped_5e02a151_lang = "";
  const _hoisted_1$1 = { class: "aria2-tip__icon" };
  const _hoisted_2$1 = { key: 0 };
  const _hoisted_3 = { key: 1 };
  const _hoisted_4 = { key: 2 };
  const _hoisted_5 = { key: 3 };
  const _hoisted_6 = { class: "aria2-tip__content" };
  const _sfc_main$2 = {
    __name: "Aria2Toast",
    setup(__props, { expose: __expose }) {
      const show = vue.ref(false);
      const type = vue.ref("info");
      let timer = null;
      const open = (toastType = "info") => {
        if (timer) {
          clearTimeout(timer);
        }
        type.value = toastType;
        show.value = true;
        timer = setTimeout(() => {
          show.value = false;
        }, 3e3);
      };
      __expose({ open });
      return (_ctx, _cache) => {
        return show.value ? (vue.openBlock(), vue.createElementBlock("div", {
          key: 0,
          class: vue.normalizeClass(["aria2-tip", `aria2-tip--${type.value}`])
        }, [
          vue.createElementVNode("div", _hoisted_1$1, [
            type.value === "success" ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_2$1, "✓")) : type.value === "error" ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_3, "✕")) : type.value === "warning" ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_4, "⚠")) : type.value === "info" ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_5, "ℹ")) : vue.createCommentVNode("", true)
          ]),
          vue.createElementVNode("div", _hoisted_6, [
            vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
          ])
        ], 2)) : vue.createCommentVNode("", true);
      };
    }
  };
  const Aria2Toast = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-5e02a151"]]);
  const FloatingWindow_vue_vue_type_style_index_0_scoped_4681666b_lang = "";
  const _withScopeId = (n) => (vue.pushScopeId("data-v-4681666b"), n = n(), vue.popScopeId(), n);
  const _hoisted_1 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("svg", {
    width: "24",
    height: "24",
    viewBox: "0 0 24 24",
    fill: "currentColor"
  }, [
    /* @__PURE__ */ vue.createElementVNode("path", { d: "M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" })
  ], -1));
  const _hoisted_2 = [
    _hoisted_1
  ];
  const _sfc_main$1 = {
    __name: "FloatingWindow",
    props: {
      show: {
        type: Boolean,
        default: true
      }
    },
    emits: ["download"],
    setup(__props, { emit: __emit }) {
      const emit = __emit;
      const floatingWindow = vue.ref(null);
      const isDragging = vue.ref(false);
      const dragOffset = vue.ref({ x: 0, y: 0 });
      const position = vue.ref({ x: 0, y: 150 });
      const hasDragged = vue.ref(false);
      const startDrag = (e) => {
        isDragging.value = true;
        hasDragged.value = false;
        const rect = floatingWindow.value.getBoundingClientRect();
        dragOffset.value = {
          x: e.clientX - rect.left,
          y: e.clientY - rect.top
        };
        document.addEventListener("mousemove", onDrag);
        document.addEventListener("mouseup", stopDrag);
        e.preventDefault();
      };
      const onDrag = (e) => {
        if (!isDragging.value)
          return;
        hasDragged.value = true;
        const newX = e.clientX - dragOffset.value.x;
        const newY = e.clientY - dragOffset.value.y;
        const maxX = window.innerWidth - floatingWindow.value.offsetWidth;
        const maxY = window.innerHeight - floatingWindow.value.offsetHeight;
        position.value.x = Math.max(0, Math.min(newX, maxX));
        position.value.y = Math.max(0, Math.min(newY, maxY));
      };
      const stopDrag = () => {
        isDragging.value = false;
        document.removeEventListener("mousemove", onDrag);
        document.removeEventListener("mouseup", stopDrag);
      };
      const handleDownload = (e) => {
        e.stopPropagation();
        e.preventDefault();
        if (!hasDragged.value && !isDragging.value) {
          emit("download");
        }
      };
      const adjustPosition = () => {
        const maxX = window.innerWidth - 60;
        const maxY = window.innerHeight - 60;
        position.value.x = Math.max(0, Math.min(position.value.x, maxX));
        position.value.y = Math.max(0, Math.min(position.value.y, maxY));
      };
      const handleResize = () => {
        adjustPosition();
      };
      vue.onMounted(() => {
        position.value.x = window.innerWidth - 80;
        position.value.y = 150;
        adjustPosition();
        window.addEventListener("resize", handleResize);
      });
      vue.onUnmounted(() => {
        document.removeEventListener("mousemove", onDrag);
        document.removeEventListener("mouseup", stopDrag);
        window.removeEventListener("resize", handleResize);
      });
      return (_ctx, _cache) => {
        return __props.show ? (vue.openBlock(), vue.createElementBlock("div", {
          key: 0,
          ref_key: "floatingWindow",
          ref: floatingWindow,
          class: vue.normalizeClass(["floating-window", { dragging: isDragging.value }]),
          style: vue.normalizeStyle({ left: position.value.x + "px", top: position.value.y + "px" })
        }, [
          vue.createElementVNode("div", {
            class: "download-button",
            onClick: handleDownload,
            onMousedown: vue.withModifiers(startDrag, ["stop"])
          }, _hoisted_2, 32)
        ], 6)) : vue.createCommentVNode("", true);
      };
    }
  };
  const FloatingWindow = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-4681666b"]]);
  const App_vue_vue_type_style_index_0_scoped_efdfc046_lang = "";
  const _sfc_main = {
    __name: "App",
    setup(__props) {
      const downloadShow = vue.ref(false);
      const configShow = vue.ref(false);
      const tip = vue.ref("");
      const toastRef = vue.ref(null);
      const showPlugin = vue.ref(false);
      const showToast = (val, type = "info") => {
        tip.value = val;
        toastRef.value.open(type);
      };
      if (location.pathname !== "/") {
        showPlugin.value = true;
      }
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
          showPlugin.value ? (vue.openBlock(), vue.createBlock(FloatingWindow, {
            key: 0,
            onDownload: _cache[0] || (_cache[0] = ($event) => downloadShow.value = true)
          })) : vue.createCommentVNode("", true),
          vue.createVNode(AriaDownloadDialog, {
            show: downloadShow.value,
            onClose: _cache[1] || (_cache[1] = ($event) => downloadShow.value = false),
            onOpenConfig: _cache[2] || (_cache[2] = ($event) => configShow.value = true),
            onMsg: showToast
          }, null, 8, ["show"]),
          vue.createVNode(AriaConfigDialog, {
            show: configShow.value,
            onClose: _cache[3] || (_cache[3] = ($event) => configShow.value = false),
            onMsg: showToast
          }, null, 8, ["show"]),
          vue.createVNode(Aria2Toast, {
            ref_key: "toastRef",
            ref: toastRef
          }, {
            default: vue.withCtx(() => [
              vue.createTextVNode(vue.toDisplayString(tip.value), 1)
            ]),
            _: 1
          }, 512)
        ], 64);
      };
    }
  };
  const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-efdfc046"]]);
  document.cookie = "pp_access_to_visit=true";
  setTimeout(() => {
    vue.createApp(App).mount(
      (() => {
        let pikpakContainer = document.getElementById("app");
        const app = document.createElement("div");
        document.body.insertBefore(app, pikpakContainer);
        return app;
      })()
    );
  }, 1e3);
})(Vue);

QingJ © 2025

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