Greasy Fork

Greasy Fork is available in English.

百度网盘 - 更高级的重命名

你不知道的百度网盘重命名姿势~支持批量替换重命名、手动批量修改后一次提交、智能重命名,拒绝转圈圈!

当前为 2023-07-24 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name            百度网盘 - 更高级的重命名
// @version         1.0.3
// @description     你不知道的百度网盘重命名姿势~支持批量替换重命名、手动批量修改后一次提交、智能重命名,拒绝转圈圈!
// @author          Priate
// @match           https://pan.baidu.com/*
// @grant           GM_setValue
// @grant           GM_getValue
// @grant           GM_addStyle
// @icon            https://nd-static.bdstatic.com/m-static/v20-main/favicon-main.ico
// @require         https://unpkg.com/vue@2
// @require         https://unpkg.com/[email protected]/dist/sweetalert.min.js
// @require         https://unpkg.com/[email protected]/dist/jquery.min.js
// @require         http://greasyfork.icu/scripts/435476-priatelib/code/PriateLib.js?version=1202493
// @supportURL      http://greasyfork.icu/zh-CN/scripts/435495/feedback
// @homepageURL     http://greasyfork.icu/zh-CN/scripts/435495
// @contributionURL https://afdian.net/@cyberubbish
// @license         MIT
// @namespace       http://greasyfork.icu/users/219866
// ==/UserScript==

