Bilibili File

一款基于哔哩哔哩弹幕网(B站)的文件托管插件( ̄▽ ̄)

  1. // ==UserScript==
  2. // @name Bilibili File
  3. // @namespace npm/bilibili-file
  4. // @version 1.1.0
  5. // @author https://github.com/WJZ-P
  6. // @description 一款基于哔哩哔哩弹幕网(B站)的文件托管插件( ̄▽ ̄)
  7. // @license Eclipse Public License 2.0
  8. // @icon https://i0.hdslb.com/bfs/material_up/12d89bc3fa38ffd23e1e8bad1e26037ddcf2f152.png
  9. // @match https://www.bilibili.com/*
  10. // @require https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/3.2.31/vue.runtime.global.prod.min.js
  11. // @grant GM_addStyle
  12. // ==/UserScript==
  13.  
  14. (e=>{if(typeof GM_addStyle=="function"){GM_addStyle(e);return}const a=document.createElement("style");a.textContent=e,document.head.append(a)})(" .cyber-title[data-v-f31f94ef]{position:relative;text-align:center;margin:2rem 0;perspective:1000px;width:fit-content;display:flex;justify-content:center}.gradient-text[data-v-f31f94ef]{font-size:3.5rem;font-weight:900;background:linear-gradient(90deg,#00aeec,#7be7ff,#00aeec,#7be7ff,#00aeec);background-size:200% auto;-webkit-background-clip:text;-webkit-text-fill-color:transparent;animation:gradient-f31f94ef 4s linear infinite;display:inline-block;transform:translateZ(0);transition:transform .3s;width:fit-content}.glow[data-v-f31f94ef]{position:absolute;top:0;left:50%;transform:translate(-50%);width:80%;height:100%;background:radial-gradient(circle at 50% 50%,rgba(0,174,236,.4) 0%,transparent 70%);filter:blur(30px);z-index:-1}@keyframes gradient-f31f94ef{0%{background-position:0% center}to{background-position:-200% center}}.cyber-title:hover .gradient-text[data-v-f31f94ef]{transform:scale(1.05) rotateX(10deg) rotateY(-5deg);text-shadow:0 10px 20px rgba(0,174,236,.4)}.main-menu[data-v-f31f94ef]{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%}.file-manager[data-v-f31f94ef]{display:flex;flex-direction:column;width:95%;margin:20px auto;background:#fff;border-radius:12px;box-shadow:0 4px 12px #0000001a;padding:20px;height:calc(100vh - 150px);justify-content:flex-start;align-items:center;box-sizing:border-box}.action-bar[data-v-f31f94ef]{width:100%;display:flex;gap:20px;margin-bottom:30px;justify-content:center;align-items:center}.upload-area[data-v-f31f94ef]{flex:1;border:2px dashed #00aeec;border-radius:8px;padding:20px;display:flex;align-items:center;justify-content:center;gap:10px;cursor:pointer;transition:all .3s}.upload-area[data-v-f31f94ef][data-v-f31f94ef]:hover{background:#f5fbff;border-color:#09c}.share-link-area[data-v-f31f94ef]{flex:1;display:flex;gap:10px;align-items:center;background:#fff;border:2px solid #00aeec;border-radius:8px;padding:0 15px;transition:all .3s}.share-link-area[data-v-f31f94ef][data-v-f31f94ef]:hover{border-color:#09c;box-shadow:0 2px 8px #00aeec1f}.share-link-area[data-v-f31f94ef] input[data-v-f31f94ef]{flex:1;border:none;outline:none;padding:12px 0;font-size:14px;color:#18191c;background:transparent}.share-link-area[data-v-f31f94ef] input[data-v-f31f94ef][data-v-f31f94ef]::placeholder{color:#9499a0}.share-link-area[data-v-f31f94ef] .download-btn[data-v-f31f94ef]{background:none;border:none;padding:8px;cursor:pointer;border-radius:6px;transition:all .2s;display:flex;align-items:center;justify-content:center}.share-link-area[data-v-f31f94ef] .download-btn[data-v-f31f94ef][data-v-f31f94ef]:hover{background:#00aeec1a;transform:scale(1.05)}.share-link-area[data-v-f31f94ef] .download-btn[data-v-f31f94ef] .iconfont[data-v-f31f94ef]{color:#00aeec;font-size:20px}.search-box[data-v-f31f94ef]{width:320px;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);display:flex;justify-content:center;height:45px}.search-box[data-v-f31f94ef] input[data-v-f31f94ef]{width:100%;padding:14px 48px 14px 24px;border:2px solid #00aeec;border-radius:40px;background:#f5fbffcc;font-size:14px;color:#18191c;transition:all .3s}.search-box[data-v-f31f94ef] input[data-v-f31f94ef][data-v-f31f94ef]::placeholder{color:#9499a0;font-weight:400}.search-box[data-v-f31f94ef] input[data-v-f31f94ef][data-v-f31f94ef]:hover{border-color:#09c;box-shadow:0 2px 8px #00aeec1f}.search-box[data-v-f31f94ef] input[data-v-f31f94ef][data-v-f31f94ef]:focus{outline:none;border-color:#0088b7;box-shadow:0 4px 16px #00aeec29;background:#fff}.search-box[data-v-f31f94ef] .iconfont[data-v-f31f94ef]{position:absolute;right:20px;top:50%;transform:translateY(-50%);color:#00aeec;font-size:20px;transition:all .3s}.search-box[data-v-f31f94ef]:hover .iconfont[data-v-f31f94ef]{color:#09c;transform:translateY(-50%) scale(1.1)}.search-box[data-v-f31f94ef] input:focus~.iconfont[data-v-f31f94ef]{color:#0088b7;animation:searchPulse-f31f94ef 1.5s infinite}@keyframes searchPulse-f31f94ef{0%,to{transform:translateY(-50%) scale(1)}50%{transform:translateY(-50%) scale(1.15)}}.file-list[data-v-f31f94ef]{width:100%;overflow-y:auto;flex:1;position:relative}.file-table[data-v-f31f94ef]{width:100%;border-collapse:collapse;border-spacing:0;table-layout:fixed}.file-table th[data-v-f31f94ef],.file-table td[data-v-f31f94ef]{padding:12px;text-align:center;border-bottom:1px solid #eee}.file-table .col-name[data-v-f31f94ef]{width:45%}.file-table .col-size[data-v-f31f94ef]{width:15%}.file-table .col-date[data-v-f31f94ef],.file-table .col-actions[data-v-f31f94ef]{width:20%}.file-table th[data-v-f31f94ef]{color:#666;font-weight:500;background:#fafafa}.file-row[data-v-f31f94ef]{position:relative;transition:background .2s}.file-row[data-v-f31f94ef]:hover{background:#f9f9f9}.file-name-cell[data-v-f31f94ef]{position:relative;display:flex;align-items:center;gap:10px;cursor:pointer;transition:color .2s;text-align:left;padding-bottom:4px}.file-name-cell[data-v-f31f94ef]:hover{color:#00aeec}.file-name[data-v-f31f94ef]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.action-buttons[data-v-f31f94ef]{display:flex;gap:8px;justify-content:center}.col-actions button[data-v-f31f94ef]{background:#00c1ff;border:none;padding:6px;border-radius:6px;cursor:pointer;transition:.2s;width:70px;display:flex;justify-content:center;align-items:center;gap:4px}.col-actions button[data-v-f31f94ef] .iconfont[data-v-f31f94ef]{color:#fff;font-size:18px}.col-actions button[data-v-f31f94ef] span[data-v-f31f94ef]{color:#fff;font-weight:400;font-size:14px}.col-actions button[data-v-f31f94ef][data-v-f31f94ef]:hover{background:#6cf;transform:translateY(-2px);box-shadow:0 3px 12px #00aeec4d}.col-actions button[data-v-f31f94ef].btn-delete[data-v-f31f94ef]{background:#f54b4cdb}.col-actions button[data-v-f31f94ef].btn-delete[data-v-f31f94ef][data-v-f31f94ef]:hover{background:#ff6668;box-shadow:0 3px 12px #ff4d4f4d}.col-actions button[data-v-f31f94ef].btn-preview[data-v-f31f94ef]{background:#00ff438f}.col-actions button[data-v-f31f94ef].btn-preview[data-v-f31f94ef][data-v-f31f94ef]:hover{background:#00ff43c2;box-shadow:0 3px 12px #00ff434d}.progress-bar[data-v-f31f94ef]{position:absolute;bottom:0;left:0;width:100%;height:2px;background:#00aeec1a;overflow:hidden;border-radius:1px;z-index:1}.progress-inner[data-v-f31f94ef]{height:100%;background:#00aeec;transition:width .3s ease;border-radius:1px}@font-face{font-family:iconfont;src:url(//at.alicdn.com/t/c/font_123456_xxxxxx.css)}.modal-fade-enter-active[data-v-f31f94ef],.modal-fade-leave-active[data-v-f31f94ef]{transition:opacity .25s ease}.modal-fade-enter-from[data-v-f31f94ef],.modal-fade-leave-to[data-v-f31f94ef]{opacity:0}.preview-modal[data-v-f31f94ef]{position:fixed;top:0;right:0;bottom:0;left:0;background:#e5e8e833;z-index:9999;display:flex;justify-content:center;align-items:center;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.modal-container[data-v-f31f94ef]{position:relative;background:#fff;border-radius:12px;box-shadow:0 12px 24px #66ccff59;max-width:90vw;max-height:90vh;overflow:hidden}.close-btn[data-v-f31f94ef]{position:absolute;top:16px;right:16px;background:#ffffff1a;border:none;border-radius:50%;width:40px;height:40px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s;z-index:1}.close-btn[data-v-f31f94ef]:hover{background:#fff3;transform:scale(1.1)}.icon-close[data-v-f31f94ef]{color:#fff;font-size:24px}.image-wrapper[data-v-f31f94ef]{position:relative;width:80vw;max-width:2000px;height:80vh;display:flex;align-items:center;justify-content:center;padding:40px}.image-wrapper img[data-v-f31f94ef]{max-width:100%;max-height:100%;object-fit:contain;border-radius:8px}.loading-indicator[data-v-f31f94ef]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;color:#fffc}.spinner[data-v-f31f94ef]{width:40px;height:40px;border:4px solid rgba(255,255,255,.1);border-top-color:#00aeec;border-radius:50%;animation:spin-f31f94ef 1s linear infinite;margin-bottom:12px}@keyframes spin-f31f94ef{to{transform:rotate(360deg)}}.error-message[data-v-f31f94ef]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:#ff4d4f;font-size:1.2em}.file-info[data-v-f31f94ef]{position:absolute;bottom:0;left:0;right:0;background:linear-gradient(transparent,#66ccffc2);color:#1e1d1d;padding:15px;text-align:center;font-size:1em;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px)}.footer-info[data-v-f31f94ef]{width:90%;text-align:center;color:#777;font-size:1em;border-top:1px solid #eee}.footer-info[data-v-f31f94ef] a[data-v-f31f94ef]{color:#6cf}.copy-toast[data-v-f31f94ef]{position:fixed;background:#00aeecd9;color:#fff;padding:12px 24px;border-radius:8px;box-shadow:0 4px 12px #00aeec4d;z-index:100;font-size:14px;font-weight:500;pointer-events:none;white-space:nowrap;transform:translate(-50%)}.toast-fade-enter-active[data-v-f31f94ef],.toast-fade-leave-active[data-v-f31f94ef]{transition:all .3s ease}.toast-fade-enter-from[data-v-f31f94ef],.toast-fade-leave-to[data-v-f31f94ef]{opacity:0;transform:translate(-50%,10px)}.col-name[data-v-f31f94ef]{position:relative;cursor:pointer;transition:color .2s}.col-name[data-v-f31f94ef]:hover{color:#00aeec}.file-list[data-v-f31f94ef]::-webkit-scrollbar{width:8px}.file-list[data-v-f31f94ef]::-webkit-scrollbar-track{background:#f1f1f1;border-radius:4px}.file-list[data-v-f31f94ef]::-webkit-scrollbar-thumb{background:#6cf;border-radius:4px}.file-list[data-v-f31f94ef]::-webkit-scrollbar-thumb:hover{background:#09c}.file-table thead[data-v-f31f94ef],.file-table th[data-v-f31f94ef]{position:sticky;top:0;background:#fafafa;z-index:2}.main-container{width:100%;height:95%;display:flex;justify-content:center;align-items:center} ");
  15.  
  16. (async function (vue) {
  17. 'use strict';
  18.  
  19. var _a;
  20. const uploadUrl = "https://member.bilibili.com/x/material/up/upload";
  21. const pixelPath = "https://i0.hdslb.com/bfs/material_up/49f20d9277765f51227fecb4db010350c3ed90ad.gif";
  22. const headers = new Headers({
  23. "accept": "*/*",
  24. "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,zh-TW;q=0.5",
  25. "origin": "https://member.bilibili.com",
  26. //"priority": "u=1, i",
  27. "referer": "https://member.bilibili.com/york/image-material-upload",
  28. "sec-ch-ua": '"Chromium";v="136", "Microsoft Edge";v="136", "Not.A/Brand";v="99"',
  29. "sec-ch-ua-mobile": "?0",
  30. "sec-ch-ua-platform": '"Windows"',
  31. "sec-fetch-dest": "empty",
  32. "sec-fetch-mode": "cors",
  33. "sec-fetch-site": "same-origin",
  34. "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Edg/135.0.0.0"
  35. //"Cookie": credentials.cookie
  36. });
  37. const credentials = {};
  38. async function uploadFile(file, onProgress) {
  39. if (!file || !(credentials == null ? void 0 : credentials.bili_jct)) {
  40. throw new Error("缺少必要参数:file/csrf");
  41. }
  42. if (!isImage(file)) {
  43. const pixelBuffer = await (await fetch(pixelPath)).arrayBuffer();
  44. const mergedBlob = new Blob([pixelBuffer, new Blob([file])]);
  45. file = new File([mergedBlob], file.name);
  46. }
  47. const formData = new FormData();
  48. const filename = file.name || `bili_upload_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
  49. formData.append("bucket", "material_up");
  50. formData.append("dir", "");
  51. formData.append("file", file, filename);
  52. formData.append("csrf", credentials.bili_jct);
  53. return new Promise((resolve, reject) => {
  54. const xhr = new XMLHttpRequest();
  55. xhr.upload.addEventListener("progress", (event) => {
  56. if (event.lengthComputable && onProgress) {
  57. const progress = Math.round(event.loaded / event.total * 100);
  58. onProgress(progress);
  59. }
  60. });
  61. xhr.addEventListener("load", () => {
  62. if (xhr.status >= 200 && xhr.status < 300) {
  63. try {
  64. const result = JSON.parse(xhr.responseText);
  65. if (result.code !== 0) {
  66. reject(new Error(`上传失败: ${result.message} (code: ${result.code})`));
  67. } else {
  68. resolve(result);
  69. }
  70. } catch (error) {
  71. reject(new Error("解析响应失败"));
  72. }
  73. } else {
  74. reject(new Error(`HTTP错误: ${xhr.status}`));
  75. }
  76. });
  77. xhr.addEventListener("error", () => {
  78. reject(new Error("网络请求失败"));
  79. });
  80. xhr.open("POST", uploadUrl);
  81. Object.entries(headers).forEach(([key, value]) => {
  82. xhr.setRequestHeader(key, value);
  83. });
  84. xhr.withCredentials = true;
  85. xhr.send(formData);
  86. });
  87. }
  88. function isImage(file) {
  89. var _a2;
  90. const imageExtensions = ["jpg", "jpeg", "png", "gif", "webp", "bmp"];
  91. const extension = ((_a2 = file.name.split(".").pop()) == null ? void 0 : _a2.toLowerCase()) || "";
  92. return imageExtensions.includes(extension);
  93. }
  94. const SAVE_FILES_KEY = "bili_files";
  95. function saveFiles(files) {
  96. try {
  97. localStorage.setItem(SAVE_FILES_KEY, JSON.stringify(files));
  98. } catch (error) {
  99. console.error("[Bilibili-File] 本地存储失败", error);
  100. }
  101. }
  102. function loadFiles() {
  103. try {
  104. const data = localStorage.getItem(SAVE_FILES_KEY);
  105. return data ? JSON.parse(data) : [];
  106. } catch (error) {
  107. console.log("存储读取失败", error);
  108. return [];
  109. }
  110. }
  111. const _export_sfc = (sfc, props) => {
  112. const target = sfc.__vccOpts || sfc;
  113. for (const [key, val] of props) {
  114. target[key] = val;
  115. }
  116. return target;
  117. };
  118. const _withScopeId = (n) => (vue.pushScopeId("data-v-f31f94ef"), n = n(), vue.popScopeId(), n);
  119. const _hoisted_1$1 = { class: "main-menu" };
  120. const _hoisted_2 = { class: "file-manager" };
  121. const _hoisted_3 = { class: "cyber-title" };
  122. const _hoisted_4 = { class: "gradient-text" };
  123. const _hoisted_5 = /* @__PURE__ */ vue.createTextVNode("Bilibili File ( 。・▽・。 )ノ");
  124. const _hoisted_6 = /* @__PURE__ */ vue.createTextVNode("Bilibili File (*ノωノ)");
  125. const _hoisted_7 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", { class: "glow" }, null, -1));
  126. const _hoisted_8 = { class: "action-bar" };
  127. const _hoisted_9 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "iconfont icon-upload" }, null, -1));
  128. const _hoisted_10 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", null, "点击上传文件", -1));
  129. const _hoisted_11 = { class: "share-link-area" };
  130. const _hoisted_12 = ["onKeyup"];
  131. const _hoisted_13 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "iconfont icon-download" }, [
  132. /* @__PURE__ */ vue.createElementVNode("svg", {
  133. xmlns: "http://www.w3.org/2000/svg",
  134. height: "20px",
  135. viewBox: "0 -960 960 960",
  136. width: "20px",
  137. fill: "#5f6368"
  138. }, [
  139. /* @__PURE__ */ vue.createElementVNode("path", { d: "M480-328.46 309.23-499.23l42.16-43.38L450-444v-336h60v336l98.61-98.61 42.16 43.38L480-328.46ZM252.31-180Q222-180 201-201q-21-21-21-51.31v-108.46h60v108.46q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h455.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-108.46h60v108.46Q780-222 759-201q-21 21-51.31 21H252.31Z" })
  140. ])
  141. ], -1));
  142. const _hoisted_14 = [
  143. _hoisted_13
  144. ];
  145. const _hoisted_15 = { class: "search-box" };
  146. const _hoisted_16 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "iconfont icon-search" }, [
  147. /* @__PURE__ */ vue.createElementVNode("svg", {
  148. xmlns: "http://www.w3.org/2000/svg",
  149. height: "24px",
  150. viewBox: "0 -960 960 960",
  151. width: "24px",
  152. fill: "#5f6368"
  153. }, [
  154. /* @__PURE__ */ vue.createElementVNode("path", { d: "M781.69-136.92 530.46-388.16q-30 24.77-69 38.77-39 14-80.69 14-102.55 0-173.58-71.01-71.03-71.01-71.03-173.54 0-102.52 71.01-173.6 71.01-71.07 173.54-71.07 102.52 0 173.6 71.03 71.07 71.03 71.07 173.58 0 42.85-14.38 81.85-14.39 39-38.39 67.84l251.23 251.23-42.15 42.16ZM380.77-395.38q77.31 0 130.96-53.66 53.66-53.65 53.66-130.96t-53.66-130.96q-53.65-53.66-130.96-53.66t-130.96 53.66Q196.15-657.31 196.15-580t53.66 130.96q53.65 53.66 130.96 53.66Z" })
  155. ])
  156. ], -1));
  157. const _hoisted_17 = { class: "file-list" };
  158. const _hoisted_18 = { class: "file-table" };
  159. const _hoisted_19 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("thead", null, [
  160. /* @__PURE__ */ vue.createElementVNode("tr", null, [
  161. /* @__PURE__ */ vue.createElementVNode("th", { class: "col-name" }, "文件名"),
  162. /* @__PURE__ */ vue.createElementVNode("th", { class: "col-size" }, "大小"),
  163. /* @__PURE__ */ vue.createElementVNode("th", { class: "col-date" }, "上传日期"),
  164. /* @__PURE__ */ vue.createElementVNode("th", { class: "col-actions" }, "操作")
  165. ])
  166. ], -1));
  167. const _hoisted_20 = ["onClick"];
  168. const _hoisted_21 = { class: "file-name-cell" };
  169. const _hoisted_22 = {
  170. key: 0,
  171. class: "iconfont icon-file"
  172. };
  173. const _hoisted_23 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("svg", {
  174. xmlns: "http://www.w3.org/2000/svg",
  175. height: "24px",
  176. viewBox: "0 -960 960 960",
  177. width: "24px",
  178. fill: "#5f6368"
  179. }, [
  180. /* @__PURE__ */ vue.createElementVNode("path", { d: "M212.31-140Q182-140 161-161q-21-21-21-51.31v-535.38Q140-778 161-799q21-21 51.31-21h535.38Q778-820 799-799q21 21 21 51.31v535.38Q820-182 799-161q-21 21-51.31 21H212.31Zm0-60h535.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-535.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H212.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v535.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85ZM270-290h423.07L561.54-465.38 449.23-319.23l-80-102.31L270-290Zm-70 90v-560 560Z" })
  181. ], -1));
  182. const _hoisted_24 = [
  183. _hoisted_23
  184. ];
  185. const _hoisted_25 = {
  186. key: 1,
  187. class: "iconfont icon-file"
  188. };
  189. const _hoisted_26 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("svg", {
  190. xmlns: "http://www.w3.org/2000/svg",
  191. height: "24px",
  192. viewBox: "0 -960 960 960",
  193. width: "24px",
  194. fill: "#5f6368"
  195. }, [
  196. /* @__PURE__ */ vue.createElementVNode("path", { d: "M640-480v-80h80v80h-80Zm0 80h-80v-80h80v80Zm0 80v-80h80v80h-80ZM447.38-640l-80-80H172.31q-5.39 0-8.85 3.46t-3.46 8.85v455.38q0 5.39 3.46 8.85t8.85 3.46H560v-80h80v80h147.69q5.39 0 8.85-3.46t3.46-8.85v-375.38q0-5.39-3.46-8.85t-8.85-3.46H640v80h-80v-80H447.38ZM172.31-180Q142-180 121-201q-21-21-21-51.31v-455.38Q100-738 121-759q21-21 51.31-21h219.61l80 80h315.77Q818-700 839-679q21 21 21 51.31v375.38Q860-222 839-201q-21 21-51.31 21H172.31ZM160-240v-480 480Z" })
  197. ], -1));
  198. const _hoisted_27 = [
  199. _hoisted_26
  200. ];
  201. const _hoisted_28 = {
  202. key: 2,
  203. class: "iconfont icon-file"
  204. };
  205. const _hoisted_29 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("svg", {
  206. xmlns: "http://www.w3.org/2000/svg",
  207. height: "24px",
  208. viewBox: "0 -960 960 960",
  209. width: "24px",
  210. fill: "#5f6368"
  211. }, [
  212. /* @__PURE__ */ vue.createElementVNode("path", { d: "M330-250h300v-60H330v60Zm0-160h300v-60H330v60Zm-77.69 310Q222-100 201-121q-21-21-21-51.31v-615.38Q180-818 201-839q21-21 51.31-21H570l210 210v477.69Q780-142 759-121q-21 21-51.31 21H252.31ZM540-620v-180H252.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v615.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h455.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46V-620H540ZM240-800v180-180V-160v-640Z" })
  213. ], -1));
  214. const _hoisted_30 = [
  215. _hoisted_29
  216. ];
  217. const _hoisted_31 = { class: "file-name" };
  218. const _hoisted_32 = { class: "col-size" };
  219. const _hoisted_33 = { class: "col-date" };
  220. const _hoisted_34 = { class: "col-actions" };
  221. const _hoisted_35 = { class: "action-buttons" };
  222. const _hoisted_36 = ["onClick"];
  223. const _hoisted_37 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "iconfont icon-preview" }, [
  224. /* @__PURE__ */ vue.createElementVNode("svg", {
  225. xmlns: "http://www.w3.org/2000/svg",
  226. height: "20px",
  227. viewBox: "0 -960 960 960",
  228. width: "20px",
  229. fill: "#5f6368"
  230. }, [
  231. /* @__PURE__ */ vue.createElementVNode("path", { d: "M480.09-336.92q67.99 0 115.49-47.59t47.5-115.58q0-67.99-47.59-115.49t-115.58-47.5q-67.99 0-115.49 47.59t-47.5 115.58q0 67.99 47.59 115.49t115.58 47.5ZM480-392q-45 0-76.5-31.5T372-500q0-45 31.5-76.5T480-608q45 0 76.5 31.5T588-500q0 45-31.5 76.5T480-392Zm.05 172q-137.97 0-251.43-76.12Q115.16-372.23 61.54-500q53.62-127.77 167.02-203.88Q341.97-780 479.95-780q137.97 0 251.43 76.12Q844.84-627.77 898.46-500q-53.62 127.77-167.02 203.88Q618.03-220 480.05-220ZM480-500Zm0 220q113 0 207.5-59.5T832-500q-50-101-144.5-160.5T480-720q-113 0-207.5 59.5T128-500q50 101 144.5 160.5T480-280Z" })
  232. ])
  233. ], -1));
  234. const _hoisted_38 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", null, "预览", -1));
  235. const _hoisted_39 = [
  236. _hoisted_37,
  237. _hoisted_38
  238. ];
  239. const _hoisted_40 = ["onClick"];
  240. const _hoisted_41 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "iconfont icon-download" }, [
  241. /* @__PURE__ */ vue.createElementVNode("svg", {
  242. xmlns: "http://www.w3.org/2000/svg",
  243. height: "20px",
  244. viewBox: "0 -960 960 960",
  245. width: "20px",
  246. fill: "#5f6368"
  247. }, [
  248. /* @__PURE__ */ vue.createElementVNode("path", { d: "M480-328.46 309.23-499.23l42.16-43.38L450-444v-336h60v336l98.61-98.61 42.16 43.38L480-328.46ZM252.31-180Q222-180 201-201q-21-21-21-51.31v-108.46h60v108.46q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h455.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-108.46h60v108.46Q780-222 759-201q-21 21-51.31 21H252.31Z" })
  249. ])
  250. ], -1));
  251. const _hoisted_42 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", null, "下载", -1));
  252. const _hoisted_43 = [
  253. _hoisted_41,
  254. _hoisted_42
  255. ];
  256. const _hoisted_44 = ["onClick"];
  257. const _hoisted_45 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "iconfont icon-delete" }, [
  258. /* @__PURE__ */ vue.createElementVNode("svg", {
  259. xmlns: "http://www.w3.org/2000/svg",
  260. height: "20px",
  261. viewBox: "0 -960 960 960",
  262. width: "20px",
  263. fill: "#5f6368"
  264. }, [
  265. /* @__PURE__ */ vue.createElementVNode("path", { d: "M292.31-140q-29.92 0-51.12-21.19Q220-182.39 220-212.31V-720h-40v-60h180v-35.38h240V-780h180v60h-40v507.69Q740-182 719-161q-21 21-51.31 21H292.31ZM680-720H280v507.69q0 5.39 3.46 8.85t8.85 3.46h375.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46V-720ZM376.16-280h59.99v-360h-59.99v360Zm147.69 0h59.99v-360h-59.99v360ZM280-720v520-520Z" })
  266. ])
  267. ], -1));
  268. const _hoisted_46 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", null, "删除", -1));
  269. const _hoisted_47 = [
  270. _hoisted_45,
  271. _hoisted_46
  272. ];
  273. const _hoisted_48 = {
  274. key: 0,
  275. class: "progress-bar"
  276. };
  277. const _hoisted_49 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "footer-info" }, [
  278. /* @__PURE__ */ vue.createTextVNode(" © 2025 "),
  279. /* @__PURE__ */ vue.createElementVNode("a", {
  280. href: "https://github.com/WJZ-P/Bilibili-File",
  281. target: "_blank",
  282. title: "GitHub地址"
  283. }, "Bilibili File"),
  284. /* @__PURE__ */ vue.createTextVNode(". Made by WJZ_P with love. ( ̄▽ ̄) ")
  285. ], -1));
  286. const _hoisted_50 = ["onClick"];
  287. const _hoisted_51 = { class: "modal-container" };
  288. const _hoisted_52 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "iconfont icon-close" }, [
  289. /* @__PURE__ */ vue.createElementVNode("svg", {
  290. xmlns: "http://www.w3.org/2000/svg",
  291. height: "24px",
  292. viewBox: "0 -960 960 960",
  293. width: "24px",
  294. fill: "#5f6368"
  295. }, [
  296. /* @__PURE__ */ vue.createElementVNode("path", { d: "M256-213.85 213.85-256l224-224-224-224L256-746.15l224 224 224-224L746.15-704l-224 224 224 224L704-213.85l-224-224-224 224Z" })
  297. ])
  298. ], -1));
  299. const _hoisted_53 = [
  300. _hoisted_52
  301. ];
  302. const _hoisted_54 = { class: "image-wrapper" };
  303. const _hoisted_55 = ["src", "alt"];
  304. const _hoisted_56 = {
  305. key: 0,
  306. class: "loading-indicator"
  307. };
  308. const _hoisted_57 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "spinner" }, null, -1));
  309. const _hoisted_58 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", null, "加载中...", -1));
  310. const _hoisted_59 = [
  311. _hoisted_57,
  312. _hoisted_58
  313. ];
  314. const _hoisted_60 = { class: "file-info" };
  315. const _sfc_main$1 = {
  316. setup(__props) {
  317. const fileInputEl = vue.ref(null);
  318. const isHovered = vue.ref(false);
  319. const files = vue.ref([]);
  320. const previewImg = vue.ref(null);
  321. const loading = vue.ref(false);
  322. const loadError = vue.ref(false);
  323. const showViewModel = vue.ref(false);
  324. const searchQuery = vue.ref("");
  325. const sliceIndex = 35;
  326. vue.onMounted(() => {
  327. files.value = loadFiles();
  328. });
  329. const filteredFiles = vue.computed(() => {
  330. if (!searchQuery.value.trim()) return files.value;
  331. const query = searchQuery.value.trim().toLowerCase();
  332. return files.value.filter((file) => {
  333. return file.name.toLowerCase().includes(query);
  334. });
  335. });
  336. const handleUpload = () => fileInputEl.value.click();
  337. const fileProgress = vue.ref({});
  338. const shareLink = vue.ref("");
  339. const handleFileSelect = async (event) => {
  340. console.log("下面打印出传入的文件参数");
  341. console.log(event.target.files);
  342. const filePromises = Array.from(event.target.files).map((file) => {
  343. const resultFile = {
  344. name: file.name,
  345. size: file.size,
  346. url: "",
  347. lastModified: Date.now(),
  348. status: "uploading"
  349. };
  350. files.value.push(resultFile);
  351. fileProgress.value[file.name] = 0;
  352. return { file, resultFile };
  353. });
  354. try {
  355. const uploadPromises = filePromises.map(
  356. ({ file, resultFile }) => uploadFile(file, (progress) => {
  357. fileProgress.value[file.name] = progress;
  358. }).then((result) => {
  359. resultFile.url = result.data.location.replace(/^http:\/\//i, "https://");
  360. resultFile.status = "success";
  361. delete fileProgress.value[file.name];
  362. }).catch((error) => {
  363. console.error(`文件 ${file.name} 上传失败:`, error);
  364. resultFile.status = "error";
  365. delete fileProgress.value[file.name];
  366. showToastMessage(`文件 ${file.name} 上传失败,请重试`, {
  367. clientX: window.innerWidth / 2,
  368. clientY: 100
  369. });
  370. })
  371. );
  372. await Promise.all(uploadPromises);
  373. saveFiles(files.value);
  374. } catch (error) {
  375. console.error("批量上传过程中发生错误:", error);
  376. showToastMessage("上传过程中发生错误,请重试", {
  377. clientX: window.innerWidth / 2,
  378. clientY: 100
  379. });
  380. }
  381. };
  382. const formatDate = (timestamp) => {
  383. const date = new Date(timestamp);
  384. return date.toISOString().split("T")[0];
  385. };
  386. const formatSize = (bytes) => {
  387. if (bytes === 0) return "0 B";
  388. const units = ["B", "KB", "MB", "GB"];
  389. const i = Math.floor(Math.log(bytes) / Math.log(1024));
  390. return `${(bytes / Math.pow(1024, i)).toFixed(2)} ${units[i]}`;
  391. };
  392. const handleDownload = async (file) => {
  393. try {
  394. fileProgress.value[file.name] = 0;
  395. const response = await fetch(file.url);
  396. const reader = response.body.getReader();
  397. const contentLength = +response.headers.get("Content-Length");
  398. let receivedLength = 0;
  399. let chunks = [];
  400. while (true) {
  401. const { done, value } = await reader.read();
  402. if (done) {
  403. break;
  404. }
  405. chunks.push(value);
  406. receivedLength += value.length;
  407. fileProgress.value[file.name] = Math.round(receivedLength / contentLength * 100);
  408. }
  409. let blob = new Blob(chunks);
  410. if (!isImage2(file)) blob = blob.slice(sliceIndex);
  411. const url2 = URL.createObjectURL(blob);
  412. const a = document.createElement("a");
  413. a.href = url2;
  414. a.download = file.name;
  415. document.body.appendChild(a);
  416. a.click();
  417. document.body.removeChild(a);
  418. URL.revokeObjectURL(url2);
  419. setTimeout(() => {
  420. delete fileProgress.value[file.name];
  421. }, 1e3);
  422. } catch (error) {
  423. console.error("下载失败:", error);
  424. showToastMessage("下载失败,请重试", { clientX: window.innerWidth / 2, clientY: 100 });
  425. delete fileProgress.value[file.name];
  426. }
  427. };
  428. const handleDelete = (file) => {
  429. files.value = files.value.filter(
  430. (f) => !(f.name === file.name && f.size === file.size)
  431. );
  432. console.log("删除后的总文件列表");
  433. console.log(files.value);
  434. saveFiles(files.value);
  435. };
  436. const handlePreview = (file) => {
  437. showViewModel.value = true;
  438. previewImg.value = file;
  439. };
  440. const closePreview = () => {
  441. showViewModel.value = false;
  442. previewImg.value = null;
  443. };
  444. const handleImageLoad = () => {
  445. loading.value = false;
  446. };
  447. const handleImageError = () => {
  448. loading.value = false;
  449. loadError.value = true;
  450. };
  451. function isImage2(file) {
  452. var _a2;
  453. const imageExtensions = ["jpg", "jpeg", "png", "gif", "webp", "bmp"];
  454. const extension = ((_a2 = file.name.split(".").pop()) == null ? void 0 : _a2.toLowerCase()) || "";
  455. return imageExtensions.includes(extension);
  456. }
  457. function isCompressed(file) {
  458. var _a2;
  459. const compressedExtensions = [
  460. "zip",
  461. "rar",
  462. "7z",
  463. "tar",
  464. "gz",
  465. "bz2",
  466. "xz",
  467. "dmg",
  468. "iso",
  469. "cab",
  470. "arj",
  471. "z",
  472. "lz",
  473. "lzma",
  474. "tgz"
  475. ];
  476. const extension = ((_a2 = file.name.split(".").pop()) == null ? void 0 : _a2.toLowerCase()) || "";
  477. return compressedExtensions.includes(extension);
  478. }
  479. const handleMouseEnter = () => isHovered.value = true;
  480. const handleMouseLeave = () => isHovered.value = false;
  481. const showToast = vue.ref(false);
  482. const toastMessage = vue.ref("");
  483. const toastPosition = vue.ref({ x: 0, y: 0 });
  484. const toastStyle = vue.computed(() => ({
  485. left: `${toastPosition.value.x}px`,
  486. top: `${toastPosition.value.y}px`
  487. }));
  488. const showToastMessage = (message, event) => {
  489. toastMessage.value = message;
  490. const x = event.clientX;
  491. const y = event.clientY - 40;
  492. const maxX = window.innerWidth - 200;
  493. const maxY = window.innerHeight - 50;
  494. toastPosition.value = {
  495. x: Math.min(Math.max(x + 100, 0), maxX),
  496. // 水平居中
  497. y: Math.min(Math.max(y, 0), maxY)
  498. };
  499. showToast.value = true;
  500. setTimeout(() => {
  501. showToast.value = false;
  502. }, 1e3);
  503. };
  504. const copyFileLink = async (file, event) => {
  505. try {
  506. await navigator.clipboard.writeText(file.url);
  507. showToastMessage("链接已复制到剪贴板", event);
  508. } catch (err) {
  509. console.error("复制失败:", err);
  510. showToastMessage("复制失败,请重试", event);
  511. }
  512. };
  513. const handleShareLinkDownload = async () => {
  514. if (!shareLink.value.trim()) {
  515. showToastMessage("请输入分享链接", { clientX: window.innerWidth / 2, clientY: 100 });
  516. return;
  517. }
  518. try {
  519. if (!shareLink.value.startsWith("https://")) {
  520. showToastMessage("请输入有效的链接", { clientX: window.innerWidth / 2, clientY: 100 });
  521. return;
  522. }
  523. const fileName2 = shareLink.value.split("/").pop() || "downloaded_file";
  524. fileProgress.value[fileName2] = 0;
  525. const response = await fetch(shareLink.value);
  526. const reader = response.body.getReader();
  527. const contentLength = +response.headers.get("Content-Length");
  528. let receivedLength = 0;
  529. let chunks = [];
  530. while (true) {
  531. const { done, value } = await reader.read();
  532. if (done) break;
  533. chunks.push(value);
  534. receivedLength += value.length;
  535. fileProgress.value[fileName2] = Math.round(receivedLength / contentLength * 100);
  536. }
  537. const blob = new Blob(chunks);
  538. const url2 = URL.createObjectURL(blob);
  539. const a = document.createElement("a");
  540. a.href = url2;
  541. a.download = fileName2;
  542. document.body.appendChild(a);
  543. a.click();
  544. document.body.removeChild(a);
  545. URL.revokeObjectURL(url2);
  546. shareLink.value = "";
  547. setTimeout(() => {
  548. delete fileProgress.value[fileName2];
  549. }, 1e3);
  550. showToastMessage("文件下载成功", { clientX: window.innerWidth / 2, clientY: 100 });
  551. } catch (error) {
  552. console.error("下载失败:", error);
  553. showToastMessage("下载失败,请检查链接是否正确", { clientX: window.innerWidth / 2, clientY: 100 });
  554. delete fileProgress.value[fileName];
  555. }
  556. };
  557. return (_ctx, _cache) => {
  558. return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
  559. vue.createElementVNode("div", _hoisted_1$1, [
  560. vue.createElementVNode("div", _hoisted_2, [
  561. vue.createElementVNode("h1", _hoisted_3, [
  562. vue.createElementVNode("a", {
  563. href: "https://github.com/WJZ-P/Bilibili-File",
  564. target: "_blank",
  565. rel: "noopener noreferrer",
  566. class: "title-link",
  567. onMouseenter: handleMouseEnter,
  568. onMouseleave: handleMouseLeave
  569. }, [
  570. vue.createElementVNode("span", _hoisted_4, [
  571. !isHovered.value ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
  572. _hoisted_5
  573. ], 64)) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
  574. _hoisted_6
  575. ], 64))
  576. ]),
  577. _hoisted_7
  578. ], 32)
  579. ]),
  580. vue.createElementVNode("div", _hoisted_8, [
  581. vue.createElementVNode("div", {
  582. class: "upload-area",
  583. onClick: handleUpload
  584. }, [
  585. _hoisted_9,
  586. _hoisted_10,
  587. vue.createElementVNode("input", {
  588. type: "file",
  589. ref_key: "fileInputEl",
  590. ref: fileInputEl,
  591. multiple: "",
  592. style: { "display": "none" },
  593. onChange: handleFileSelect
  594. }, null, 544)
  595. ]),
  596. vue.createElementVNode("div", _hoisted_11, [
  597. vue.withDirectives(vue.createElementVNode("input", {
  598. type: "text",
  599. "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => shareLink.value = $event),
  600. placeholder: "粘贴分享链接...",
  601. onKeyup: vue.withKeys(handleShareLinkDownload, ["enter"])
  602. }, null, 40, _hoisted_12), [
  603. [vue.vModelText, shareLink.value]
  604. ]),
  605. vue.createElementVNode("button", {
  606. class: "download-btn",
  607. onClick: handleShareLinkDownload
  608. }, _hoisted_14)
  609. ]),
  610. vue.createElementVNode("div", _hoisted_15, [
  611. vue.withDirectives(vue.createElementVNode("input", {
  612. type: "text",
  613. "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => searchQuery.value = $event),
  614. placeholder: "搜索文件...",
  615. onInput: _cache[2] || (_cache[2] = (...args) => _ctx.handleSearch && _ctx.handleSearch(...args))
  616. }, null, 544), [
  617. [vue.vModelText, searchQuery.value]
  618. ]),
  619. _hoisted_16
  620. ])
  621. ]),
  622. vue.createElementVNode("div", _hoisted_17, [
  623. vue.createElementVNode("table", _hoisted_18, [
  624. _hoisted_19,
  625. vue.createElementVNode("tbody", null, [
  626. (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(filteredFiles), (file) => {
  627. return vue.openBlock(), vue.createElementBlock("tr", {
  628. key: file.name + file.size,
  629. class: "file-row"
  630. }, [
  631. vue.createElementVNode("td", {
  632. class: "col-name",
  633. onClick: ($event) => copyFileLink(file, $event),
  634. title: "点击复制下载链接"
  635. }, [
  636. vue.createElementVNode("div", _hoisted_21, [
  637. isImage2(file) ? (vue.openBlock(), vue.createElementBlock("i", _hoisted_22, _hoisted_24)) : isCompressed(file) ? (vue.openBlock(), vue.createElementBlock("i", _hoisted_25, _hoisted_27)) : (vue.openBlock(), vue.createElementBlock("i", _hoisted_28, _hoisted_30)),
  638. vue.createElementVNode("span", _hoisted_31, vue.toDisplayString(file.name), 1)
  639. ])
  640. ], 8, _hoisted_20),
  641. vue.createElementVNode("td", _hoisted_32, vue.toDisplayString(formatSize(file.size)), 1),
  642. vue.createElementVNode("td", _hoisted_33, vue.toDisplayString(formatDate(file.lastModified)), 1),
  643. vue.createElementVNode("td", _hoisted_34, [
  644. vue.createElementVNode("div", _hoisted_35, [
  645. isImage2(file) ? (vue.openBlock(), vue.createElementBlock("button", {
  646. key: 0,
  647. class: "btn-preview",
  648. onClick: vue.withModifiers(($event) => handlePreview(file), ["stop"])
  649. }, _hoisted_39, 8, _hoisted_36)) : vue.createCommentVNode("", true),
  650. file.status === "success" ? (vue.openBlock(), vue.createElementBlock("button", {
  651. key: 1,
  652. class: "btn-download",
  653. onClick: vue.withModifiers(($event) => handleDownload(file), ["stop"])
  654. }, _hoisted_43, 8, _hoisted_40)) : vue.createCommentVNode("", true),
  655. vue.createElementVNode("button", {
  656. class: "btn-delete",
  657. onClick: vue.withModifiers(($event) => handleDelete(file), ["stop"])
  658. }, _hoisted_47, 8, _hoisted_44)
  659. ])
  660. ]),
  661. file.status === "uploading" ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_48, [
  662. vue.createElementVNode("div", {
  663. class: "progress-inner",
  664. style: vue.normalizeStyle({ width: `${fileProgress.value[file.name] || 0}%` })
  665. }, null, 4)
  666. ])) : vue.createCommentVNode("", true)
  667. ]);
  668. }), 128))
  669. ])
  670. ])
  671. ])
  672. ]),
  673. _hoisted_49
  674. ]),
  675. (vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
  676. vue.createVNode(vue.Transition, { name: "modal-fade" }, {
  677. default: vue.withCtx(() => [
  678. showViewModel.value ? (vue.openBlock(), vue.createElementBlock("div", {
  679. key: 0,
  680. class: "preview-modal",
  681. onClick: vue.withModifiers(closePreview, ["self"])
  682. }, [
  683. vue.createElementVNode("div", _hoisted_51, [
  684. vue.createElementVNode("button", {
  685. class: "close-btn",
  686. onClick: closePreview
  687. }, _hoisted_53),
  688. vue.createElementVNode("div", _hoisted_54, [
  689. vue.createElementVNode("img", {
  690. src: previewImg.value.url,
  691. alt: previewImg.value.name,
  692. onLoad: handleImageLoad,
  693. onError: handleImageError
  694. }, null, 40, _hoisted_55),
  695. loading.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_56, _hoisted_59)) : vue.createCommentVNode("", true)
  696. ]),
  697. vue.createElementVNode("div", _hoisted_60, vue.toDisplayString(previewImg.value.name), 1)
  698. ])
  699. ], 8, _hoisted_50)) : vue.createCommentVNode("", true)
  700. ]),
  701. _: 1
  702. })
  703. ])),
  704. (vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
  705. vue.createVNode(vue.Transition, { name: "toast-fade" }, {
  706. default: vue.withCtx(() => [
  707. showToast.value ? (vue.openBlock(), vue.createElementBlock("div", {
  708. key: 0,
  709. class: "copy-toast",
  710. style: vue.normalizeStyle(vue.unref(toastStyle))
  711. }, vue.toDisplayString(toastMessage.value), 5)) : vue.createCommentVNode("", true)
  712. ]),
  713. _: 1
  714. })
  715. ]))
  716. ], 64);
  717. };
  718. }
  719. };
  720. const MainMenu = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-f31f94ef"]]);
  721. const _hoisted_1 = { class: "main-container" };
  722. const _sfc_main = {
  723. setup(__props) {
  724. return (_ctx, _cache) => {
  725. return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
  726. vue.createVNode(MainMenu)
  727. ]);
  728. };
  729. }
  730. };
  731. vue.createApp(_sfc_main).mount(
  732. (() => {
  733. if (document.contentType !== "text/html" || window.location.href !== "https://www.bilibili.com/bilibili-file") return;
  734. const app = document.createElement("div");
  735. document.querySelector(".error-container").remove();
  736. document.body.append(app);
  737. return app;
  738. })()
  739. );
  740. console.log("[Bilibili-File] 启动");
  741. console.log("为了防止未加载完成,先等待一秒");
  742. await( sleep(1e3));
  743. credentials["bili_jct"] = (_a = document.cookie.split("; ").find((row) => row.startsWith("bili_jct="))) == null ? void 0 : _a.split("=")[1];
  744. credentials["cookie"] = document.cookie;
  745. const url = new URL(window.location.href);
  746. if (url.hostname.includes("www.bilibili.com")) addMyBtn();
  747. else console.log("[Bilibili-File] 不在B站首页,不添加上传按钮");
  748. if (url.pathname.includes("bilibili-file")) {
  749. document.title = "文件上传 - Bilibili-File";
  750. }
  751. function addMyBtn() {
  752. const list = document.querySelector(".right-entry");
  753. const button = document.querySelector(".right-entry-item--upload");
  754. let cloneBtn;
  755. if (list && button) {
  756. cloneBtn = button.cloneNode(true);
  757. cloneBtn.id = "bilibili-file-uploadFile";
  758. list.appendChild(cloneBtn);
  759. } else {
  760. console.log("[Bilibili-File] 元素未找到,添加上传按钮失败");
  761. }
  762. cloneBtn.querySelector(".header-upload-entry__text").textContent = "传输";
  763. cloneBtn.querySelector(".header-upload-entry__icon").innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -960 960 960" width="20px" fill="#ffffff"><path d="M450-224.62h60V-402l74 74 42.15-42.77L480-516.92 333.85-370.77l42.77 42.15L450-402v177.38ZM252.31-100Q222-100 201-121q-21-21-21-51.31v-615.38Q180-818 201-839q21-21 51.31-21H570l210 210v477.69Q780-142 759-121q-21 21-51.31 21H252.31ZM540-620v-180H252.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v615.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h455.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46V-620H540ZM240-800v180-180V-160v-640Z"/></svg>`;
  764. cloneBtn.onclick = null;
  765. cloneBtn.removeAttribute("onclick");
  766. cloneBtn.addEventListener("click", (event) => {
  767. window.location.href = "https://www.bilibili.com/bilibili-file";
  768. });
  769. }
  770. async function sleep(ms) {
  771. return new Promise((resolve) => setTimeout(resolve, ms));
  772. }
  773.  
  774. })(Vue);

QingJ © 2025

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