// ==UserScript== // @name 夸克网盘树状目录 // @version 1.0 // @description 夸克网盘分享页显示树状列表,点击顶部右边笑脸即可 // @author sunzehui // @license MIT // @match https://pan.quark.cn/s/* // @grant GM_xmlhttpRequest // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/jquery.fancytree/2.38.3/jquery.fancytree-all-deps.min.js // @namespace https://greasyfork.org/users/454712 // @downloadURL https://update.greasyfork.icu/scripts/499326/%E5%A4%B8%E5%85%8B%E7%BD%91%E7%9B%98%E6%A0%91%E7%8A%B6%E7%9B%AE%E5%BD%95.user.js // @updateURL https://update.greasyfork.icu/scripts/499326/%E5%A4%B8%E5%85%8B%E7%BD%91%E7%9B%98%E6%A0%91%E7%8A%B6%E7%9B%AE%E5%BD%95.meta.js // ==/UserScript== (function () { var listeners = []; var doc = window.document; varMutationObserver = window.MutationObserver || window.WebKitMutationObserver; var observer; function domReady(selector, fn) { // 储存选择器和回调函数 listeners.push({ selector: selector, fn: fn, }); if (!observer) { // 监听document变化 observer = new MutationObserver(check); observer.observe(doc.documentElement, { childList: true, subtree: true, }); } // 检查该节点是否已经在DOM中 check(); } function check() { // 检查是否匹配已储存的节点 for (var i = 0; i < listeners.length; i++) { var listener = listeners[i]; // 检查指定节点是否有匹配 var elements = doc.querySelectorAll(listener.selector); for (var j = 0; j < elements.length; j++) { var element = elements[j]; // 确保回调函数只会对该元素调用一次 if (!element.ready) { element.ready = true; // 对该节点调用回调函数 listener.fn.call(element, element); } } } } // 对外暴露ready window.domReady = domReady; })(); const api = { 'fileList': "https://drive-pc.quark.cn/1/clouddrive/share/sharepage/detail" } class QuarkScript { constructor() { this.config = { insertContainer: "div.CommonHeader--container--LPZpeBK", tagClassname : 'script-tag', insertTreeViewContainer: ".DetailLayout--container--264z8Xd", lazyLoad: true, fancytreeCSS_CDN: "https://cdnjs.cloudflare.com/ajax/libs/jquery.fancytree/2.27.0/skin-win8/ui.fancytree.css" } this.api = api this.headers = { accept: "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/json;charset=UTF-8", "sec-fetch-mode": "cors", "sec-fetch-site": "same-site", "x-canary": "client=web,app=adrive,version=v2.3.1", }; this.params = { pwd_id: this.getPwdId() } this.nowSelectNode = null; this.isLoading = false; } // ... existing code ... parseCookie(str) { // ... existing code ... } getPwdId() { const url = location.pathname; return url.match(/(?<=\/s\/)(\w+)(?=#)?/g)[0]; } getStoken(){ const tokenStorage = JSON.parse(sessionStorage.getItem("_share_args")); return tokenStorage.value.stoken ? tokenStorage.value.stoken : ""; } loading(type = 'start') { const tag = $( '.' + this.config.tagClassname) if(this.isLoading==false && type == 'start'){ this.isLoading = true; setTimeout(() => { if(!this.isLoading)return; if (tag.html() == 'o') { tag.html( "0"); } else { tag.html( "o"); } this.loading("start"); }, 500); } if(this.isLoading==true && type == 'stop'){ this.isLoading = false tag.html("😃"); } } async handleTagClick(){ console.log('clicked') // const tokenStorage = JSON.parse(localStorage.getItem("shareToken")); // const token = tokenStorage.share_token ? tokenStorage.share_token : ""; // headers["x-share-token"] = token; const $existsView = $('.tree-container') if($existsView.length > 0){ return $existsView.show(); } this.loading(); await this.renderView(); this.loading('stop'); } renderTag() { const tag = document.createElement("div"); tag.classList.add(this.config.tagClassname); tag.innerHTML = "😃"; let that = this; $(document).on('click','.'+this.config.tagClassname, function() { that.handleTagClick() }) const insertContainer = this.config.insertContainer domReady(insertContainer,function(){ document .querySelector( insertContainer ) .appendChild(tag); }) } listAdapter(list, isFirst = true) { return list.map((item) => { const hasFolder = !!item.children; const obj = { title: item.name, folder: hasFolder, expanded: isFirst, }; if (hasFolder) { obj.children = this.listAdapter(item.children, false); } return obj; }); } async buildFancytreeCfg() { const that = this const cfg = { selectMode: 1, autoScroll: true, activate: function (event, data) { console.log('active',data) that.nowSelectNode = data.node; }, }; const loadRootNode = async (event, data) => { const list = await this.getList({ parent_file_id: 0 }); const children = await Promise.all( list.map(async (pItem) => { const cList = await this.getList({ parent_file_id: pItem.fid }); return cList.map((cItem) => { return { title: cItem.file_name, folder: cItem.dir, key: cItem.fid, lazy: true, }; }); }) ); return list.map((item) => ({ title: item.file_name, folder: item.dir, key: item.fid, expanded: true, lazy: true, children: children.flat(1), })); }; const loadNode = function (event, data) { data.result = that.getList({ parent_file_id: data.node.key }).then((list) => { return list.map((item) => ({ title: item.file_name, folder: item.dir, key: item.fid, lazy: item.dir, })); }); }; if (this.config.lazyLoad) { cfg["source"] = loadRootNode(); cfg["lazyLoad"] = loadNode; } else { const tree = await this.buildTree(); cfg["source"] = await this.listAdapter(tree.children); } return cfg; } async renderView() { const cfg = await this.buildFancytreeCfg(); const $treeContainer = $(`