(function() {
    'use strict';

    function initSetting() {
        var setting;
        if (!GM_getValue('priate_script_bdwp_data')) {
            GM_setValue('priate_script_bdwp_data', {
                left: 20,
                top: 100,
            })
        }
        setting = GM_getValue('priate_script_bdwp_data')
        GM_setValue('priate_script_bdwp_data', setting)
    }

    function injectDiv() {
        var priate_script_div = document.createElement("div")
        priate_script_div.innerHTML = `
<div id="priate_script_div">
<b style='font-size:30px; font-weight:300; margin: 10px 20px'>更高级的重命名</b>
<p id='priate_script_setting' style='margin: 0 0'>
❤️ by <a @click='openDonate' style='color:#337ab7'>Priate</a> |
v <a href="//greasyfork.org/scripts/443771" target="_blank" style='color:#ff6666'>{{version}}</a> |
<a @click="switchDrag">📌</a> | <a @click="recoverText">♻️</a> | <a v-show="data.length > 0" @click="smartRename">🤖️ |</a> <a @click="clearData">❌</a>
<br>
文件夹重命名 : <a @click='todo' :style='"color:" + (false ? "#00947e" : "#CC0F35")'> 关闭 </a> |
正则 : <a @click='todo' :style='"color:" + (false ? "#00947e" : "#CC0F35")'> 关闭 </a>
<div v-show="data.length">
<a style='color:#946C00;' @click="changeOriginText" v-show="showOriginText">{{'【' + originText + '】'}}</a>
<textarea class="replaceArea" ref="originTextInput" v-show="!showOriginText" @blur="recoverOriginText" type="text" v-model="originText" ></textarea>
<a @click="autoRename">➡️ ➡️ ➡️</a>
<a style='color:#00947e' @click="changeReplaceText" v-show="showReplaceText">{{'【' + replaceText + '】' }}</a>
<textarea class="replaceArea" ref="replaceTextInput" v-show="!showReplaceText" @blur="recoverReplaceText" type="text" v-model="replaceText" ></textarea>
</div>
</p>
<button @click="loadData">{{data.length > 0 ? '重载数据' : '加载数据'}}</button>
<button @click="postRename" v-show="musicList.length > 0"> 确定修改 </button>
</br>
<table v-show="data.length > 0">
<thead><tr><th></th><th>原始文件名</th><th>修改后文件名</th></tr></thead>
<tbody id="priate_script_table">
<tr v-for="(item, index) in data" :key="index">
<td><input class="checkMusicBox" v-model="musicList" :value='item' type="checkbox" :disabled="item.replace == item.origin"></td>
<td><a @click="originText = item.origin" style='color:#337ab7'>{{item.origin}}</a></td>
<td><a v-show="!item.isChanging" @click="manualRename(item)" style='color:#C01D07'>{{item.replace}}</a><textarea class="replaceArea" :ref="item.id" @blur="modifyReplace(item)" v-show="item.isChanging" v-model="item.replace"></textarea></td>
</tr>
</tbody>
</table>
</div>
`
        GM_addStyle(`
#priate_script_div{
font-size : 15px;
position: fixed;
background-color: rgb(240, 223, 175);
color : #660000;
text-align : center;
padding: 10px;
z-index : 9999;
border-radius : 20px;
border:2px solid #660000;
font-weight: 300;
text-stroke: 0.5px;
box-shadow: 5px 15px 15px rgba(0,0,0,0.4);
user-select : none;
-webkit-user-select : none;
-moz-user-select : none;
-ms-user-select:none;
}
#priate_script_div:hover{
box-shadow: 5px 15px 15px rgba(0,0,0,0.8);
transition: box-shadow 0.3s;
}

#priate_script_div a{
margin-bottom: 2px !important;
}
.priate_script_hide{
padding: 0 !important;
border:none !important;
}
a{
cursor : pointer;
text-decoration : none;
}
/*表格样式*/
#priate_script_div table{
text-align: center;
// border:2px solid #660000;
margin: 5px auto;
padding: 2px;
border-collapse: collapse;
display: block;
height : 400px;
overflow-y: scroll;
}
/*表格框样式*/
#priate_script_div td{
border:2px solid #660000;
padding: 8px 12px;
max-width : 300px;
word-wrap : break-word;
}
/*表头样式*/
#priate_script_div th{
border:2px solid #660000;
padding: 8px 12px;
font-weight: 300;
-webkit-text-stroke: 0.5px;
text-stroke: 0.5px;
}

/*脚本按钮样式*/
#priate_script_div button{
display: inline-block;
border-radius: 4px;
border: 1px solid #660000;
background-color: transparent;
color: #660000;
text-decoration: none;
padding: 5px 10px;
margin : 5px 10px;
font-weight: 300;
-webkit-text-stroke: 0.5px;
text-stroke: 0.5px;
}
/*脚本按钮悬浮样式*/
#priate_script_div button:hover{
cursor : pointer;
color: rgb(240, 223, 175);
background-color: #660000;
transition: background-color 0.2s;
}
/*设置区域 p 标签*/
#priate_script_setting{
user-select : none;
-webkit-user-select : none;
-moz-user-select : none;
-ms-user-select:none;
}
/*swal按钮*/
.swal-button--1{
background-color: #FFFAEB !important;
color: #946C00;
}
.swal-button--2{
background-color: #ebfffc !important;
color: #00947e;
}
.swal-button--3{
background-color: #ECF6FD !important;
color: #55ACEE;
}
.checkMusicBox{
transform: scale(1.7,1.7);
cursor: pointer;
}
.replaceArea{
height : 100%;
width : 100%;
background-color: #fff;
border:1px solid #000000;
padding: 4px;
border-radius: 4px;
}
.replaceInput{
height : 100%;
width : 40%;
background-color: #fff;
border:1px solid #000000;
padding: 4px;
border-radius: 4px;
}
`);
        document.querySelector("html").appendChild(priate_script_div)
        var setting = GM_getValue('priate_script_bdwp_data')
        document.getElementById("priate_script_div").style.left = (setting.left || 20) + "px";
        document.getElementById("priate_script_div").style.top = (setting.top || 100) + "px";
    }

    function dragFunc(id) {
        var Drag = document.getElementById(id);
        var setting = GM_getValue('priate_script_bdwp_data')
        Drag.onmousedown = function(event) {
            var ev = event || window.event;
            event.stopPropagation();
            var disX = ev.clientX - Drag.offsetLeft;
            var disY = ev.clientY - Drag.offsetTop;
            document.onmousemove = function(event) {
                var ev = event || window.event;
                setting.left = ev.clientX - disX
                Drag.style.left = setting.left + "px";
                setting.top = ev.clientY - disY
                Drag.style.top = setting.top + "px";
                Drag.style.cursor = "move";
                GM_setValue('priate_script_bdwp_data', setting)
            };
        };
        Drag.onmouseup = function() {
            document.onmousemove = null;
            this.style.cursor = "default";
        };
    };

    function unDragFunc(id) {
        var Drag = document.getElementById(id);
        Drag.onmousedown = function(event) {
            var ev = event || window.event;
            event.stopPropagation();
        };
        Drag.onmouseup = function() {};
        Drag.onmousemove = function() {};
    };

    //初始化脚本设置
    initSetting()
    //注入脚本div
    injectDiv()

    function getToken() {
        return document.querySelector(".nd-main-list, .nd-new-main-list").__vue__.yunData.bdstoken;
    }

    function getLogid() {
        let ut = unsafeWindow.require("system-core:context/context.js").instanceForSystem.tools.baseService;
        return ut.base64Encode(base.getCookie("BAIDUID"));
    }

    function getPath() {
        var nowPath = location.href.match(/path=(.+?)(?:&|$)/);
        var pathValue;
        if (nowPath)
            pathValue = decodeURIComponent(nowPath[1]);
        else
            pathValue = "/";
        if (pathValue.charAt(0) !== "/")
            pathValue = "/" + pathValue; // 补齐路径前缀斜杠
        if (pathValue.charAt(pathValue.length - 1) !== "/")
            pathValue += "/"
        return pathValue
    }

    function reloadList() {
        document.querySelector(".nd-main-list, .nd-new-main-list").__vue__.reloadList();
    }

    // 处理数据等逻辑
    var vm = new Vue({
        el: '#priate_script_div',
        data: {
            version: "1.0.3",
            setting: GM_getValue('priate_script_bdwp_data'),
            data: [],
            musicList: [],
            showOriginText: true,
            showReplaceText: true,
            originText: "需要替换的内容",
            replaceText: "",
            path: '/',
            isDrag: true,
        },
        methods: {
            loadData() {
                const path = getPath()
                this.path = path
                const all_tr = document.querySelectorAll('table.wp-s-pan-table__body-table tbody>tr');
                var result = [];
                var _this = this
                all_tr.forEach((item) => {
                    const type = item.querySelector('img[alt]') ? item.querySelector('img[alt]').getAttribute('alt') : 'unknow'
                    if (!item.querySelector('a')) return
                    const music = {
                        id: item.getAttribute('data-id'),
                        origin: item.querySelector('a').getAttribute('title'),
                        replace: item.querySelector('a').getAttribute('title'),
                        isChanging: false,
                        type,
                        isFolder: type == 'folder',
                    }
                    result.push(music)
                })
                // 如果仍未获取到数据
                if (result.length == 0) {
                    swal("未获取到数据,请确认此目录下有文件或文件夹!", {
                        icon: "error",
                        buttons: false,
                        timer: 3000,
                    });
                }
                this.data = result
                this.musicList = []
            },
            clearData() {
                if (this.data.length == 0) swal(`已经是最简形态了!`, {
                    buttons: false,
                    timer: 2000,
                });
                this.data = []
                this.musicList = []
            },
            openDonate() {
                showDonate()
            },
            async manualRename(item) {
                this.unDrag()
                item.isChanging = true
                await Sleep(0.01)
                this.$refs[item.id][0].focus();
            },
            modifyReplace(item) {
                this.drag()
                item.isChanging = false
                if (item.replace != item.origin) {
                    if (!this.musicList.find(el => el.id == item.id)) {
                        this.musicList.push(item)
                    }
                } else {
                    this.musicList = this.musicList.filter(el => el.id != item.id)
                }

            },
            autoRename() {
                var _this = this
                const origin = this.originText
                const replace = this.replaceText
                var hasChanged = false
                var hasEmpty = false
                this.data.forEach(item => {
                    item.replace = item.replace.replace(origin, replace)
                    if (item.replace !== item.origin) {
                        hasChanged = true
                    }
                    if (item.replace == "") {
                        hasEmpty = true
                        item.replace = item.origin
                    }
                    _this.modifyReplace(item)
                })
                if (!hasChanged) swal(`没有匹配到任何需要修改的文件!`, {
                    icon: "error",
                    buttons: false,
                    timer: 3000,
                });
                if (hasEmpty) swal(`替换后某个文件名为空!`, {
                    icon: "error",
                    buttons: false,
                    timer: 3000,
                });
            },
            async postRename() {
                var _this = this
                const token = getToken()
                // const logid = getLogid()
                const data = this.musicList.map(item => {
                    return {
                        id: item.id,
                        path: `${_this.path}${item.origin}`,
                        newname: item.replace,
                    }
                })
                $.ajax(`https://pan.baidu.com/api/filemanager?async=2&onnest=fail&opera=rename&bdstoken=${getToken()}&clienttype=0&app_id=250528&web=1`, {
                    type: 'post',
                    data: {
                        filelist: JSON.stringify(data)
                    },
                    complete: function(res) {
                        const resp = res.responseJSON
                        if (resp['errno'] == 0) {
                            swal(`重命名已完成!\n如部分文件显示未修改请点击 ♻️ 按钮手动刷新!`, {
                                icon: "success",
                                buttons: false,
                                timer: 3000,
                            });
                        } else {
                            swal(`重命名失败!`, {
                                icon: "error",
                                buttons: false,
                                timer: 3000,
                            });
                        }
                        _this.clearData()
                    }
                });
                await Sleep(3)
                reloadList()
            },
            switchDrag() {
                if (this.isDrag) {
                    this.unDrag()
                    swal(`悬浮窗已固定`, {
                        buttons: false,
                        timer: 2000,
                    });
                } else {
                    this.drag()
                    swal(`悬浮窗可以拖动了`, {
                        buttons: false,
                        timer: 2000,
                    });
                }
            },
            unDrag() {
                this.isDrag = false
                unDragFunc("priate_script_div")
            },
            drag() {
                this.isDrag = true
                dragFunc("priate_script_div")
            },
            async changeOriginText() {
                this.unDrag()
                this.showOriginText = false
                await Sleep(0.01)
                this.$refs.originTextInput.focus();
            },
            async changeReplaceText() {
                this.unDrag()
                this.showReplaceText = false
                await Sleep(0.01)
                this.$refs.replaceTextInput.focus();
            },
            recoverOriginText() {
                this.drag()
                this.showOriginText = true
            },
            recoverReplaceText() {
                this.drag()
                this.showReplaceText = true
            },
            recoverText() {
                reloadList()
            },
            smartRename() {
                var _this = this
                var hasChanged = false
                var hasEmpty = false
                var lengthStatistics = {}
                var maxLength = 0
                this.data.forEach(item => {
                    const suffix = item.origin.split('.').length > 1 ? '.' + item.origin.split('.')[item.origin.split('.').length - 1] : ''
                    item.numArr = item.origin.replace(suffix, '').match(/\d+/g) || []
                    // 寻找出现次数最多的匹配项
                    if (lengthStatistics[item.numArr.length] == undefined) lengthStatistics[item.numArr.length] = 1
                    else lengthStatistics[item.numArr.length] += 1
                })
                for (var i in lengthStatistics) {
                    maxLength = lengthStatistics[i] > maxLength ? i : maxLength
                }
                var seq = -1
                for (var index = 0; index < maxLength; index++) {
                    const tempList = this.data.map(item => {
                        if (item.numArr.length == maxLength) {
                            return item.numArr[index]
                        }
                    }).filter(l => l != undefined)
                    // 判断是否有重复元素
                    if (Array.from(new Set(tempList)).length == tempList.length) {
                        seq = index
                        break
                    }
                }
                if (seq < 0) return swal(`智能重命名失败,找不到唯一的数字序号!`, {
                    icon: "error",
                    buttons: false,
                    timer: 3000,
                });
                this.data.forEach(item => {
                    if (item.numArr.length == maxLength) {
                        const suffix = item.origin.split('.').length > 1 ? '.' + item.origin.split('.')[item.origin.split('.').length - 1] : ''
                        item.replace = `${item.numArr[seq]}${suffix}`
                    }
                    if (item.replace !== item.origin) {
                        hasChanged = true
                    }
                    if (item.replace == "") {
                        hasEmpty = true
                        item.replace = item.origin
                    }
                    _this.modifyReplace(item)
                })

                if (!hasChanged) swal(`没有匹配到任何需要修改的文件!`, {
                    icon: "error",
                    buttons: false,
                    timer: 3000,
                });
                if (hasEmpty) swal(`替换后某个文件名为空!`, {
                    icon: "error",
                    buttons: false,
                    timer: 3000,
                });
            },
            todo() {
                swal(`🈲️🈲️🈲️ 此功能暂不可用,请等待版本更新 🔞🔞🔞`, {
                    buttons: false,
                    timer: 2000,
                });
            }
        },
        computed: {},
        mounted() {}
    })
    //设置div可拖动
    dragFunc("priate_script_div");
})();